GLART week 11: Stencil and Shadows

Reading: Red Book, Chapter 10, The Framebuffer, Buffers and Their Uses: pgs 432-447 Examples: GLART_11_Stencil.java -- Use the stencil buffer to mask an area of the screen GLART_11_Shadow.java -- Use a custom matrix to make shadows. glart_week11_examples.zip -- Full source code NOTES: ================================================================= Stenciling is a technique to mask out areas of the screen and restrict rendering only to these masked areas. To do this we use the Stencil Buffer and the Stencil Test, which can allow or prevent certain pixels from being drawn to the screen. We've briefly discussed the two other buffers before: the Color buffer and Depth buffer. Together with the Stencil buffer these three data structures manage how pixels are drawn onto the screen, and keep track of all the pixels that are actually on the screen. Buffers ------------------------ Buffers are like large arrays that hold information about each pixel on the screen. The most basic buffer is the Color buffer, which holds the RGBA color value for each pixel. Other buffers hold depth information, and stencil masks. Think of the buffers as arrays that hold a numerical value for each pixel on the screen. Each buffer has a "test" associated with it. Before a pixel is written to the screen it is tested to see if it should be written or not. For instance, let's say that shape A is behind shape B, so that A is completely hidden from view. If the depth test is enabled, OpenGL will test the pixels that make up shape A before it draws them to the screen. It will compare the depth value of those pixels to the depth values stored in the depth buffer at the same screen location, and if the depth buffer values are closer to the front, OpenGL will discard the pixels of shape A. Shape A fails the depth test (something was drawn to the screen that is closer to the viewpoint than shape A, so shape A is not visible), and so will not be drawn to the screen. The three buffers are: Color buffer holds an RGB color value and alpha value for each pixel often referred to as the "frame buffer" similar to the pixels array in Processing the color buffer is always "on" (unlike Depth and Stencil buffers, which can be disabled) Depth buffer holds a depth value (a number from 0 to 1) for each pixel describes what object is closest to the viewpoint at each pixel Stencil buffer holds a mask value for each pixel can be used to restrict drawing to specific areas of the screen Buffer Tests: Each buffer has a corresponding test that can be turned on or off. Use glEnable() and glDisable() with one of these parameters: GL_ALPHA_TEST test an incoming pixel alpha value before drawing to screen for example: discard transparent pixels from a gif texture image Color buffer is always "on", but alpha testing can be turned on/off by default it's "off". GL_DEPTH_TEST test an incoming pixel depth value before drawing to screen for example: don't draw objects that are hidden behind other objects by default it's "off" GL_STENCIL_TEST test the mask at a pixel position before drawing to screen for example: only draw pixels if they fall inside a mask area by default it's "off" You can change how tests will occur: Each buffer has a function that can change the rule for how that buffer test will behave. glAlphaFunc() glDepthFunc() glStencilFunc() You can make the buffers read-only: To fine-tune how a buffer test behaves, you may want to preserve the contents of the buffer by making it read-only. This prevents OpenGL from writing any more values to the buffer but preserves the current values in the buffer. This is not the same as disabling the test, which will completely turn the test and its buffer off. glColorMask() glDepthMask() glStencilMask() Additional functions: Two tests can be fine-tuned with additional functions that control what to do when a value passes or fails a test. glBlendFunc() specifies how to blend an incoming pixel into the color buffer ie. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) will average the pixels together must glEnable(GL_BLEND) for alpha blending to work glStencilOp() specifies what to do when: 1) the stencil test fails, or 2) the stencil test passes but depth test fails or 3) the stencil test passes and depth test passes Summary Buffer Enable/Disable How to test incoming Make buffer Additional testing on this pixel value against read-only buffer what's in the buffer -------------- --------------------- ---------------------- --------------------- -------------- Color GL_ALPHA_TEST glAlphaFunc glColorMask glBlendFunc Depth GL_DEPTH_TEST glDepthFunc glDepthMask Stencil GL_STENCIL_TEST glStencilFunc glStencilMask glStencilOp Scissor Test --------------------------- The "Scissor Test" clips all drawing to a specified rectangle. Like other tests it can be enabled or disabled, and when enabled, it will restrict what pixels are rendered. Unlike other tests, it is not related to a specific buffer. The Scissor test restricts rendering to a given rectangular area of the display, but does not specifically alter the behavior of the color, depth or stencil buffers. glEnable(GL_SCISSOR_TEST) turn on scissor test (by default it's off) glScissor(lowerX, lowerY, width, height) specify the rectangle where rendering can occur