140 likes | 530 Views
Stencil Buffer, Shadow Volumes. Soon Tee Teoh CS 134. Stencil Buffer. The Stencil Buffer is another frame buffer, like the Color Buffer, Depth Buffer and Accumulation Buffer.
E N D
Stencil Buffer, Shadow Volumes Soon Tee Teoh CS 134
Stencil Buffer • The Stencil Buffer is another frame buffer, like the Color Buffer, Depth Buffer and Accumulation Buffer. • Stencil Buffer can be used to specify a pattern so that only fragments that pass the stencil test are rendered to the color buffer.
Stencil Buffer ExampleRender the fragments only where the stencil buffer bit is 0 0 1 1 1 Stencil Buffer Color Buffer
OpenGL Stencil Buffer Functions // glStencilFunc: set function and reference value for stencil testing // func :Specifies the test function. Options: GL_NEVER, GL_LESS, GL_LEQUAL, // GL_GREATER, GL_GEQUAL, GL_EQUAL, GL_NOTEQUAL, and GL_ALWAYS. // Default is GL_ALWAYS. // ref : Specifies the reference value for the stencil test. // ref is clamped to the range [0,2n−1], where n is the number of bits for each fragment // in the stencil buffer. The initial value is 0. // Mask: Specifies a mask that is ANDed with both the reference value and the stored // stencil value when the test is done. Default is all 1's. void glStencilFunc (GLenum func , GLint ref , GLuint mask ); // glStencilOp: set stencil test actions on the stencil buffer // fail:Specifies the action to take when the stencil test fails. Options: GL_KEEP, GL_ZERO, // GL_REPLACE, GL_INCR, GL_DECR, and GL_INVERT. Default is GL_KEEP. // zfail: Specifies the stencil action when the stencil test passes, but the depth test fails. // Options and default same as for fail. // zpass: Specifies the stencil action when both the stencil test and the depth test pass, // or when the stencil test passes and either there is no depth buffer // or depth testing is not enabled. Options and default same as for fail. void glStencilOp (GLenum fail , GLenum zfail , GLenum zpass );
How to set the Stencil Buffer • First, make sure we request the stencil buffer. • Next, make sure we enable stencil test • Example: Make a stencil buffer have value 1 inside a diamond shape and value 0 outside. glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL ); glEnable(GL_STENCIL_TEST); glClearStencil(0x0); // specify stencil clear value glClear(GL_STENCIL_BUFFER_BIT); // clear stencil buffer // Set the ref value to 0x1 glStencilFunc(GL_ALWAYS, 0x1, 0x1); // Replace stencil bit with ref (0x1) whenever we process a fragment glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); // draw a diamond (we’ll not really render the color buffer, // but just use this to set the stencil buffer) glBegin(GL_QUADS); glVertex2f(-1,0); glVertex2f(0,1); glVertex2f(1,0); glVertex2f(0,-1); glEnd();
How to use Stencil Buffer to filter rendering to Color Buffer // render scene only where stencil buffer is 0 void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // fragment passes the test if stencil value at fragment is not equal to 0x1 glStencilFunc(GL_NOTEQUAL, 0x1, 0x1); // don’t change the value of the stencil buffer in any case glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // render the scene renderScene(); }
Shadow Volumes • One method to create shadows is to use shadow volumes. • The shadow volume of an object is the volume that is in shadow due to the object, with respect to a light source. • Any object inside the shadow volume is in shadow. • For computation purpose, a shadow volume can either be finite or infinite. Point light source Shadow Volume Occluder
How to find Shadow Volume (1) • First, need to get the silhouette edges of the occluder with respect to the light source. • A silhouette edge is an edge that separates a front-facing polygon from a back-facing polygon (with respect to the light source). • For triangles, it’s easy. The silhouette edges of a triangle are equal to the edges of the triangle. Silhouette Point light source Occluder
How to find Shadow Volume (2) • Next, we extrude the silhouette edges by projecting the vertices away from the light source (assuming point light source) • The resulting quadrilaterals define the shadow volume. light source quadrilateral
Implementing Shadow Volumes using Stencil Buffer • 1. Render all the objects using only ambient lighting. Make sure depth buffer is written. • 2. Starting with a light source, calculate the silhouette of all the occluders with respect to the light source. • 3. Extrude the silhouette away from the light source to a finite or infinite distance to form the shadow volumes. • 4. Clear the stencil buffer, and then render the shadow volumes using the depth-pass technique (next slide). The depth-pass technique will set a value 1 in the stencil buffer position for every fragment that is inside the shadow volume. • 5. Using the updated stencil buffer, render all objects using diffuse and specular lighting for this light for all fragments that correspond to zero stencil values. • 6. Accumulate the colors from step 5. • 7. Repeat step 2 to 6 for all the lights in the scene.
The Depth Pass Technique • Assume that the scene has already been rendered and the depth buffer values set accordingly. • Then, the depth-pass technique is as follows: • Render front face of shadow volume. If depth test passes, increment stencil value, else do nothing. Disable draw to frame and depth buffer. • Render back face of shadow volume. If depth test passes, decrement stencil value, else do nothing. Disable draw to frame and depth buffer. • The depth pass technique works for multiple intersecting shadow volumes.
Problems with the Depth Pass Technique • Does not work if camera is inside the shadow volume • Solution: If camera is inside the shadow volume, use the depth-fail technique instead. • Both depth-pass and depth-fail will have problems with OpenGL view frustum clipping. • Depth-pass fails when the shadow volume intersects the near clipping plane. • Depth-fail fails when the shadow volume intersects the far clipping plane.