Transitions part three: stencil swipes

Originally posted to Shawn Hargreaves Blog on MSDN, Thursday, May 17, 2007

Remember the original Star Wars films? (not the more recent episodes: I refuse to talk about those :-)

Remember how they transition from one scene to another, using a circular swipe where one image gradually zooms up over the top of another?

That style of transition is pleasantly easy to implement using the stencil buffer.

Stencil is usually an 8 bit integer value, and is attached to each pixel in addition to the usual color and depth values. You can set renderstates to control how values are written into the stencil buffer while drawing graphics, and also to specify that graphics should only be drawn in areas where the existing stencil values meet specified conditions. This functionality can be used for all kinds of interesting effects.

The first step in using stencil is to make sure you actually have some stencil bits included in your depth buffer format. Add this line to your Game constructor:

    graphics.PreferredDepthStencilFormat = DepthFormat.Depth24Stencil8;

Next, draw the screen you are transitioning away from exactly as normal.

Now we are going to draw a swipe mask into the stencil buffer. Set these renderstates to write 1's into the stencil buffer:

    device.RenderState.StencilEnable = true;
    device.RenderState.StencilFunction = CompareFunction.Always;
    device.RenderState.StencilPass = StencilOperation.Replace;
    device.RenderState.ReferenceStencil = 1;

Also, set these states to disable drawing to the regular color buffer:

    device.RenderState.AlphaBlendEnable = true;
    device.RenderState.SourceBlend = Blend.Zero;
    device.RenderState.DestinationBlend = Blend.One;

Now you can draw whatever kind of mask shape you like into the stencil buffer. You could create a texture that has a circle in its alpha channel, something like this:

 

Animate this gradually zooming up to fill the screen. You won't see anything visible when you draw it, because you turned off output to the color buffer, but a circular swipe mask will have been written to the stencil buffer.

Finally, we can use this stencil data to implement our transition. Reset the alpha blending state to something sensible, and set these stencil states to only accept pixels where there is a 1 in the stencil buffer:

    device.RenderState.StencilEnable = true;
    device.RenderState.StencilFunction = CompareFunction.Equal;
    device.RenderState.ReferenceStencil = 1;

Now draw your second screen (the one you are transitioning toward) and you will see that it only appears in the areas where you previously drew the circle mask. A huge number of different transition effects can be achieved by drawing different animating patterns into the stencil buffer.

At the end of all this, make sure you turn stencil back off again, to avoid messing up drawing at the start of the next frame!

Blog index   -   Back to my homepage