• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Name
2
3    EXT_stencil_two_side
4
5Name Strings
6
7    GL_EXT_stencil_two_side
8
9Contact
10
11    Mark J. Kilgard, NVIDIA Corporation (mjk 'at' nvidia.com)
12
13Notice
14
15    Copyright NVIDIA Corporation, 2001-2002.
16
17Status
18
19    Implemented in CineFX (NV30) Emulation driver, August 2002.
20    Shipping in Release 40 NVIDIA driver for CineFX hardware, January 2003.
21
22Version
23
24    Last Modified Date:  09/15/2005
25    Revision:            2
26
27Number
28
29    268
30
31Dependencies
32
33    Written based on the OpenGL 1.3 specification.
34
35    NV_packed_depth_stencil affects the definition of this extension.
36
37    OpenGL 2.0 affects the definition of this extension.
38
39Overview
40
41    This extension provides two-sided stencil testing where the
42    stencil-related state (stencil operations, reference value, compare
43    mask, and write mask) may be different for front- and back-facing
44    polygons.  Two-sided stencil testing may improve the performance
45    of stenciled shadow volume and Constructive Solid Geometry (CSG)
46    rendering algorithms.
47
48Issues
49
50    Is this sufficient for shadow volume stencil update in a single pass?
51
52      RESOLUTION:  Yes.
53
54      An application that wishes to increment the stencil value for
55      rasterized depth-test passing fragments of front-facing polygons and
56      decrement the stencil value for rasterized fragments of depth-test
57      passing back-facing polygons in a single pass can use the following
58      configuration:
59
60        glDepthMask(0);
61        glColorMask(0,0,0,0);
62        glDisable(GL_CULL_FACE);
63        glEnable(GL_STENCIL_TEST);
64        glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
65
66        glActiveStencilFaceEXT(GL_BACK);
67        glStencilOp(GL_KEEP,            // stencil test fail
68                    GL_KEEP,            // depth test fail
69                    GL_DECR_WRAP_EXT);  // depth test pass
70        glStencilMask(~0);
71        glStencilFunc(GL_ALWAYS, 0, ~0);
72
73        glActiveStencilFaceEXT(GL_FRONT);
74        glStencilOp(GL_KEEP,            // stencil test fail
75                    GL_KEEP,            // depth test fail
76                    GL_INCR_WRAP_EXT);  // depth test pass
77        glStencilMask(~0);
78        glStencilFunc(GL_ALWAYS, 0, ~0);
79
80        renderShadowVolumePolygons();
81
82      Notice the use of EXT_stencil_wrap to avoid saturating decrements
83      losing the shadow volume count.  An alternative, using the
84      conventional GL_INCR and GL_DECR operations, is to clear the stencil
85      buffer to one half the stencil buffer value range, say 128 for an
86      8-bit stencil buffer.  In the case, a pixel is "in shadow" if the
87      final stencil value is greater than 128 and "out of shadow" if the
88      final stencil value is 128.  This does still create a potential
89      for stencil value overflow if the stencil value saturates due
90      to an increment or decrement.  However saturation is less likely
91      with two-sided stencil testing than the conventional two-pass
92      approach because front- and back-facing polygons are mixed together,
93      rather than processing batches of front-facing then back-facing
94      polygons.
95
96      Contrast the two-sided stencil testing approach with the more
97      or less equivalent approach using facingness-independent stencil
98      testing:
99
100        glDepthMask(0);
101        glColorMask(0,0,0,0);
102        glEnable(GL_CULL_FACE);
103        glEnable(GL_STENCIL_TEST);
104
105        glStencilMask(~0);
106        glStencilFunc(GL_ALWAYS, 0, ~0);
107
108        // Increment for front faces
109        glCullFace(GL_BACK);
110        glStencilOp(GL_KEEP,   // stencil test fail
111                    GL_KEEP,   // depth test fail
112                    GL_INCR);  // depth test pass
113
114        renderShadowVolumePolygons();
115
116        // Decrement for back faces
117        glCullFace(GL_FRONT);
118        glStencilOp(GL_KEEP,   // stencil test fail
119                    GL_KEEP,   // depth test fail
120                    GL_DECR);  // depth test pass
121
122        renderShadowVolumePolygons();
123
124      Notice that all the render work implicit
125      in renderShadowVolumePolygons is performed twice with the
126      conventional approach, but only once with the two-sided stencil
127      testing approach.
128
129    Should there be just front and back stencil test state, or should
130    the stencil write mask also have a front and back state?
131
132      RESOLUTION:  Both the stencil test and stencil write mask state
133      should have front and back versions.
134
135      The shadow volume application for two-sided stencil testing does
136      not require differing front and back versions of the stencil write
137      mask, but we anticipate other applications where front and back
138      write masks may be useful.
139
140      For example, it may be useful to draw a convex polyhedra such that
141      (assuming the stencil bufer is cleared to the binary value 1010):
142
143      1) front-facing polygons that pass the depth test set stencil bit 0
144
145      2) front-facing polygons that fail the depth test zero stencil bit 1
146
147      3) back-facing polygons that pass the depth test set stencil bit 2
148
149      4) back-facing polygons that fail the depth test zero stencil bit 3
150
151      This could be accomplished in a single rendering pass using:
152
153        glStencilMask(~0);
154        glStencilClear(0xA);
155        glClear(GL_STENCIL_BUFFER_BIT);
156
157        glDepthMask(0);
158        glColorMask(0,0,0,0);
159        glDisable(GL_CULL_FACE);
160        glEnable(GL_STENCIL_TEST);
161        glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
162
163        glActiveStencilFaceEXT(GL_BACK);
164        glStencilOp(GL_KEEP,      // stencil test fail
165                    GL_ZERO,      // depth test fail
166                    GL_REPLACE);  // depth test pass
167        glStencilMask(0xC);
168        glStencilFunc(GL_ALWAYS, 0x4, ~0);
169
170        glActiveStencilFaceEXT(GL_FRONT);
171        glStencilOp(GL_KEEP,      // stencil test fail
172                    GL_ZERO,      // depth test fail
173                    GL_REPLACE);  // depth test pass
174        glStencilMask(0x3);
175        glStencilFunc(GL_ALWAYS, 0x1, ~0);
176
177        renderConvexPolyhedra();
178
179    Is there a performance advantage to using two-sided stencil testing?
180
181      RESOLUTION:  It depends.
182
183      In a fill-rate limited situation, rendering front-facing primitives,
184      then back-facing primitives in two passes will generate the same
185      number of rasterized fragments as rendering front- and back-facing
186      primitives in a single pass.
187
188      However, in other situations that are CPU-limited,
189      transform-limited, or setup-limited, two-sided stencil testing can
190      be faster than the conventional two-pass face culling rendering
191      approaches.  For example, if a lengthy vertex program is executed
192      for every shadow volume vertex, rendering the shadow volume with
193      a single two-sided stencil testing pass is advantageous.
194
195      Often applications using stencil shadow volume techniques require
196      substantial CPU resources to determine potential silhouette
197      boundaries to project shadow volumes from.  If the shadow volume
198      geometry generated by the CPU is only required to be sent to the GL
199      once per-frame (rather than twice with the conventional technique),
200      that can ease the CPU burden required to implement stenciled shadow
201      volumes.
202
203    Should GL_FRONT_AND_BACK be accepted by glActiveStencilFaceEXT?
204
205      RESOLUTION:  No.
206
207      GL_FRONT_AND_BACK is useful when materials are being updated for
208      two-sided lighting because the front and back material are often
209      identical and may change frequently (glMaterial calls are allowed
210      within glBegin/glEnd pairs).
211
212      Two-sided stencil has no similiar performance justification.
213
214      It is also likely that forcing implementations to support this mode
215      would increase the amount of overhead required to set stencil
216      state, even for applications that don't use two-sided stencil.
217
218    How should the two-sided stencil enable operate?
219
220      RESOLUTION:  It should be modeled after the way two-sided lighting
221      works.  There is a GL_LIGHTING enable and then an additional
222      two-sided lighting mode.  Unlike two-sided lighting which is a
223      light model boolean, the two-sided stencil testing is a standard
224      enable named GL_STENCIL_TEST_TWO_SIDE_EXT.
225
226      Here is the pseudo-code for the stencil testing enables:
227
228        if (glIsEnabled(GL_STENCIL_TEST)) {
229          if (glIsEnabled(GL_STENCIL_TEST_TWO_SIDE_EXT) && primitiveType == polygon) {
230            use two-sided stencil testing
231          } else {
232            use conventional stencil testing
233          }
234        } else {
235          no stencil testing
236        }
237
238    How should the two-sided stencil interact with glPolygonMode?
239
240      RESOLUTION:  Primitive type is determined by the begin mode
241      so GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_QUAD_STRIP, GL_QUADS,
242      GL_TRIANGLE_FAN, and GL_POLYGON generate polygon primitives.  If the
243      polygon mode is set such that lines or points are rasterized,
244      two-sided stencil testing still operates based on the original
245      polygon facingness if stencil testing and two-sided stencil testing
246      are enabled.
247
248      This is consistent with how two-sided lighting and face culling
249      interact with glPolygonMode.
250
251New Procedures and Functions
252
253    void ActiveStencilFaceEXT(enum face);
254
255New Tokens
256
257    Accepted by the <cap> parameter of Enable, Disable, and IsEnabled,
258    and by the <pname> parameter of GetBooleanv, GetIntegerv,
259    GetFloatv, and GetDoublev:
260
261        STENCIL_TEST_TWO_SIDE_EXT                 0x8910
262
263    Accepted by the <face> parameter of ActiveStencilFaceEXT:
264
265        FRONT
266        BACK
267
268    Accepted by the <pname> parameters of GetBooleanv, GetIntegerv,
269    GetFloatv, and GetDoublev:
270
271        ACTIVE_STENCIL_FACE_EXT                   0x8911
272
273Additions to Chapter 2 of the GL Specification (OpenGL Operation)
274
275    None
276
277Additions to Chapter 3 of the GL Specification (Rasterization)
278
279    None
280
281Additions to Chapter 4 of the GL Specification (Per-Fragment Operations
282and the Framebuffer)
283
284 -- Section 4.1.5 "Stencil test"
285
286    Replace the first paragraph in the section with:
287
288    "The stencil test conditionally discards a fragment based on the
289    outcome of a comparison between the value in the stencil buffer at
290    location (xw,yw) and a reference value.
291
292    The test is enabled or disabled with the Enable and Disable commands,
293    using the symbolic constant STENCIL_TEST.  When disabled, the stencil
294    test and associated modifications are not made, and the fragment is
295    always passed.
296
297    Stencil testing may operate in a two-sided mode.  Two-sided stencil
298    testing is enabled or disabled with the Enable and Disable commands,
299    using the symbolic constant STENCIL_TEST_TWO_SIDE_EXT.  When stencil
300    testing is disabled, the state of two-sided stencil testing does
301    not affect fragment processing.
302
303    There are two sets of stencil-related state, the front stencil
304    state set and the back stencil state set.  When two-sided stencil
305    testing is enabled, stencil tests and writes use the front set of
306    stencil state when processing fragments rasterized from non-polygon
307    primitives (points, lines, bitmaps, image rectangles) and front-facing
308    polygon primitives while the back set of stencil state is used when
309    processing fragments rasterized from back-facing polygon primitives.
310    For the purposes of two-sided stencil testing, a primitive is still
311    considered a polygon even if the polygon is to be rasterized as
312    points or lines due to the current polygon mode.  Whether a polygon
313    is front- or back-facing is determined in the same manner used for
314    two-sided lighting and face culling (see sections 2.13.1 and 3.5.1).
315    When two-sided stencil testing is disabled, the front set of stencil
316    state is always used when stencil testing fragments.
317
318    The active stencil face determines whether stencil-related commands
319    update the front or back stencil state.  The active stencil face is
320    set with:
321
322      void ActiveStencilFace(enum face);
323
324    where face is either FRONT or BACK.  Stencil commands (StencilFunc,
325    StencilOp, and StencilMask) that update the stencil state update the
326    front stencil state if the active stencil face is FRONT and the back
327    stencil state if the active stencil face is BACK.  Additionally,
328    queries of stencil state return the front or back stencil state
329    depending on the current active stencil face.
330
331    The stencil test state is controlled with
332
333       void StencilFunc(enum func, int ref, uint mask);
334       void StencilOp(enum sfail, enum dpfail, enum dppass);"
335
336    Replace the third and second to the last sentence in the last
337    paragraph in section 4.1.5 with:
338
339    "In the initial state, stencil testing and two-sided stencil testing
340    are both disabled, the front and back stencil reference values are
341    both zero, the front and back stencil comparison functions are ALWAYS,
342    and the front and back stencil mask are both all ones.  Initially,
343    both the three front and the three back stencil operations are KEEP."
344
345 -- Section 4.2.2 "Fine Control of Buffer Updates"
346
347    Replace the last sentence of the third paragraph with:
348
349    "The initial state is for both the front and back stencil plane mask
350    to be all ones.  The clear operation always uses the front stencil
351    write mask when clearing the stencil buffer."
352
353 -- Section 4.3.1 "Writing to the Stencil Buffer or to the Depth and
354    Stencil Buffers"
355
356    Replace the final sentence in the first paragraph with:
357
358    "Finally, each stencil index is written to its indicated location
359    in the framebuffer, subject to the current front stencil mask state
360    (set with StencilMask), and if a depth component is present, if the
361    setting of DepthMask is not FALSE, it is also written to the
362    framebuffer; the setting of DepthTest is ignored."
363
364Additions to Chapter 5 of the GL Specification (Special Functions)
365
366    None
367
368Additions to Chapter 6 of the GL Specification (State and State Requests)
369
370    None
371
372Additions to the GLX, WGL, and AGL Specification
373
374    None
375
376GLX Protocol
377
378    A new GL rendering command is added. The following command is sent to the
379    server as part of a glXRender request:
380
381        ActiveStencilFaceEXT
382            2           8               rendering command length
383            2           4220            rendering command opcode
384            4           ENUM            face
385
386Interactions with OpenGL 2.0
387
388    OpenGL 2.0 provides similar "separate stencil" functionality with an API
389    based on the ATI_separate_stencil extension.  In the OpenGL 2.0 API, there
390    is no enable; instead, new functions are provided that set both front and
391    back state simultaneously.  Non-separate stencil functions (e.g.,
392    StencilFunc, StencilOp) set *both* back and front state.  In this
393    extension, they set either front or back state depending on the active
394    stencil face.
395
396    Implementations supporting both this extension and OpenGL 2.0 will need to
397    support both styles of two-sided stencil usage without API modification,
398    which is ugly since the OpenGL 2.0 API does not have an enable for
399    two-sided functionality -- it's always on.  To achieve this, we provide
400    three different sets of stencil state:
401
402      - front state
403      - "OpenGL 2.0" back state
404      - "EXT_stencil_two_side" back state
405
406    OpenGL 2.0 separate stencil functions set the front and "OpenGL 2.0" back
407    state.  Non-separate stencil functions use the stencil face selector to
408    determine what to set:  FRONT (the default) sets both front and "OpenGL
409    2.0" back state; BACK sets "EXT_stencil_two_side" back state.
410
411    If the two-sided stencil enable in this extension is set, implying
412    EXT_stencil_two_side usage, we choose between the front state and the
413    EXT_stencil_two_side back state.  Those two sets of state are set
414    appropriately when using the active stencil face selector provided by this
415    extension.
416
417    If the two-sided stencil enable in this extension is not set, implying
418    either OpenGL 2.0 or "one-sided" EXT_stencil_two_side usage, we choose
419    between the front state and the OpenGL 2.0 back state.  In OpenGL 2.0
420    usage, the separate stencil functions set either of these two pieces of
421    state appropriately, and the non-separate stencil functions set both.  In
422    "one-sided" EXT_stencil_two_side usage, the separate stencil functions
423    from OpenGL 2.0 will not be used.  Any time the non-separate functions set
424    the front state (active face == FRONT), they also set the OpenGL 2.0 back
425    state, so the front and back state used will always be identical in this
426    case.
427
428    The relevant spec language changes in the OpenGL 2.0 specification are:
429
430    (modify 2nd paragraph, p. 202) There are three sets of stencil-related
431    state, the front stencil state set, the OpenGL 2.0 back stencil state set,
432    and the EXT_stencil_two_side back stencil state set.  Stencil tests and
433    writes use the front set of stencil state when processing fragments
434    rasterized from non-polygon primitives (points, lines, bitmaps, image
435    rectangles) and front-facing polygon primitives.  When processing
436    fragments rasterized from back-facing polygon primitives, stencil tests
437    and writes use the OpenGL 2.0 back stencil state set when
438    STENCIL_TEST_TWO_SIDE_EXT is disabled and the EXT_stencil_two_side back
439    stencil state set otherwise. ...
440
441    (modify 3rd paragraph, p. 202) StencilFuncSeparate and StencilOpSeparate
442    take a face argument which can be FRONT, BACK, or FRONT_AND_BACK and
443    indicates which set of state is affected.  If <face> is BACK or
444    FRONT_AND_BACK, the OpenGL 2.0 back stencil state is modified, but the
445    EXT_stencil_two_side state is not.  StencilFunc and StencilOp set state
446    based on the active stencil face.  If the active stencil face is FRONT,
447    the corresponding front and OpenGL 2.0 back stencil state are set to
448    identical values.  If the active stencil face is BACK, the corresponding
449    EXT_stencil_two_side back state is set.
450
451Errors
452
453    None
454
455New State
456
457(table 6.15, page 205) amend the following entries:
458
459Get Value                  Type  Get Command  Initial Value  Description          Sec    Attribute
460-------------------------  ----  -----------  -------------  -------------------  -----  --------------
461STENCIL_FUNC               2xZ8  GetIntegerv  ALWAYS         Stencil function     4.1.4  stencil-buffer
462STENCIL_VALUE_MASK         2xZ+  GetIntegerv  1's            Stencil mask         4.1.4  stencil-buffer
463STENCIL_REF                2xZ+  GetIntegerv  0              Stencil reference    4.1.4  stencil-buffer
464                                                             value
465STENCIL_FAIL               2xZ6  GetIntegerv  KEEP           Stencil fail action  4.1.4  stencil-buffer
466STENCIL_PASS_DEPTH_FAIL    2xZ6  GetIntegerv  KEEP           Stencil depth        4.1.4  stencil-buffer
467                                                             buffer fail action
468STENCIL_PASS_DEPTH_PASS    2xZ6  GetIntegerv  KEEP           Stencil depth        4.1.4  stencil-buffer
469                                                             buffer pass action
470
471[Type field is amended with "2x" prefix.]
472
473(table 6.15, page 205) add the following entries:
474
475Get Value                  Type  Get Command  Initial Value  Description        Sec    Attribute
476-------------------------  ----  -----------  -------------  -----------------  ------ ---------------------
477STENCIL_TEST_TWO_SIDE_EXT  B     IsEnabled    False          Two-sided stencil  4.1.4  stencil-buffer/enable
478                                                             test enable
479ACTIVE_STENCIL_FACE_EXT    Z2    GetIntegerv  FRONT          Active stencil     4.1.4  stencil-buffer
480                                                             face selector
481
482(table 6.16, page 205) ammend the following entry:
483
484Get Value                  Type  Get Command  Initial Value  Description        Sec    Attribute
485-------------------------  ----  -----------  -------------  -----------------  ------ --------------
486STENCIL_WRITE_MASK         2xZ+  GetIntegerv  1's            Stencil buffer     4.2.2  stencil-buffer
487                                                             writemask
488
489[Type field is amended with "2x" prefix.]
490
491
492Revision History
493
494    Rev.    Date    Author    Changes
495    ----  --------  --------  --------------------------------------------
496    2     09/15/05  pbrown    Clarified interaction with OpenGL 2.0 two-
497                              sided stencil.
498
499    1     01/08/03  mjk       Initial revision.
500