Contents

Creating a Stencil Buffer

Configuring the Stenciling State

Creating Effects

Configuring the Stenciling State


You control the various settings for the stencil buffer using the IDirect3DDevice7::
SetRenderState method. Listing 2 shows the stencil-related members of the D3DRENDERSTATETYPE enumerated type.

      These are the definitions for the stencil-related render states:

The D3DSTENCILOP enumerated type describes the stencil operations for the D3DRENDERSTATE_STENCILFAIL, D3DRENDERSTATE_STENCILZFAIL, and D3DRENDERSTATE_STENCILPASS render states. Here's the definition of D3DSTENCILOP:

  typedef enum _D3DSTENCILOP {
      D3DSTENCILOP_KEEP                    = 1,
      D3DSTENCILOP_ZERO                    = 2,
      D3DSTENCILOP_REPLACE                 = 3,
      D3DSTENCILOP_INCRSAT                 = 4,
      D3DSTENCILOP_DECRSAT                 = 5,
      D3DSTENCILOP_INVERT                  = 6,
        D3DSTENCILOP_INCR                    = 7,
      D3DSTENCILOP_DECR                    = 8,
      D3DSTENCILOP_FORCE_DWORD             = 0x7fffffff
  } D3DSTENCILOP;

      These members serve the following purposes:

Let's walk through some code that uses the stencil buffer while rendering a scene. This code is from a sample that shows how to draw shadows. For now, don't worry about how all this code generates shadows-the algorithm is described later in the chapter.

The shadow-rendering code starts out by disabling the depth buffer and enabling the stencil buffer:

    //--------------------------------------------------
    // Name: RenderShadow
    // Desc:
    //------------------------------------------------
    HRESULT CMyD3DApplication::RenderShadow()
    {
        // Turn off depth buffer and turn on
           stencil buffer.
        m_pd3dDevice->SetRenderState(
                           D3DRENDERSTATE_ZWRITEENABLE,
                                     FALSE );
        m_pd3dDevice->SetRenderState(
                           D3DRENDERSTATE_STENCILENABLE,
                                     TRUE );

Next the code sets the comparison function that performs the stencil test by calling the IDirect3DDevice7::SetRenderState method and setting the first parameter to D3DRENDERSTATE_STENCILFUNC. The second parameter is set to a member of the D3DCMPFUNC enumerated type. In this code, we want to update the stencil buffer everywhere a primitive is rendered, so we use D3DCMP_ALWAYS:

     //
    // Set up stencil comparison function,
       reference value, and masks.
    // Stencil test passes if ((ref & mask)
       cmpfn (stencil & mask))
    // is true.
    //
    m_pd3dDevice->SetRenderState(
                           D3DRENDERSTATE_STENCILFUNC,
                                 D3DCMP_ALWAYS );

In this sample, we don't want the stencil buffer to change if either the stencil buffer test or the depth buffer test fails, so we set the appropriate states to D3DSTENCILOP_KEEP:

     m_pd3dDevice->SetRenderState(
                          D3DRENDERSTATE_STENCILZFAIL,
                                  D3DSTENCILOP_KEEP );
     m_pd3dDevice->SetRenderState(
                          D3DRENDERSTATE_STENCILFAIL,
                                  D3DSTENCILOP_KEEP );

The settings in listing 3 are different depending on whether a 1-bit or a multibit stencil buffer is present. If the stencil buffer has only 1 bit, the value 1 is stored in the stencil buffer whenever the stencil test passes. Otherwise, an increment operation (either D3DSTENCILOP_INCR or D3DSTENCILOP_INCRSAT) is applied if the stencil test passes. At this point, the stencil state is configured and the code is ready to render some primitives.

________________________________________________________

Creating Effects