| OLD | NEW |
| (Empty) |
| 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 | |
| 19 typedef 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 // | |
| 35 int 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_pos
ition" ); | |
| 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 // | |
| 82 void 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 // | |
| 245 void ShutDown ( ESContext *esContext ) | |
| 246 { | |
| 247 UserData *userData = esContext->userData; | |
| 248 | |
| 249 // Delete program object | |
| 250 glDeleteProgram ( userData->programObject ); | |
| 251 } | |
| 252 | |
| 253 | |
| 254 int main ( int argc, char *argv[] ) | |
| 255 { | |
| 256 ESContext esContext; | |
| 257 UserData userData; | |
| 258 | |
| 259 esInitContext ( &esContext ); | |
| 260 esContext.userData = &userData; | |
| 261 | |
| 262 esCreateWindow ( &esContext, "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 } | |
| OLD | NEW |