glStencilOpSeparate
glStencilOp with separate actions for front-facing and back-facing triangles.
Signature
void glStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
How it works
Same three cases as glStencilOp, but only for the faces you name. The classic use is stencil shadow volumes: drawing the volume once with culling off, back faces increment and front faces decrement, so each pixel ends up counting how many volumes it is inside. A pixel with a count other than 0 is in shadow.
It saves drawing the volume twice with glCullFace in between.
Parameters
Which faces these actions apply to.
Common values
- GL_FRONT
- Front-facing triangles (see glFrontFace).
- GL_BACK
- Back-facing triangles.
- GL_FRONT_AND_BACK
- Both: the same as glStencilOp.
Action when the stencil test fails.
Common values
- GL_KEEP
- Leave the stored value as it is (default for all three).
- GL_REPLACE
- Write ref (from glStencilFunc). The usual way to paint a mask.
- GL_ZERO
- Write 0.
- GL_INCR / GL_DECR
- Add or subtract 1, stopping at the maximum (255 with 8 bits) or at 0.
- GL_INCR_WRAP / GL_DECR_WRAP
- Add or subtract 1, wrapping around (255 + 1 = 0). Shadow volumes count with these.
- GL_INVERT
- Flip every bit of the stored value.
Action when the stencil passes but depth fails.
Action when both pass.
Tips & pitfalls
Use the _WRAP versions for counting: with plain GL_DECR a count that dips below 0 would stick at 0 and break the sum.
Errors
When the call is invalid it does nothing and sets an error, which glGetError returns:
- GL_INVALID_ENUM
- face or any action is not an accepted value.
Example
1// z-fail shadow volume: count where the volume hides behind geometry
2glDisable(GL_CULL_FACE);
3glStencilOpSeparate(GL_BACK, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
4glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
5drawShadowVolumes();