back  Return to list

GL_EXT_stencil_two_side
homeprevnext Name
  
    EXT_stencil_two_side  
  
homeprevnext Name Strings
  
    GL_EXT_stencil_two_side  
  
homeprevnext Contact
  
    Mark J. Kilgard, NVIDIA Corporation (mjk 'at' nvidia.com)  
  
homeprevnext Notice
  
    Copyright NVIDIA Corporation, 2001-2002.  
  
homeprevnext Status
  
    Implemented in CineFX (NV30) Emulation driver, August 2002.  
    Shipping in Release 40 NVIDIA driver for CineFX hardware, January 2003.  
  
homeprevnext Version
  
    Last Modified Date:  $Date: 2003/01/08 $  
    $Id: //sw/main/docs/OpenGL/specs/GL_EXT_stencil_two_side.txt#6 $  
  
homeprevnext Number
  
    268  
  
homeprevnext Dependencies
  
    Written based on the OpenGL 1.3 specification.  
  
    NV_packed_depth_stencil affects the definition of this extension.  
  
homeprevnext Overview
  
    This extension provides two-sided stencil testing where the  
    stencil-related state (stencil operations, reference value, compare  
    mask, and write mask) may be different for front- and back-facing  
    polygons.  Two-sided stencil testing may improve the performance  
    of stenciled shadow volume and Constructive Solid Geometry (CSG)  
    rendering algorithms.  
  
homeprevnext Issues
  
    Is this sufficient for shadow volume stencil update in a single pass?  
  
      RESOLUTION:  Yes.  
  
      An application that wishes to increment the stencil value for  
      rasterized depth-test passing fragments of front-facing polygons and  
      decrement the stencil value for rasterized fragments of depth-test  
      passing back-facing polygons in a single pass can use the following  
      configuration:  
  
        glDepthMask(0);  
        glColorMask(0,0,0,0);  
        glDisable(GL_CULL_FACE);  
        glEnable(GL_STENCIL_TEST);  
        glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);  
  
        glActiveStencilFaceEXT(GL_BACK);  
        glStencilOp(GL_KEEP,            // stencil test fail  
                    GL_KEEP,            // depth test fail  
                    GL_DECR_WRAP_EXT);  // depth test pass  
        glStencilMask(~0);  
        glStencilFunc(GL_ALWAYS, 0, ~0);  
  
        glActiveStencilFaceEXT(GL_FRONT);  
        glStencilOp(GL_KEEP,            // stencil test fail  
                    GL_KEEP,            // depth test fail  
                    GL_INCR_WRAP_EXT);  // depth test pass  
        glStencilMask(~0);  
        glStencilFunc(GL_ALWAYS, 0, ~0);  
  
        renderShadowVolumePolygons();  
  
      Notice the use of EXT_stencil_wrap to avoid saturating decrements  
      losing the shadow volume count.  An alternative, using the  
      conventional GL_INCR and GL_DECR operations, is to clear the stencil  
      buffer to one half the stencil buffer value range, say 128 for an  
      8-bit stencil buffer.  In the case, a pixel is "in shadow" if the  
      final stencil value is greater than 128 and "out of shadow" if the  
      final stencil value is 128.  This does still create a potential  
      for stencil value overflow if the stencil value saturates due  
      to an increment or decrement.  However saturation is less likely  
      with two-sided stencil testing than the conventional two-pass  
      approach because front- and back-facing polygons are mixed together,  
      rather than processing batches of front-facing then back-facing  
      polygons.  
  
      Contrast the two-sided stencil testing approach with the more  
      or less equivalent approach using facingness-independent stencil  
      testing:  
  
        glDepthMask(0);  
        glColorMask(0,0,0,0);  
        glEnable(GL_CULL_FACE);  
        glEnable(GL_STENCIL_TEST);  
  
        glStencilMask(~0);  
        glStencilFunc(GL_ALWAYS, 0, ~0);  
  
        // Increment for front faces  
        glCullFace(GL_BACK);  
        glStencilOp(GL_KEEP,   // stencil test fail  
                    GL_KEEP,   // depth test fail  
                    GL_INCR);  // depth test pass  
  
        renderShadowVolumePolygons();  
  
        // Decrement for back faces  
        glCullFace(GL_FRONT);  
        glStencilOp(GL_KEEP,   // stencil test fail  
                    GL_KEEP,   // depth test fail  
                    GL_DECR);  // depth test pass  
  
        renderShadowVolumePolygons();  
  
      Notice that all the render work implicit  
      in renderShadowVolumePolygons is performed twice with the  
      conventional approach, but only once with the two-sided stencil  
      testing approach.  
  
    Should there be just front and back stencil test state, or should  
    the stencil write mask also have a front and back state?  
  
      RESOLUTION:  Both the stencil test and stencil write mask state  
      should have front and back versions.  
  
      The shadow volume application for two-sided stencil testing does  
      not require differing front and back versions of the stencil write  
      mask, but we anticipate other applications where front and back  
      write masks may be useful.  
  
      For example, it may be useful to draw a convex polyhedra such that  
      (assuming the stencil bufer is cleared to the binary value 1010):  
  
      1) front-facing polygons that pass the depth test set stencil bit 0  
  
      2) front-facing polygons that fail the depth test zero stencil bit 1  
  
      3) back-facing polygons that pass the depth test set stencil bit 2  
  
      4) back-facing polygons that fail the depth test zero stencil bit 3  
  
      This could be accomplished in a single rendering pass using:  
  
        glStencilMask(~0);  
        glStencilClear(0xA);  
        glClear(GL_STENCIL_BUFFER_BIT);  
  
        glDepthMask(0);  
        glColorMask(0,0,0,0);  
        glDisable(GL_CULL_FACE);  
        glEnable(GL_STENCIL_TEST);  
        glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);  
  
        glActiveStencilFaceEXT(GL_BACK);  
        glStencilOp(GL_KEEP,      // stencil test fail  
                    GL_ZERO,      // depth test fail  
                    GL_REPLACE);  // depth test pass  
        glStencilMask(0xC);  
        glStencilFunc(GL_ALWAYS, 0x4, ~0);  
  
        glActiveStencilFaceEXT(GL_FRONT);  
        glStencilOp(GL_KEEP,      // stencil test fail  
                    GL_ZERO,      // depth test fail  
                    GL_REPLACE);  // depth test pass  
        glStencilMask(0x3);  
        glStencilFunc(GL_ALWAYS, 0x1, ~0);  
  
        renderConvexPolyhedra();  
  
    Is there a performance advantage to using two-sided stencil testing?  
  
      RESOLUTION:  It depends.  
  
      In a fill-rate limited situation, rendering front-facing primitives,  
      then back-facing primitives in two passes will generate the same  
      number of rasterized fragments as rendering front- and back-facing  
      primitives in a single pass.  
  
      However, in other situations that are CPU-limited,  
      transform-limited, or setup-limited, two-sided stencil testing can  
      be faster than the conventional two-pass face culling rendering  
      approaches.  For example, if a lengthy vertex program is executed  
      for every shadow volume vertex, rendering the shadow volume with  
      a single two-sided stencil testing pass is advantageous.  
  
      Often applications using stencil shadow volume techniques require  
      substantial CPU resources to determine potential silhouette  
      boundaries to project shadow volumes from.  If the shadow volume  
      geometry generated by the CPU is only required to be sent to the GL  
      once per-frame (rather than twice with the conventional technique),  
      that can ease the CPU burden required to implement stenciled shadow  
      volumes.  
  
    Should GL_FRONT_AND_BACK be accepted by glActiveStencilFaceEXT?  
  
      RESOLUTION:  No.  
  
      GL_FRONT_AND_BACK is useful when materials are being updated for  
      two-sided lighting because the front and back material are often  
      identical and may change frequently (glMaterial calls are allowed  
      within glBegin/glEnd pairs).  
  
      Two-sided stencil has no similiar performance justification.  
  
      It is also likely that forcing implementations to support this mode  
      would increase the amount of overhead required to set stencil  
      state, even for applications that don't use two-sided stencil.  
  
    How should the two-sided stencil enable operate?  
  
      RESOLUTION:  It should be modeled after the way two-sided lighting  
      works.  There is a GL_LIGHTING enable and then an additional  
      two-sided lighting mode.  Unlike two-sided lighting which is a  
      light model boolean, the two-sided stencil testing is a standard  
      enable named GL_STENCIL_TEST_TWO_SIDE_EXT.  
  
      Here is the pseudo-code for the stencil testing enables:  
  
        if (glIsEnabled(GL_STENCIL_TEST)) {  
          if (glIsEnabled(GL_STENCIL_TEST_TWO_SIDE_EXT) && primitiveType == polygon) {  
            use two-sided stencil testing  
          } else {  
            use conventional stencil testing  
          }  
        } else {  
          no stencil testing  
        }  
  
    How should the two-sided stencil interact with glPolygonMode?  
  
      RESOLUTION:  Primitive type is determined by the begin mode  
      so GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_QUAD_STRIP, GL_QUADS,  
      GL_TRIANGLE_FAN, and GL_POLYGON generate polygon primitives.  If the  
      polygon mode is set such that lines or points are rasterized,  
      two-sided stencil testing still operates based on the original  
      polygon facingness if stencil testing and two-sided stencil testing  
      are enabled.  
  
      This is consistent with how two-sided lighting and face culling  
      interact with glPolygonMode.  
  
homeprevnext New Procedures and Functions
  
    void ActiveStencilFaceEXT(enum face);  
  
homeprevnext New Tokens
  
    Accepted by the <cap> parameter of Enable, Disable, and IsEnabled,  
    and by the <pname> parameter of GetBooleanv, GetIntegerv,  
    GetFloatv, and GetDoublev:  
  
        STENCIL_TEST_TWO_SIDE_EXT                 0x8910  
  
    Accepted by the <face> parameter of ActiveStencilFaceEXT:  
  
        FRONT  
        BACK  
  
    Accepted by the <pname> parameters of GetBooleanv, GetIntegerv,  
    GetFloatv, and GetDoublev:  
  
        ACTIVE_STENCIL_FACE_EXT                   0x8911  
  
homeprevnext Additions to Chapter 2 of the GL Specification (OpenGL Operation)
  
    None  
  
homeprevnext Additions to Chapter 3 of the GL Specification (Rasterization)
  
    None  
  
homeprevnext Additions to Chapter 4 of the GL Specification (Per-Fragment Operations and the Framebuffer)
  
 -- Section 4.1.5 "Stencil test"  
  
    Replace the first paragraph in the section with:  
  
    "The stencil test conditionally discards a fragment based on the  
    outcome of a comparison between the value in the stencil buffer at  
    location (xw,yw) and a reference value.  
  
    The test is enabled or disabled with the Enable and Disable commands,  
    using the symbolic constant STENCIL_TEST.  When disabled, the stencil  
    test and associated modifications are not made, and the fragment is  
    always passed.  
  
    Stencil testing may operate in a two-sided mode.  Two-sided stencil  
    testing is enabled or disabled with the Enable and Disable commands,  
    using the symbolic constant STENCIL_TEST_TWO_SIDE_EXT.  When stencil  
    testing is disabled, the state of two-sided stencil testing does  
    not affect fragment processing.  
  
    There are two sets of stencil-related state, the front stencil  
    state set and the back stencil state set.  When two-sided stencil  
    testing is enabled, stencil tests and writes use the front set of  
    stencil state when processing fragments rasterized from non-polygon  
    primitives (points, lines, bitmaps, image rectangles) and front-facing  
    polygon primitives while the back set of stencil state is used when  
    processing fragments rasterized from back-facing polygon primitives.  
    For the purposes of two-sided stencil testing, a primitive is still  
    considered a polygon even if the polygon is to be rasterized as  
    points or lines due to the current polygon mode.  Whether a polygon  
    is front- or back-facing is determined in the same manner used for  
    two-sided lighting and face culling (see sections 2.13.1 and 3.5.1).  
    When two-sided stencil testing is disabled, the front set of stencil  
    state is always used when stencil testing fragments.  
  
    The active stencil face determines whether stencil-related commands  
    update the front or back stencil state.  The active stencil face is  
    set with:  
  
      void ActiveStencilFace(enum face);  
  
    where face is either FRONT or BACK.  Stencil commands (StencilFunc,  
    StencilOp, and StencilMask) that update the stencil state update the  
    front stencil state if the active stencil face is FRONT and the back  
    stencil state if the active stencil face is BACK.  Additionally,  
    queries of stencil state return the front or back stencil state  
    depending on the current active stencil face.  
  
    The stencil test state is controlled with  
  
       void StencilFunc(enum func, int ref, uint mask);  
       void StencilOp(enum sfail, enum dpfail, enum dppass);"  
  
    Replace the third and second to the last sentence in the last  
    paragraph in section 4.1.5 with:  
  
    "In the initial state, stencil testing and two-sided stencil testing  
    are both disabled, the front and back stencil reference values are  
    both zero, the front and back stencil comparison functions are ALWAYS,  
    and the front and back stencil mask are both all ones.  Initially,  
    both the three front and the three back stencil operations are KEEP."  
  
 -- Section 4.2.2 "Fine Control of Buffer Updates"  
  
    Replace the last sentence of the third paragraph with:  
  
    "The initial state is for both the front and back stencil plane mask  
    to be all ones.  The clear operation always uses the front stencil  
    write mask when clearing the stencil buffer."  
  
 -- Section 4.3.1 "Writing to the Stencil Buffer or to the Depth and  
    Stencil Buffers"  
  
    Replace the final sentence in the first paragraph with:  
  
    "Finally, each stencil index is written to its indicated location  
    in the framebuffer, subject to the current front stencil mask state  
    (set with StencilMask), and if a depth component is present, if the  
    setting of DepthMask is not FALSE, it is also written to the  
    framebuffer; the setting of DepthTest is ignored."  
  
homeprevnext Additions to Chapter 5 of the GL Specification (Special Functions)
  
    None  
  
homeprevnext Additions to Chapter 6 of the GL Specification (State and State Requests)
  
    None  
  
homeprevnext Additions to the GLX, WGL, and AGL Specification
  
    None  
  
homeprevnext GLX Protocol
  
    A new GL rendering command is added. The following command is sent to the   
    server as part of a glXRender request:  
  
        ActiveStencilFaceEXT  
            2           8               rendering command length  
            2           4220            rendering command opcode  
            4           ENUM            face  
  
homeprevnext Errors
  
    None  
  
homeprevnext New State
  
(table 6.15, page 205) amend the following entries:  
  
Get Value                  Type  Get Command  Initial Value  Description          Sec    Attribute  
-------------------------  ----  -----------  -------------  -------------------  -----  --------------  
STENCIL_FUNC               2xZ8  GetIntegerv  ALWAYS         Stencil function     4.1.4  stencil-buffer  
STENCIL_VALUE_MASK         2xZ+  GetIntegerv  1's            Stencil mask         4.1.4  stencil-buffer  
STENCIL_REF                2xZ+  GetIntegerv  0              Stencil reference    4.1.4  stencil-buffer  
                                                             value  
STENCIL_FAIL               2xZ6  GetIntegerv  KEEP           Stencil fail action  4.1.4  stencil-buffer  
STENCIL_PASS_DEPTH_FAIL    2xZ6  GetIntegerv  KEEP           Stencil depth        4.1.4  stencil-buffer  
                                                             buffer fail action  
STENCIL_PASS_DEPTH_PASS    2xZ6  GetIntegerv  KEEP           Stencil depth        4.1.4  stencil-buffer  
                                                             buffer pass action  
  
[Type field is amended with "2x" prefix.]  
  
(table 6.15, page 205) add the following entries:  
  
Get Value                  Type  Get Command  Initial Value  Description        Sec    Attribute  
-------------------------  ----  -----------  -------------  -----------------  ------ ---------------------  
STENCIL_TEST_TWO_SIDE_EXT  B     IsEnabled    False          Two-sided stencil  4.1.4  stencil-buffer/enable  
                                                             test enable   
ACTIVE_STENCIL_FACE_EXT    Z2    GetIntegerv  FRONT          Active stencil     4.1.4  stencil-buffer  
                                                             face selector  
  
(table 6.16, page 205) ammend the following entry:  
  
Get Value                  Type  Get Command  Initial Value  Description        Sec    Attribute  
-------------------------  ----  -----------  -------------  -----------------  ------ --------------  
STENCIL_WRITE_MASK         2xZ+  GetIntegerv  1's            Stencil buffer     4.2.2  stencil-buffer  
                                                             writemask  
  
[Type field is amended with "2x" prefix.]  
  
homeprevnext Revision History
  
    None  
    None  
Valid XHTML 1.1! Valid CSS! Last update: November 14, 2006.
Cette page doit être lue avec un navigateur récent respectant le standard XHTML 1.1.