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