Transitions part three: stencil swipes

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!

Comments (10)

  1. Ultrahead says:

    It’s been a while since I last posted comments on your blog Shawn. This part is the best of the series on transitions -so far. It’s got my five. Concise, accurate and practical. Thanks for the link to the SB tuto -I missed that one when browsing the nVidia site.

    BTW, the recent episodes of SW suck. Did you notice that there was more advanced technology in the Universe before the time where almost all of the Jedis where exterminated? Battle robots and droids, faster ships, and racing pods, etc. … I know, I know … you don’t want to talk about that …

    So we have -please correct me if I forget any, vertex buffer, index buffer, color/pixel buffer, depth/z buffer, texture buffer(if that is the name), back buffers (for swap chains) and pages. Does DX10 introduce any new kind of buffer?

  2. ShawnHargreaves says:

    DX10 added a constant buffer type: I think that’s the only new one.

  3. Ultrahead says:

    Found it! => "Direct3D 10 introduced a new buffer for supplying shader constants. It is called a shader-constant buffer. Conceptually, it looks just like a vertex buffer).

    To create a shader-constant buffer, specify the constant-buffer bind flag (D3D10_BIND_CONSTANT_BUFFER). Once created, read the buffer using the Load (Direct3D 10 HLSL) intrinsic function. Each shader stage allows up to 15 slots for shader-constant buffers; each buffer can hold up to 4096 constants."

  4. zygote says:

    Nice work Shawn. This article should really help people looking to understand how to use the stencil buffer effectively 🙂


  5. jsedlak says:

    Thanks for the sample Shawn! I wrote up a quick sample that applies it to a progress bar.

  6. For the ultimate in crazy transition effects, render-to-texture is your friend. Setting this up is pretty

  7. Spiro Gulgas says:

    There Really Is no Limit on the effects in Stenciling… Mirrors, Shadows… Stuff we use Shaders and Shadow-Maps For… Great Tutorial!

  8. Sorry I’m late to the party, I just started playing with stenciling.  I really like your post!  One difficulty I encountered was that I didn’t realize I needed to use the AlphaTestEnable render state to write my circular mirror to my stencil buffer (because AlphaBlendEnable is already being used to disable rendering to the color buffer).  If there is another/better way to write non-rectangular values to the stencil buffer I’d really like to know!

  9. Andrew says:

    I was wondering if anyone has a sample of this in action. I’m trying to create a light effect in my game that shows only areas in the game visible inside a circle of light. I’m not sure exactly how I implement this technique, and since this is a rather out of date post I was wondering if anyone had anything more recent.

  10. Jesús Bosch says:


    How do we do this using XNA4?


Skip to main content