BasicEffect: a misnomer?

XNAThomas asks:

"I tried with all the models from the Spacewar starter kit and they seem to all have the same problem. The cockpit and engine exhausts never get the correct material/texture/lighting, although the fuselage looks fine."

Short answer: the bodies of the Spacewar ships have texture maps, but the cockpits do not. To render these correctly, your shader should disable texturing and just use the material color instead.

Longer answer: this provides a great example of why BasicEffect is actually not so basic after all! Shader permutations are the bane of graphics engine developers, and BasicEffect supports many permutations:

  • Simple shader applies one texture plus directional lighting
  • But what if there is no texture?
  • What if your model has vertex colors?
  • What if you want to disable lighting?
  • What if you want the lighting to be per-pixel rather than per-vertex?

Two texture modes (on, off) plus two vertex color modes (on, off) and three lighting modes (off, per-vertex, per-pixel) ends up requiring 2*2*3 = 12 different versions of the BasicEffect shader.

Not all of these shaders can be used with every model. If the shader does not match its input data, things will render incorrectly. You will get unpredictable results if:

  • Shader uses texturing, but no texture is set
  • Shader uses texturing, but the model does not contain texture coordinate data
  • Shader uses vertex colors, but the model does not contain vertex color data
  • Shader uses lighting, but the model does not contain normal data

What exactly do I mean by unpredictable? On some graphics cards the rendering will come out white, while on others it may be black. If you use the debug DirectX runtime, you will get an error. This is not a good place to be!

People using BasicEffect through the Content Pipeline are often unaware of these shader variations, because the build process takes care of them for you:

  • The pipeline always generates vertex normals, so you can safely turn on lighting even if your original model file did not include normal data.

  • Any time ModelProcessor encounters a BasicMaterialContent, it checks whether this material includes a texture, and automatically sets BasicEffect.TextureEnabled to match.

  • ModelProcessor warns if a material has a texture but the geometry that uses it does not include texture coordinate data.

  • Any time ModelProcessor encounters a BasicMaterialContent, it checks whether the geometry that uses this material includes vertex color data, and automatically sets BasicEffect.VertexColorEnabled to match.

Thanks to this processor magic, most models "just work" without you having to think too hard about it. But if you do stop to think, you will realize that what looks like a single BasicEffect is in fact 12 different shaders masquerading as one. This only works because the Content Pipeline has some smarts to examine your model data and automatically choose the right version of BasicEffect for each object.

If you use a custom shader instead of BasicEffect, the default content processors will no longer understand how to set it up for you. This leaves you with two choices:

  1. You could make your shader as complicated as BasicEffect, creating several versions to match different source data, and then write some code (either in a custom processor or while your game is loading) to choose the right shader for each object.

  2. Or you can simplify things by imposing restrictions on your source artwork. For instance many games decide something like "all our objects are going to be lit, and will be textured, and will not use vertex colors". This can make it dramatically easier to write and manage your shaders.

Comments (2)

  1. Rim says:

    I just happened to be thinking the BasicEffect indeed is a nifty feature in XNA earlier this week. I’m porting a game over from MDX and instead of having to wrestle with my old pile of custom shaders, the BasicEffect provides most of the techniques I needed for the game and they readily work on all models out of the box… well, most of the time 🙂

    The BasicEffect also allows for a bit of hackery that makes it quite useful in non-typical scenarios. For example, I abused the fogging to render a bunch of lines and points in specific colors, without having to include this color information in the vertices. It might not be the cleanest little hack, but it beats wrestling with the TextureStageStates in MDX or having to write a custom shader for something simple like this.

    Hurrah for BasicEffect!

  2. Andy says:

    Googling around for some answers I came across this and thought I would add the history from when I wrote the SpaceWar sample – this was well before XNA was announced, let alone released.

    Back then there was no BasicEffect – there was a custom shader for every part of SpaceWar. The cockpit needed to be partially transparent so we used the texture as an alpha map and just picked up the vertex colors to tint it. Since it was a custom shader this was pretty easy to implement.

Skip to main content