2
\$\begingroup\$

If I have a Model that is drawn with a different effect occasionally, what is the typical approach to this?

Models have effects stored in each of their meshes, and you seem to be forced to use those.

Typically this is done:

foreach (ModelMesh mesh in model.Meshes)
{
    foreach (Effect effect in mesh.Effects)
    {
        effect.Parameters["World"].SetValue(world);
        // Other stuff related to this specific effect is done here.
    }
    mesh.Draw();
}

I want to be able to do this:

foreach (ModelMesh mesh in model.Meshes)
{
    myEffect.CurrentTechnique.Passes[0].Apply();
    mesh.Draw(); // Mesh will be drawn with "myEffect".
}

What are our options?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Shawn Hargreaves outlines the two options for changing which effect is used when rendering a model on his blog here.

The first option is purely a run-time option: iterate over all of the model.MeshParts and directly modify the ModelMeshPart.Effect property to the new effect. I haven't tried this but I would expect it to work.

The second, and more flexible option, is to use your own custom ModelProcessor to modify the effect that is compiled into each model. If you take this approach you can write your own Effect which has several techniques, each with different shaders, Switching shaders at run-time is then just a matter of changing which technique each effect in the model will use.

foreach (ModelMesh mesh in model.Meshes)
{
    foreach (Effect effect in mesh.Effects)
    {
        effect.CurrentTechnique = effect.Techniques["CreateShadowMap"];
        // Other stuff related to this specific effect is done here.
    }
    mesh.Draw();
}
...
foreach (ModelMesh mesh in model.Meshes)
{
    foreach (Effect effect in mesh.Effects)
    {
        effect.CurrentTechnique = effect.Techniques["DrawWithShadowMap"];
        // Other stuff related to this specific effect is done here.
    }
    mesh.Draw();
}
\$\endgroup\$
5
  • \$\begingroup\$ "The first option is purely a run-time option: iterate over all of the model.MeshParts and directly modify the ModelMeshPart.Effect property to the new effect. I haven't tried this but I would expect it to work." Actually he's doing that at compile time (in a ContentProcessor) and you can't do that at run-time as far as I know. I think what you're trying to say is that I can assign an effect to the model and then just pick whatever technique I want in that effect at run-time. That's true but doesn't answer the question of: how do I use different effects on the same model at run-time? \$\endgroup\$
    – Olhovsky
    Commented Mar 26, 2011 at 0:38
  • \$\begingroup\$ I tried the first option and you can modify the effect at run-time using code like foreach (var mesh in model.Meshes) { foreach (var part in mesh.MeshParts) { part.Effect = newEffect; } } As for the second approach, doesn't the ability to change the technique at run-time give you the same functionality as changing the effect if you write a single effect that exposes the original multiple effects as separate techniques? \$\endgroup\$ Commented Mar 27, 2011 at 16:05
  • \$\begingroup\$ Are you using XNA 4? part.Effect = newEffect; doesn't work because part.Effect has no setter. \$\endgroup\$
    – Olhovsky
    Commented Mar 27, 2011 at 23:30
  • \$\begingroup\$ Oh, nevermind, you're right, you CAN change the effect that way. Thanks! \$\endgroup\$
    – Olhovsky
    Commented Mar 27, 2011 at 23:35
  • \$\begingroup\$ Also good to know: the default effect is a BasicEffect. You can cast part.Effect to it and get some mesh part data from it - the two you probably need are DiffuseColor (which is object color actually) and the texture. \$\endgroup\$
    – Arek
    Commented Feb 1, 2016 at 22:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .