I predict that DualTextureEffect will turn out to be the secret weapon in the armory of all the best looking Windows Phone games. It is efficient (only 7 vertex and 6 pixel shader instructions when not using fog), yet enables visually lush rendering techniques such as lightmaps and detail textures. For instance, the Harvest demo makes heavy use of DualTextureEffect.

DualTextureEffect samples from a pair of textures. Each has its own texture coordinates, so they can be independently aligned, tiled, rotated, etc. The textures are combined using Modulate2X blend mode:

output.rgb = Texture1.rgb * Texture2.rgb * 2;

output.a = Texture1.a * Texture2.a;

The easiest way to think about this operation is that the first texture defines the basic color of the object, which can then be adjusted by the second texture:

  • Where the second texture contains 50% grey, the color is unchanged
  • Where it is darker than 50%, the color is darkened
  • Where it is brighter than 50%, the color becomes brighter
  • If the second texture is not monochrome, the color is tinted accordingly

To use DualTextureEffect, you must:

  • Have two texture coordinate channels in your vertex data (both TexCoord0 and TexCoord1)
  • Set your model to use DualTextureEffect
  • Set the DualTextureEffect.Texture2 property
    • If you apply a multitexturing material in Max or Maya, you can export dual texture settings to FBX, and then when ModelProcessor.DefaultEffect is set to DualTextureEffect, it will automatically set up both textures for you
    • Or you can do this in a custom content processor (again see the Reach Graphics Demo DualTextureProcessor)
    • Or you can just manually set the Texture2 property at runtime



The idea behind lightmapping is simple. Instead of trying to compute lighting and shadows in realtime, you precompute them for an entire level, and store the results in one or more textures. These textures are uniquely mapped across the level, which means that every triangle gets its own unique area of the texture, with no tiling or texture reuse. Even with the largest textures that can fit in memory, the lightmap data typically ends up quite low resolution, but when you use DualTextureEffect to combine this with the base textures (which are usually tiled and thus appear to have higher resolution), the results can be stunning.

The big advantage of lightmaps is that because everything is precomputed, even the most complex lighting effects (soft shadows, radiosity, large numbers of lights, area lights, gobos, etc) can be rendered using even the weakest GPU hardware. Who cares if your crazy photon mapping algorithm takes hours on a high end workstation, when at runtime this will require just a simple texture fetch to display?

Of course the disadvantage is that because everything is precomputed, lightmaps only work for static models and static lighting. They are no use for things that animate.

Some people write their own code for generating lightmaps, and many game engines have lightmap generators built into their level editors. But the easiest way to get started is using a 3D modeling program: here are tutorials on how to render lightmaps with Max or Maya.

In the Reach Graphics Demo, our DualTextureEffect demo uses these simple base textures:


Combined with this lightmap, which we created in Maya:


The result is:



Detail Textures

I wrote about detail textures a while ago, so won’t repeat the details here. Detail textures are a valuable technique for high resolution Xbox games, but less useful when targeting smaller phone screens.

The interesting thing is that from a runtime perspective, lightmaps and detail textures are exactly the same thing! The only difference is in the artwork. Lightmaps use a texture that is stretched just once over the world (so they provide very coarse color information), and are typically generated by programs, while detail textures are tiled many times (so they provide very fine color information), and are typically drawn by artists. But they use the exact same data formats and shader code, so once you set up a game to use DualTextureEffect, artists can choose whether they want lightmaps or detail textures just by changing their models!

Comments (15)

  1. Luke says:

    Hey Shawn,

    Quick one for anyone using DualTextureEffects and the Overdraw XRay render mode that you've talked about in the past (Think it was in your WP7 GDC/MIX PPT?) to visual measure the overdraw… make sure that you set your DualTextureEffect.DiffuseColor value to be 1/2 of what you set it to be on other effects (ie. 0.1, 0.1, 0.1 instead of 0.2, 0.2, 0.2 etc.) or you'll think that your DualTextureEffects are giving you double overdraw. This is obviously due to the additional *2 multiply that you do to the RGB component in the shader.

    That one had me stumped for a bit, thinking that you guys were actually using 2 passes for your DualTextureEffect instead of a shader-based multi-texture 😉

  2. Allan Chaney says:

    This is all well and good but for 3D mobile game development, I would really like to see MS collaborate with the Unity team to get WP7 support by Unity.  Afterall, you can use Unity for iPhone, Ipod, Ipad and Android.  I'm not sure why any Indie developer would go through the trouble of developing a 3D game engine in XNA just for WP7 when they can have the kind of cross platform capabilities made avilable by Unity on other platforms.  It just makes more business sense…that is if you are going for a 3D game.

  3. Jay says:

    @Allan:  Interesting.  You could ask Unity if they are planning (or even considering) a port to WP7 (or Xbox for that matter).  But, that's a completely different topic, and likely requires more expertise/knowledge than I have to wrangle successfully.

    Looks like you also started an interesting discussion in the XNA forums.  Seems like a good start for folks who want more detail: forums.xna.com/…/357737.aspx

  4. Roger Sall says:

    How to make it on PC,not WINDOWS MOBILE?

  5. Artii says:

    I just wanted to ask if say the new built in effects are usable in 2D?

  6. ShawnHargreaves says:

    2D and 3D are really the same thing as far as the GPU is concerned. 2D is just 3D with an orthographic projection matrix, so any code that works in 3D, you can also use in 2D.

    If you mean specifically 2D using SpriteBatch, that will work with any effects that can support the SpriteBatch vertex data format (position, color, and texture coordinate). That rules out DualTexture (which requires two texture coordinates), EnvironmentMapEffect (which requires normals) and SkinnedEffect (which requires both normals and skinning data) but you could use AlphaTestEffect, or BasicEffect as long as you configure it not to want normals.

  7. Artii says:

    Thanks for the quick reply .I started building a 2D game engine a while ago cant say i am quite good with at xna yet but went through to even adding some customs shaders then decided to port the project to windwos phone and,bummer, turns out it doesnt have support for custom shaders ,so was looking for ways to implement some of the effects i created to use  basic effect or something because it was the only way to crete effects on windows phone as i understand so kinda strugling on how to make it work .For examle not quite sure how to build, say ,a negative effect or whether it's even possible .

  8. Artii says:

    Just want to know if it's possible or not,so i know if i should start lookinginto this or not thanks in advance

  9. Artii says:

    K never mind i figured it out

  10. Phil says:

    Would it be possible to use detail textures and lightmaps simultaneously?

  11. ShawnHargreaves says:

    > Would it be possible to use detail textures and lightmaps simultaneously?

    DualTextureEffect, as ike the name suggests, only supports two textures at a time.

    To combine three or more textures, you could use a custom shader (if you are targetting Windows or Xbox rather than Windows Phone), or you could use multiple rendering passes.

  12. akira32 says:

    I cannot get the Texture2 in Content Processor. I had calculated light map in 3ds Max.

    Do you have any idea?


       class DualTextureProcessor : ModelProcessor


           protected override MaterialContent ConvertMaterial(MaterialContent material, ContentProcessorContext context)


               DualTextureMaterialContent dual = new DualTextureMaterialContent();

               dual.Texture = ((BasicMaterialContent)material).Texture;

               // Add the second lightmap texture.

    //dual.Texture2 = new ExternalReference<TextureContent>("Box01LightingMap.tga");

               dual.Texture2 =material.Textures["Texture2"];

               return base.ConvertMaterial(dual, context);



  13. David says:

    Every search I've done while trying to implement this in the past 8 hours or so of work has led back here, so maybe you can explain this.

    If I try to use DualTextureEffect with a vertex format with only one texture coordinate, it crashes (with no error report).

    If I try to make a custom vertex format with two texture coordinates, it raises an exception because two texture coordinates aren't allowed.

    So how can DualTextureEffect possibly be used?

  14. ShawnHargreaves says:

    David: DualTextureEffect requires two sets of texture coordinates, one per texture. This is absolutely possible so I think you must have misinterpreted what that exception was complaining about.

  15. David says:

    That's right thanks, I've got it now.  In every example I've looked at, vertex declaration has 0 as the final argument for each vertex element (and the automatic help could best be described as vague), so I've never really known what that final argument was for.  I guessed that argument must mean something, so I tried changing the 0 to a 1 for the second texture coordinate, which has solved the problem – my vertex declaration now happily accepts two texture coords.

    I have a simple demo here, if anyone's having similar trouble using DualTextureEffect with UserPrimitives.  It uses DualTextureEffect with a rendertarget to draw textured text.


Skip to main content