Using my own Effect?

Aug 27, 2008 at 2:54 AM
Hi, i've succesfuly used the XNAnimation Lib and i really like it but i need now to add my own effects so that i can have shadows and lighting in my game so i tryed the following 

 

Matrix[] Bones = mAnimationController.SkinnedBoneTransforms;

 



 

foreach (ModelMesh modelMesh in mPlayerModel.Model.Meshes)

 

{

 

foreach (Effect mEffect in modelMesh.Effects)

 

{

mEffect.CurrentTechnique = SimpleEffect.Techniques[

"Technique1"];

 

mEffect.Parameters[

"World"].SetValue(Bones[modelMesh.ParentBone.Index]);

 

mEffect.Parameters[

"View"].SetValue(CameraView);

 

mEffect.Parameters[

"Projection"].SetValue(CameraProjection);

 

}
}

but it didn't work as the model drew but some parts animated wrongly and it was totally mess i think this comes from the bone indexes but how can i fix this?

Coordinator
Aug 29, 2008 at 1:24 AM
Hi,

You need to change the effects that are set in the model, like this:

foreach (ModelMesh modelMesh in mPlayerModel.Model.Meshes)
modelMesh.Effect = YourDesiredEffect;


Aug 29, 2008 at 2:43 PM
well i've already done this,but the problem that i can't the right skin transform foreach bone so that i can pass the right world matrix for each bone.
Sep 3, 2008 at 10:26 AM
Hello.
I`ve tried also to use my own effect, but my modelMesh doesn`t have a Effect property that i can change and set to my effect.
Something I`m doing wrong?
Sep 30, 2008 at 12:54 PM
Hello there!
I like to render my Model through a toon effect!

First off all there is no modelMesh.Effect only modelMesh.Effects!The problem is that this property is read only!And also its a ModelEffectCollection...i just want to add one single effect!So how do u do this ashourism?btw. i'm workking with XNA 2.0 and the latest XNAnimation release!

If also tried:

foreach (ModelMesh meshes in BaseModel.Model.Meshes)
                {                   
                    foreach (ModelMeshPart parts in meshes.MeshParts)                      
                        parts.Effect = Toon;

                    meshes.Draw();
                }

But throws the exception that a normal Effect can't cast to an SkinnedModelBasicEffect :-/

Are the anyone who can help me?
Thanks anyway!





Oct 27, 2008 at 8:33 AM
Nobody knows?
Nov 30, 2008 at 1:23 PM

I needed to do this too and got it working. Here's what I did:

// load a shader file.
newMeshEffect = Program.CurrentGame.Content.Load<Effect>("Effects\\NewMeshEffect");

foreach (ModelMesh mesh in model.Meshes)
{
    for (int i = 0; i < mesh.MeshParts.Count; i++) 
    {
    // get the texture that the xnanimation content pipeline loaded for this mesh part
    Texture2D texture = mesh.MeshParts[i].Effect.Parameters["diffuseMap0"].GetValueTexture2D(); 
    // set our new effect - which clears the texture and values set by the pipeline
    mesh.MeshParts[i].Effect = meshEffect; 
    // set the texture of our new effect
    mesh.MeshParts[i].Effect.Parameters["diffuseMap0"].SetValue(texture);
    }
}

For the animations to work you need to pass the bone transforms to your shader - so you can't use BasicEffect. What I did is grab the xnanimation shader file and modified the Pixel Shader bits as needed. I used the SkinnedModelBasicEffect.cs.cs and SkinnedModelEffect.fx files in the xnanimation solution to work out what I needed to pass to the effect. Then I did the following when actually drawing the model...

foreach (ModelMesh mesh in _model.Model.Meshes)
{
    foreach
(Effect effect in mesh.Effects)
    {
        effect.Parameters["matW"].SetValue(world);
        effect.Parameters["matBones"].SetValue(_animationController.SkinnedBoneTransforms);
        effect.Parameters["matVP"].SetValue(viewMatrix * projectionMatrix);
        effect.Parameters["matVI"].SetValue(Matrix.Invert(viewMatrix));
        effect.Parameters["ambientLightColor"].SetValue(Vector3.One);
        effect.Parameters["material"].StructureMembers["diffuseColor"].SetValue(new Vector3(1f));
        effect.Parameters["diffuseMapEnabled"].SetValue(true); // you have to set this or it won't render your texture.
        effect.Parameters["lights"].Elements[0].StructureMembers["color"].SetValue(0.5f);
        effect.Parameters["lights"].Elements[0].StructureMembers["position"].SetValue(new Vector3(100, 100, 100));
        effect.CurrentTechnique = effect.Techniques["AnimatedModel_OneLightWithNormal"];
    }

    mesh.Draw();
}

There are other options you can set too, but these are the ones I used.

Hope that helps...

 

Apr 13, 2009 at 2:49 PM
I found this page while googling a bit and it seems like you have the same problem as me.
Basically I want to use custom shaders with XNAnimation. I've gotten it so far as to getting the shader to work but the animation the stops working.  

Right now Im doing this after trying to follow what avalpied wrote:

foreach (ModelMesh mesh in skinnedModel.Model.Meshes)
{
    for (int i = 0; i < mesh.MeshParts.Count; i++)
    {
         mesh.MeshParts[i].Effect = shaderEffect;
    }
    foreach (Effect effect in mesh.Effects)
    {
           effect.Parameters["matWorldViewProj"].SetValue(world *   Engine.Camera.View * Engine.Camera.Projection);   
           effect.CurrentTechnique = effect.Techniques["AmbientLight"];
    }

    mesh.Draw();
}

And the shader is working but there is no animation. Avalpied mentioned that one needs to pass the bone transforms to my shader but I have no idea how to do that or what to do with them in the shader. Any clues?
Apr 16, 2009 at 4:11 AM
hello stefan, I had the same problems with my project, you have two options as far as I know, or you implement your pixel shader in the SkinnedModelBasicEffect, or you add the Vertex shader into your shader. I added the vertex shader into my shader. If your shader uses a vertex shader, you would need to fuse them or (and Im not sure) have two vertex shaders in your Effect.

First of all, you need the structure insider your .fx

float4x3 matBones[80];

Now for the vertex shader, Ill show you the original code and the modified:

Original:
NormalDepthVertexShaderOutput NormalDepthVertexShader(VertexShaderInput input)
{
    NormalDepthVertexShaderOutput output;

    // Apply camera matrices to the input position.
    output.Position = mul(mul(mul(input.Position, World), View), Projection);
    
    float3 worldNormal = mul(input.Normal, World);

    // The output color holds the normal, scaled to fit into a 0 to 1 range.
    output.Color.rgb = (worldNormal + 1) / 2;

    // The output alpha holds the depth, scaled to fit into a 0 to 1 range.
    output.Color.a = output.Position.z / output.Position.w;
    
    return output;    
}

Now the modified one:

NormalDepthVertexShaderOutput NormalDepthVertexShader(VertexShaderInput input, float4 inBoneIndex :BLENDINDICES0, float4 inBoneWeight :BLENDWEIGHT0)
{
    NormalDepthVertexShaderOutput output;
    // Calculate the final bone transformation matrix
    float4x3 matSmoothSkin = 0;
    matSmoothSkin += matBones[inBoneIndex.x] * inBoneWeight.x;
    matSmoothSkin += matBones[inBoneIndex.y] * inBoneWeight.y;
    matSmoothSkin += matBones[inBoneIndex.z] * inBoneWeight.z;
    matSmoothSkin += matBones[inBoneIndex.w] * inBoneWeight.w;
    
    // Combine skin and world transformations
    float4x4 matSmoothSkinWorld = 0;
    matSmoothSkinWorld[0] = float4(matSmoothSkin[0], 0);
    matSmoothSkinWorld[1] = float4(matSmoothSkin[1], 0);
    matSmoothSkinWorld[2] = float4(matSmoothSkin[2], 0);
    matSmoothSkinWorld[3] = float4(matSmoothSkin[3], 1);
    matSmoothSkinWorld = mul(matSmoothSkinWorld, World);
    
    
    // Apply camera matrices to the input position.      
    output.Position = mul(mul(mul(input.Position, matSmoothSkinWorld), View), Projection);
    
    float3 worldNormal = float3(0,0,0); //mul(input.Normal, World);

    // The output color holds the normal, scaled to fit into a 0 to 1 range.
    output.Color.rgb = (worldNormal + 1) / 2;

    // The output alpha holds the depth, scaled to fit into a 0 to 1 range.
    output.Color.a = output.Position.z / output.Position.w;
    
    return output;    
}

The main change is in the input parameters, I just added the parameters that the skinnedmodelbasiceffect.fx uses.
Then you need to multiply some stuff with those input values, once again, those are from skinnedmodelbasiceffect.fx

And thats it, you need to modify your .fx to use the bones, I really dont know about shaders so I just tried this and it worked. Try doing something similar for your shader, and if you have any other questions, Ill be glad to try to help

Apr 16, 2009 at 8:45 PM
Thank you for the help that worked perfect! I can now pretty much use all my previously written shaders with XNAnimation. =)
Aug 16, 2010 at 11:46 PM

Sorry,i've exactly the same problem.

But i've done all the same things as in your post but can't make it work.

I've put in the Vertex Method the code you posted and added the parameters you post.

But it won't move.

Ps:maybe i'm going wrong setting matBones from C#.

            foreach (ModelMesh modelMesh in acube.Model.Meshes)
            {
                foreach (ModelMeshPart mmp in modelMesh.MeshParts)
                {
                    effect.Parameters["xWorld"].SetValue(worldAnimation);
                    effect.Parameters["xTexture"].SetValue(wallTexture);
                    if (effect.Functions == effect1Scene.Functions)
                    {
                        effect.Parameters["matBones"].SetValue(modelBones);
                    }
                    mmp.Effect = effect;
                }
                modelMesh.Draw(SaveStateMode.None);
            }

Where "modelBones" is taken from another animation with the same model (if i try to get Bones every time with SkinnedModelBasicEffect it give me error)

 

Thanks.

Aug 17, 2010 at 3:29 PM
about your problem with animations, my guess it's your "matBones" that's causing problems (though I haven't see your shader code yet). the way I get it is like this: Materials[part].Effect.Parameters["matBones"].SetValue(animationController.SkinnedBoneTransforms); but maybe I'm misunderstanding you and that is actually what you are also doing? if you could post your shadercode then that might help also.
Aug 17, 2010 at 3:58 PM
Thanks,this was the main problem (i'm using the XNA 3.0 Programming Recipes code for Shadow with Deferred rendering using multiple light). The only problem is that now animated model don't make shadow,but this is another topic :D Thanks again.