locked
I want to use a simple fx shader on a simple loaded model

    Question

  • What I want to do seems very simple to me. I want to do this -

    Load a 3D model using ContentManager.Load<Model>(...)

    Load a shader Effect from a .fx file using ContentManager.Load<Effect>(...)

    Render the 3D model using the shader from .fx file.

    Can anyone give an example of this that is as straigh forward as humanly possible? It does not seem like this should be a difficult thing to do, but I have no idea since I've never used shaders.

    Also, if anyone has a simple .fx file I can use to test my code, that would be great!

    I'd love to give my Buttermilk game / GUI engine the power of shaders!

    Thank you for reading!

    Friday, December 29, 2006 7:54 AM

Answers

  • simpleEffect.Begin();

    foreach (EffectPass pass in simpleEffect.CurrentTechnique.Passes)

    {

    pass.Begin();

    foreach (ModelMesh mesh in model.Meshes)

    {

    graphics.GraphicsDevice.Indices = mesh.IndexBuffer;

    for (int i = 0; i < mesh.MeshParts.Count; i++)

    {

    ModelMeshPart part = mesh.MeshParts [ i ];

    if (part.NumVertices > 0)

    {

    graphics.GraphicsDevice.VertexDeclaration = part.VertexDeclaration;

    graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, part.StreamOffset, part.VertexStride);

    graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, part.BaseVertex, 0,

    part.NumVertices, part.StartIndex, part.PrimitiveCount);

    }

    }

    }

     

    pass.End();

    }

    simpleEffect.End();

     

    Friday, December 29, 2006 8:28 AM
  • Looks like you've got it sorted out.  I put together a really simple demo that should compile and run out of the box in case anything is still unclear:

    http://www.georgemcbay.com/xna/SimpleEffectDemo.zip

     

    It only loads one model and displays it.  The shader is very simple, it just does basic fullbright texture mapping with no lighting or anything else. 

     

    Friday, December 29, 2006 11:18 AM

All replies

  • simpleEffect.Begin();

    foreach (EffectPass pass in simpleEffect.CurrentTechnique.Passes)

    {

    pass.Begin();

    foreach (ModelMesh mesh in model.Meshes)

    {

    graphics.GraphicsDevice.Indices = mesh.IndexBuffer;

    for (int i = 0; i < mesh.MeshParts.Count; i++)

    {

    ModelMeshPart part = mesh.MeshParts [ i ];

    if (part.NumVertices > 0)

    {

    graphics.GraphicsDevice.VertexDeclaration = part.VertexDeclaration;

    graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, part.StreamOffset, part.VertexStride);

    graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, part.BaseVertex, 0,

    part.NumVertices, part.StartIndex, part.PrimitiveCount);

    }

    }

    }

     

    pass.End();

    }

    simpleEffect.End();

     

    Friday, December 29, 2006 8:28 AM
  • Thanks a lot.

    It works perfect.

     

    Regards

    Michael

    Friday, December 29, 2006 8:59 AM
  • It seems to work on mine too, but I'm not entirely sure if it's working right or not. I need a simpler fx shader file to use.

    Thanks for the truly excellant snippet of code!

    Friday, December 29, 2006 10:22 AM
  • Yes, this absolutely does work!

    Big big big big thanks!!!

    Friday, December 29, 2006 10:45 AM
  • Looks like you've got it sorted out.  I put together a really simple demo that should compile and run out of the box in case anything is still unclear:

    http://www.georgemcbay.com/xna/SimpleEffectDemo.zip

     

    It only loads one model and displays it.  The shader is very simple, it just does basic fullbright texture mapping with no lighting or anything else. 

     

    Friday, December 29, 2006 11:18 AM
  • Very very useful :)

    One thing I don't understand clearly are the Effect.Paremeters[""] values. Do the parameter values change for each type of shader? Are there common parameters among most HLSL shaders? If so, where does one find a list, and what are the main Parameters that need to be dealt with to get a shader working properly?

    Thank you again!

    Friday, December 29, 2006 2:46 PM
  • There is no standard set of parameters ... they are defined in the shader.  In George's simple effect demo above, it is these 3 lines:

    float4x4 viewProjection;
    float4x4 world;
    texture objectTexture;

    The number and type of parameters entirely depends on what kind of effect you're trying to achieve :-)
    Friday, December 29, 2006 6:06 PM
  • Yes, what Joel said is correct, there is no standard set of parameters.  The parameters you set just have to map to global variables defined within the Effects file and the types should match (so if you define a float4x4 in the shader, you should pass it a Matrix with Parameter[""].SetValue(), or if its a float in the shader, it should be a float in the C# code, etc.  If you pass a wrong type, you'll get a runtime exception from GSE that will make it very obvious.

    When you're rendering 3d data, you'll usually find some representation of the view, projection and/or world matricies being passed to the shader, either directly or pre-multiplied, but there is no standard name for them (it is whatever you define them as in the shader).  It is a good idea to follow your *own* standards for parameter names -- like if you have 5 rendering effect files that all work on meshes, have each one that needs the world matrix call it 'world', so you can just set the parameter on any model's effect without worrying about having to know exactly which effect you're using in the C# code each time you set the parameter.   You can also define multiple shaders in the same effects file as different techniques, which is a good idea if the shaders are logically related and use many of the same parameters.

    Friday, December 29, 2006 10:04 PM
  • You, sir, are an XNA god among men.

    Thanks!
    Sunday, December 31, 2006 2:08 PM
  •  gmcbay wrote:

    Looks like you've got it sorted out. I put together a really simple demo that should compile and run out of the box in case anything is still unclear:

    http://www.georgemcbay.com/xna/SimpleEffectDemo.zip

    It only loads one model and displays it. The shader is very simple, it just does basic fullbright texture mapping with no lighting or anything else.


    Thanks for including the sample project, it helped me get past some issues I was having with effects and models.  I do have one problem though, when I render the crate.x file everything looks fine but when I render my models they appear to have their faces inverted.  Do you know why your model would look fine but mine wouldnt?  When I use the mesh.Draw() function my models look fine.

    Thanks!
    Monday, January 01, 2007 8:40 PM
  • Ok, I figured out the problem.  The example you give does not use parent transforms to set the starting position offsets.  Since my model consists of two parts, a top layer and a bottom layer, and the top layer is 10 units higher on the z-axis, it was rendering them on top of one another instead of off-set as they are in 3dsmax.  When I added parent transformation code they display properly.  The inversion I was seeing was really me just seeing the inside of the bottom layer (which normally isnt possible.)

    The updated code I used:

    Matrix[] transforms = new Matrix[myModel[index].Bones.Count];
    myModel[index].CopyAbsoluteBoneTransformsTo(transforms);

    world = transforms[mesh.ParentBone.Index];
    world *= Matrix.CreateScale(scale);
    world *= Matrix.CreateRotationY(rot.X);
    world *= Matrix.CreateRotationY(rot.Y);
    world *= Matrix.CreateRotationY(rot.Z);
    world *= Matrix.CreateTranslation(trans);
    simpleEffect.Parameters["world"].SetValue(world);
    Monday, January 01, 2007 9:50 PM