Custom effects on Model in XNA

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?

Shawn Hargreaves outlines the two options for changing which effect is used when rendering a model on his blog at http://blogs.msdn.com/b/shawnhar/archive/2006/12/07/rendering-a-model-with-a-custom-effect.aspx.

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)
{
// Other stuff related to this specific effect is done here.
}
mesh.Draw();
}
...
foreach (ModelMesh mesh in model.Meshes)
{
foreach (Effect effect in mesh.Effects)
{

• 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? – Phil Dunstan Mar 27 '11 at 16:05
• Are you using XNA 4? part.Effect = newEffect; doesn't work because part.Effect has no setter. – Olhovsky Mar 27 '11 at 23:30
• 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. – Arek Feb 1 '16 at 22:57