1// 2// Book: OpenGL(R) ES 2.0 Programming Guide 3// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner 4// ISBN-10: 0321502795 5// ISBN-13: 9780321502797 6// Publisher: Addison-Wesley Professional 7// URLs: http://safari.informit.com/9780321563835 8// http://www.opengles-book.com 9// 10 11// Stencil_Test.c 12// 13// This example shows various stencil buffer 14// operations. 15// 16#include <stdlib.h> 17#include "esUtil.h" 18 19typedef struct 20{ 21 // Handle to a program object 22 GLuint programObject; 23 24 // Attribute locations 25 GLint positionLoc; 26 27 // Uniform locations 28 GLint colorLoc; 29 30} UserData; 31 32/// 33// Initialize the shader and program object 34// 35int Init ( ESContext *esContext ) 36{ 37 UserData *userData = esContext->userData; 38 GLbyte vShaderStr[] = 39 "attribute vec4 a_position; \n" 40 "void main() \n" 41 "{ \n" 42 " gl_Position = a_position; \n" 43 "} \n"; 44 45 GLbyte fShaderStr[] = 46 "precision mediump float; \n" 47 "uniform vec4 u_color; \n" 48 "void main() \n" 49 "{ \n" 50 " gl_FragColor = u_color; \n" 51 "} \n"; 52 53 // Load the shaders and get a linked program object 54 userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); 55 56 // Get the attribute locations 57 userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); 58 59 // Get the sampler location 60 userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" ); 61 62 // Set the clear color 63 glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); 64 65 // Set the stencil clear value 66 glClearStencil ( 0x1 ); 67 68 // Set the depth clear value 69 glClearDepthf( 0.75f ); 70 71 // Enable the depth and stencil tests 72 glEnable( GL_DEPTH_TEST ); 73 glEnable( GL_STENCIL_TEST ); 74 75 return TRUE; 76} 77 78/// 79// Initialize the stencil buffer values, and then use those 80// values to control rendering 81// 82void Draw ( ESContext *esContext ) 83{ 84 int i; 85 86 UserData *userData = esContext->userData; 87 88 GLfloat vVertices[] = { 89 -0.75f, 0.25f, 0.50f, // Quad #0 90 -0.25f, 0.25f, 0.50f, 91 -0.25f, 0.75f, 0.50f, 92 -0.75f, 0.75f, 0.50f, 93 0.25f, 0.25f, 0.90f, // Quad #1 94 0.75f, 0.25f, 0.90f, 95 0.75f, 0.75f, 0.90f, 96 0.25f, 0.75f, 0.90f, 97 -0.75f, -0.75f, 0.50f, // Quad #2 98 -0.25f, -0.75f, 0.50f, 99 -0.25f, -0.25f, 0.50f, 100 -0.75f, -0.25f, 0.50f, 101 0.25f, -0.75f, 0.50f, // Quad #3 102 0.75f, -0.75f, 0.50f, 103 0.75f, -0.25f, 0.50f, 104 0.25f, -0.25f, 0.50f, 105 -1.00f, -1.00f, 0.00f, // Big Quad 106 1.00f, -1.00f, 0.00f, 107 1.00f, 1.00f, 0.00f, 108 -1.00f, 1.00f, 0.00f 109 }; 110 111 GLubyte indices[][6] = { 112 { 0, 1, 2, 0, 2, 3 }, // Quad #0 113 { 4, 5, 6, 4, 6, 7 }, // Quad #1 114 { 8, 9, 10, 8, 10, 11 }, // Quad #2 115 { 12, 13, 14, 12, 14, 15 }, // Quad #3 116 { 16, 17, 18, 16, 18, 19 } // Big Quad 117 }; 118 119#define NumTests 4 120 GLfloat colors[NumTests][4] = { 121 { 1.0f, 0.0f, 0.0f, 1.0f }, 122 { 0.0f, 1.0f, 0.0f, 1.0f }, 123 { 0.0f, 0.0f, 1.0f, 1.0f }, 124 { 1.0f, 1.0f, 0.0f, 0.0f } 125 }; 126 127 GLint numStencilBits; 128 GLuint stencilValues[NumTests] = { 129 0x7, // Result of test 0 130 0x0, // Result of test 1 131 0x2, // Result of test 2 132 0xff // Result of test 3. We need to fill this 133 // value in a run-time 134 }; 135 136 // Set the viewport 137 glViewport ( 0, 0, esContext->width, esContext->height ); 138 139 // Clear the color, depth, and stencil buffers. At this 140 // point, the stencil buffer will be 0x1 for all pixels 141 glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); 142 143 // Use the program object 144 glUseProgram ( userData->programObject ); 145 146 // Load the vertex position 147 glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 148 GL_FALSE, 0, vVertices ); 149 150 glEnableVertexAttribArray ( userData->positionLoc ); 151 152 // Test 0: 153 // 154 // Initialize upper-left region. In this case, the 155 // stencil-buffer values will be replaced because the 156 // stencil test for the rendered pixels will fail the 157 // stencil test, which is 158 // 159 // ref mask stencil mask 160 // ( 0x7 & 0x3 ) < ( 0x1 & 0x7 ) 161 // 162 // The value in the stencil buffer for these pixels will 163 // be 0x7. 164 // 165 glStencilFunc( GL_LESS, 0x7, 0x3 ); 166 glStencilOp( GL_REPLACE, GL_DECR, GL_DECR ); 167 glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[0] ); 168 169 // Test 1: 170 // 171 // Initialize the upper-right region. Here, we'll decrement 172 // the stencil-buffer values where the stencil test passes 173 // but the depth test fails. The stencil test is 174 // 175 // ref mask stencil mask 176 // ( 0x3 & 0x3 ) > ( 0x1 & 0x3 ) 177 // 178 // but where the geometry fails the depth test. The 179 // stencil values for these pixels will be 0x0. 180 // 181 glStencilFunc( GL_GREATER, 0x3, 0x3 ); 182 glStencilOp( GL_KEEP, GL_DECR, GL_KEEP ); 183 glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[1] ); 184 185 // Test 2: 186 // 187 // Initialize the lower-left region. Here we'll increment 188 // (with saturation) the stencil value where both the 189 // stencil and depth tests pass. The stencil test for 190 // these pixels will be 191 // 192 // ref mask stencil mask 193 // ( 0x1 & 0x3 ) == ( 0x1 & 0x3 ) 194 // 195 // The stencil values for these pixels will be 0x2. 196 // 197 glStencilFunc( GL_EQUAL, 0x1, 0x3 ); 198 glStencilOp( GL_KEEP, GL_INCR, GL_INCR ); 199 glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[2] ); 200 201 // Test 3: 202 // 203 // Finally, initialize the lower-right region. We'll invert 204 // the stencil value where the stencil tests fails. The 205 // stencil test for these pixels will be 206 // 207 // ref mask stencil mask 208 // ( 0x2 & 0x1 ) == ( 0x1 & 0x1 ) 209 // 210 // The stencil value here will be set to ~((2^s-1) & 0x1), 211 // (with the 0x1 being from the stencil clear value), 212 // where 's' is the number of bits in the stencil buffer 213 // 214 glStencilFunc( GL_EQUAL, 0x2, 0x1 ); 215 glStencilOp( GL_INVERT, GL_KEEP, GL_KEEP ); 216 glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[3] ); 217 218 // Since we don't know at compile time how many stecil bits are present, 219 // we'll query, and update the value correct value in the 220 // stencilValues arrays for the fourth tests. We'll use this value 221 // later in rendering. 222 glGetIntegerv( GL_STENCIL_BITS, &numStencilBits ); 223 224 stencilValues[3] = ~(((1 << numStencilBits) - 1) & 0x1) & 0xff; 225 226 // Use the stencil buffer for controlling where rendering will 227 // occur. We diable writing to the stencil buffer so we 228 // can test against them without modifying the values we 229 // generated. 230 glStencilMask( 0x0 ); 231 232 for ( i = 0; i < NumTests; ++i ) 233 { 234 glStencilFunc( GL_EQUAL, stencilValues[i], 0xff ); 235 glUniform4fv( userData->colorLoc, 1, colors[i] ); 236 glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[4] ); 237 } 238 239 eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface ); 240} 241 242/// 243// Cleanup 244// 245void ShutDown ( ESContext *esContext ) 246{ 247 UserData *userData = esContext->userData; 248 249 // Delete program object 250 glDeleteProgram ( userData->programObject ); 251} 252 253 254int main ( int argc, char *argv[] ) 255{ 256 ESContext esContext; 257 UserData userData; 258 259 esInitContext ( &esContext ); 260 esContext.userData = &userData; 261 262 esCreateWindow ( &esContext, TEXT("Stencil Test"), 320, 240, 263 ES_WINDOW_RGB | ES_WINDOW_DEPTH | ES_WINDOW_STENCIL ); 264 265 if ( !Init ( &esContext ) ) 266 return 0; 267 268 esRegisterDrawFunc ( &esContext, Draw ); 269 270 esMainLoop ( &esContext ); 271 272 ShutDown ( &esContext ); 273} 274