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