blob: 88d0549c8081721cc90886efcee7f08ddca124d2 [file] [log] [blame]
Brian Paule4b23562005-05-04 20:11:35 +00001/*
2 * Test GL_EXT_framebuffer_object render-to-texture
3 *
4 * Draw a teapot into a texture image with stenciling.
5 * Then draw a textured quad using that texture.
6 *
7 * Brian Paul
8 * 18 Apr 2005
9 */
10
11
12#define GL_GLEXT_PROTOTYPES
Brian Paul32fe2332005-11-16 14:48:11 +000013#include <GL/glut.h>
Brian Paule4b23562005-05-04 20:11:35 +000014#include <assert.h>
15#include <stdio.h>
16#include <stdlib.h>
Brian Paul32fe2332005-11-16 14:48:11 +000017#include <string.h>
Brian Paule4b23562005-05-04 20:11:35 +000018#include <math.h>
Brian Paul32fe2332005-11-16 14:48:11 +000019
Brian Paul64945412006-03-24 23:17:06 +000020/* For debug */
21#define DEPTH 1
22#define STENCIL 1
23#define DRAW 1
24
Brian Paule4b23562005-05-04 20:11:35 +000025
Brian2282d812007-03-06 16:33:00 -070026static int Win = 0;
Brian Paule4b23562005-05-04 20:11:35 +000027static int Width = 400, Height = 400;
Brian Paul64945412006-03-24 23:17:06 +000028
29static GLenum TexTarget = GL_TEXTURE_2D; /*GL_TEXTURE_RECTANGLE_ARB;*/
Brian Paule4b23562005-05-04 20:11:35 +000030static int TexWidth = 512, TexHeight = 512;
Brian Paul64945412006-03-24 23:17:06 +000031/*static int TexWidth = 600, TexHeight = 600;*/
32
Brian Paule4b23562005-05-04 20:11:35 +000033static GLuint MyFB;
34static GLuint TexObj;
35static GLuint DepthRB, StencilRB;
36static GLboolean Anim = GL_FALSE;
37static GLfloat Rot = 0.0;
Brian Paul32fe2332005-11-16 14:48:11 +000038static GLboolean UsePackedDepthStencil = GL_FALSE;
Brian Paul64945412006-03-24 23:17:06 +000039static GLuint TextureLevel = 1; /* which texture level to render to */
40static GLenum TexIntFormat = GL_RGB; /* either GL_RGB or GL_RGBA */
Briandf198d22007-12-04 10:48:05 -070041static GLboolean Cull = GL_FALSE;
42static GLboolean Wireframe = GL_FALSE;
Brian Paule4b23562005-05-04 20:11:35 +000043
44
45static void
46CheckError(int line)
47{
48 GLenum err = glGetError();
49 if (err) {
50 printf("GL Error 0x%x at line %d\n", (int) err, line);
51 }
52}
53
54
55static void
56Idle(void)
57{
Brian Paul64945412006-03-24 23:17:06 +000058 Rot = glutGet(GLUT_ELAPSED_TIME) * 0.1;
Brian Paule4b23562005-05-04 20:11:35 +000059 glutPostRedisplay();
60}
61
62
63static void
64RenderTexture(void)
65{
Brian Paule4b23562005-05-04 20:11:35 +000066 GLenum status;
67
68 glMatrixMode(GL_PROJECTION);
69 glLoadIdentity();
70 glOrtho(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
71 glMatrixMode(GL_MODELVIEW);
72 glLoadIdentity();
73 glTranslatef(0.0, 0.0, -15.0);
74
Brian Paul7edf1e82005-10-04 15:16:27 +000075 /* draw to texture image */
Brian Paule4b23562005-05-04 20:11:35 +000076 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
Brian Paule4b23562005-05-04 20:11:35 +000077
78 status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
79 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
80 printf("Framebuffer incomplete!!!\n");
81 }
82
83 glViewport(0, 0, TexWidth, TexHeight);
84
85 glClearColor(0.5, 0.5, 1.0, 0.0);
86 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
Brian Paul32fe2332005-11-16 14:48:11 +000087 CheckError(__LINE__);
Brian Paule4b23562005-05-04 20:11:35 +000088
Brian Paul64945412006-03-24 23:17:06 +000089#if DEPTH
Brian Paule4b23562005-05-04 20:11:35 +000090 glEnable(GL_DEPTH_TEST);
Brian Paul64945412006-03-24 23:17:06 +000091#endif
92
93#if STENCIL
Brian Paule4b23562005-05-04 20:11:35 +000094 glEnable(GL_STENCIL_TEST);
95 glStencilFunc(GL_NEVER, 1, ~0);
96 glStencilOp(GL_REPLACE, GL_KEEP, GL_REPLACE);
Brian Paul64945412006-03-24 23:17:06 +000097#endif
Brian Paule4b23562005-05-04 20:11:35 +000098
Brian Paul32fe2332005-11-16 14:48:11 +000099 CheckError(__LINE__);
100
Brian Paul64945412006-03-24 23:17:06 +0000101#if DEPTH || STENCIL
Brian Paule4b23562005-05-04 20:11:35 +0000102 /* draw diamond-shaped stencil pattern */
103 glColor3f(0, 1, 0);
104 glBegin(GL_POLYGON);
105 glVertex2f(-0.2, 0.0);
106 glVertex2f( 0.0, -0.2);
107 glVertex2f( 0.2, 0.0);
108 glVertex2f( 0.0, 0.2);
109 glEnd();
Brian Paul64945412006-03-24 23:17:06 +0000110#endif
Brian Paule4b23562005-05-04 20:11:35 +0000111
112 /* draw teapot where stencil != 1 */
Brian Paul64945412006-03-24 23:17:06 +0000113#if STENCIL
Brian Paule4b23562005-05-04 20:11:35 +0000114 glStencilFunc(GL_NOTEQUAL, 1, ~0);
115 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
Brian Paul64945412006-03-24 23:17:06 +0000116#endif
Brian Paule4b23562005-05-04 20:11:35 +0000117
Brian Paul32fe2332005-11-16 14:48:11 +0000118 CheckError(__LINE__);
119
Briandf198d22007-12-04 10:48:05 -0700120 if (Wireframe) {
121 glPolygonMode(GL_FRONT, GL_LINE);
122 }
123 else {
124 glPolygonMode(GL_FRONT, GL_FILL);
125 }
126
127 if (Cull) {
128 /* cull back */
129 glCullFace(GL_BACK);
130 glEnable(GL_CULL_FACE);
131 }
132 else {
133 glDisable(GL_CULL_FACE);
134 }
135
Brian Paule4b23562005-05-04 20:11:35 +0000136#if 0
137 glBegin(GL_POLYGON);
138 glColor3f(1, 0, 0);
139 glVertex2f(-1, -1);
140 glColor3f(0, 1, 0);
141 glVertex2f(1, -1);
142 glColor3f(0, 0, 1);
143 glVertex2f(0, 1);
144 glEnd();
145#else
146 glEnable(GL_LIGHTING);
147 glEnable(GL_LIGHT0);
148 glPushMatrix();
149 glRotatef(0.5 * Rot, 1.0, 0.0, 0.0);
Briandf198d22007-12-04 10:48:05 -0700150 glFrontFace(GL_CW); /* Teapot patches backward */
Brian Paule4b23562005-05-04 20:11:35 +0000151 glutSolidTeapot(0.5);
Briandf198d22007-12-04 10:48:05 -0700152 glFrontFace(GL_CCW);
Brian Paule4b23562005-05-04 20:11:35 +0000153 glPopMatrix();
154 glDisable(GL_LIGHTING);
Brian Paul64945412006-03-24 23:17:06 +0000155 /*
156 PrintStencilHistogram(TexWidth, TexHeight);
157 */
Brian Paule4b23562005-05-04 20:11:35 +0000158#endif
Brian Paul64945412006-03-24 23:17:06 +0000159
Brian Paule4b23562005-05-04 20:11:35 +0000160 glDisable(GL_DEPTH_TEST);
161 glDisable(GL_STENCIL_TEST);
Briandf198d22007-12-04 10:48:05 -0700162 glDisable(GL_CULL_FACE);
163 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
Brian Paule4b23562005-05-04 20:11:35 +0000164
Brian Paul64945412006-03-24 23:17:06 +0000165#if DRAW
Brian Paule4b23562005-05-04 20:11:35 +0000166 /* Bind normal framebuffer */
167 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
Brian Paul64945412006-03-24 23:17:06 +0000168#endif
Brian Paule4b23562005-05-04 20:11:35 +0000169
170 CheckError(__LINE__);
171}
172
173
174
175static void
176Display(void)
177{
178 float ar = (float) Width / (float) Height;
179
180 RenderTexture();
181
182 /* draw textured quad in the window */
Brian Paul64945412006-03-24 23:17:06 +0000183#if DRAW
Brian Paule4b23562005-05-04 20:11:35 +0000184 glMatrixMode(GL_PROJECTION);
185 glLoadIdentity();
186 glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0);
187 glMatrixMode(GL_MODELVIEW);
188 glLoadIdentity();
189 glTranslatef(0.0, 0.0, -7.0);
190
191 glViewport(0, 0, Width, Height);
192
193 glClearColor(0.25, 0.25, 0.25, 0);
194 glClear(GL_COLOR_BUFFER_BIT);
195
196 glPushMatrix();
197 glRotatef(Rot, 0, 1, 0);
Brian Paul64945412006-03-24 23:17:06 +0000198 glEnable(TexTarget);
199 glBindTexture(TexTarget, TexObj);
Brian Paule4b23562005-05-04 20:11:35 +0000200 glBegin(GL_POLYGON);
201 glColor3f(0.25, 0.25, 0.25);
Brian Paul64945412006-03-24 23:17:06 +0000202 if (TexTarget == GL_TEXTURE_2D) {
203 glTexCoord2f(0, 0);
204 glVertex2f(-1, -1);
205 glTexCoord2f(1, 0);
206 glVertex2f(1, -1);
207 glColor3f(1.0, 1.0, 1.0);
208 glTexCoord2f(1, 1);
209 glVertex2f(1, 1);
210 glTexCoord2f(0, 1);
211 glVertex2f(-1, 1);
212 }
213 else {
214 assert(TexTarget == GL_TEXTURE_RECTANGLE_ARB);
215 glTexCoord2f(0, 0);
216 glVertex2f(-1, -1);
217 glTexCoord2f(TexWidth, 0);
218 glVertex2f(1, -1);
219 glColor3f(1.0, 1.0, 1.0);
220 glTexCoord2f(TexWidth, TexHeight);
221 glVertex2f(1, 1);
222 glTexCoord2f(0, TexHeight);
223 glVertex2f(-1, 1);
224 }
Brian Paule4b23562005-05-04 20:11:35 +0000225 glEnd();
226 glPopMatrix();
Brian Paul64945412006-03-24 23:17:06 +0000227 glDisable(TexTarget);
228#endif
229
Brian Paule4b23562005-05-04 20:11:35 +0000230 glutSwapBuffers();
231 CheckError(__LINE__);
232}
233
234
235static void
236Reshape(int width, int height)
237{
238 glViewport(0, 0, width, height);
239 Width = width;
240 Height = height;
241}
242
243
244static void
Brian Paul32fe2332005-11-16 14:48:11 +0000245CleanUp(void)
246{
Brian Paul64945412006-03-24 23:17:06 +0000247#if DEPTH
Brian Paul32fe2332005-11-16 14:48:11 +0000248 glDeleteRenderbuffersEXT(1, &DepthRB);
Brian Paul64945412006-03-24 23:17:06 +0000249#endif
250#if STENCIL
Brian Paul32fe2332005-11-16 14:48:11 +0000251 if (!UsePackedDepthStencil)
252 glDeleteRenderbuffersEXT(1, &StencilRB);
Brian Paul64945412006-03-24 23:17:06 +0000253#endif
Brian Paul32fe2332005-11-16 14:48:11 +0000254 glDeleteFramebuffersEXT(1, &MyFB);
255
256 glDeleteTextures(1, &TexObj);
257
Brian2282d812007-03-06 16:33:00 -0700258 glutDestroyWindow(Win);
259
Brian Paul32fe2332005-11-16 14:48:11 +0000260 exit(0);
261}
262
263
264static void
Brian Paule4b23562005-05-04 20:11:35 +0000265Key(unsigned char key, int x, int y)
266{
267 (void) x;
268 (void) y;
269 switch (key) {
Briandf198d22007-12-04 10:48:05 -0700270 case 'a':
271 Anim = !Anim;
272 if (Anim)
273 glutIdleFunc(Idle);
274 else
275 glutIdleFunc(NULL);
276 break;
277 case 'c':
278 Cull = !Cull;
279 break;
280 case 'w':
281 Wireframe = !Wireframe;
282 break;
283 case 's':
284 Rot += 2.0;
285 break;
286 case 'S':
287 Rot -= 2.0;
288 break;
289 case 27:
290 CleanUp();
291 break;
Brian Paule4b23562005-05-04 20:11:35 +0000292 }
293 glutPostRedisplay();
294}
295
296
297static void
Briandf198d22007-12-04 10:48:05 -0700298Usage(void)
299{
300 printf("Usage:\n");
301 printf(" a Toggle animation\n");
302 printf(" s/s Step/rotate\n");
303 printf(" c Toggle back-face culling\n");
304 printf(" w Toggle wireframe mode (front-face only)\n");
305 printf(" Esc Exit\n");
306}
307
308
309static void
Brian Paul32fe2332005-11-16 14:48:11 +0000310Init(int argc, char *argv[])
Brian Paule4b23562005-05-04 20:11:35 +0000311{
Brian Paul64945412006-03-24 23:17:06 +0000312 static const GLfloat mat[4] = { 1.0, 0.5, 0.5, 1.0 };
Brian Paule4b23562005-05-04 20:11:35 +0000313 GLint i;
314
315 if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
316 printf("GL_EXT_framebuffer_object not found!\n");
317 exit(0);
318 }
Brian Paul32fe2332005-11-16 14:48:11 +0000319
320 if (argc > 1 && strcmp(argv[1], "-ds") == 0) {
321 if (!glutExtensionSupported("GL_EXT_packed_depth_stencil")) {
322 printf("GL_EXT_packed_depth_stencil not found!\n");
323 exit(0);
324 }
325 UsePackedDepthStencil = GL_TRUE;
326 printf("Using GL_EXT_packed_depth_stencil\n");
327 }
328
Brian Paule4b23562005-05-04 20:11:35 +0000329 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
330
Brian Paul7edf1e82005-10-04 15:16:27 +0000331 /* gen framebuffer id, delete it, do some assertions, just for testing */
Brian Paule4b23562005-05-04 20:11:35 +0000332 glGenFramebuffersEXT(1, &MyFB);
333 assert(MyFB);
Brian Paul9e920fb2005-10-04 15:01:51 +0000334 assert(!glIsFramebufferEXT(MyFB));
Brian Paule4b23562005-05-04 20:11:35 +0000335 glDeleteFramebuffersEXT(1, &MyFB);
336 assert(!glIsFramebufferEXT(MyFB));
337 /* Note, continue to use MyFB below */
338
339 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
340 assert(glIsFramebufferEXT(MyFB));
341 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &i);
342 assert(i == MyFB);
343
Brian Paul64945412006-03-24 23:17:06 +0000344 /* Make texture object/image */
345 glGenTextures(1, &TexObj);
346 glBindTexture(TexTarget, TexObj);
347 /* make two image levels */
348 glTexImage2D(TexTarget, 0, TexIntFormat, TexWidth, TexHeight, 0,
349 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
350 glTexImage2D(TexTarget, 1, TexIntFormat, TexWidth/2, TexHeight/2, 0,
351 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
352 TexWidth = TexWidth >> TextureLevel;
353 TexHeight = TexHeight >> TextureLevel;
354
355 glTexParameteri(TexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
356 glTexParameteri(TexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
357 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
358 glTexParameteri(TexTarget, GL_TEXTURE_BASE_LEVEL, TextureLevel);
359 glTexParameteri(TexTarget, GL_TEXTURE_MAX_LEVEL, TextureLevel);
360
361 CheckError(__LINE__);
362
363 /* Render color to texture */
364 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
365 TexTarget, TexObj, TextureLevel);
366
367
368#if DEPTH
Brian Paule4b23562005-05-04 20:11:35 +0000369 /* make depth renderbuffer */
370 glGenRenderbuffersEXT(1, &DepthRB);
371 assert(DepthRB);
Brian Paul9e920fb2005-10-04 15:01:51 +0000372 assert(!glIsRenderbufferEXT(DepthRB));
Brian Paule4b23562005-05-04 20:11:35 +0000373 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRB);
Brian Paul7edf1e82005-10-04 15:16:27 +0000374 assert(glIsRenderbufferEXT(DepthRB));
Brian Paul32fe2332005-11-16 14:48:11 +0000375 if (UsePackedDepthStencil)
376 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT,
377 TexWidth, TexHeight);
378 else
379 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
380 TexWidth, TexHeight);
381 CheckError(__LINE__);
Brian Paul58a95732005-07-01 01:34:29 +0000382 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
383 GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
Brian Paul32fe2332005-11-16 14:48:11 +0000384 CheckError(__LINE__);
Brian Paul58a95732005-07-01 01:34:29 +0000385 printf("Depth renderbuffer size = %d bits\n", i);
386 assert(i > 0);
Brian Paule4b23562005-05-04 20:11:35 +0000387
Brian Paule4b23562005-05-04 20:11:35 +0000388 /* attach DepthRB to MyFB */
389 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
390 GL_RENDERBUFFER_EXT, DepthRB);
Brian Paul64945412006-03-24 23:17:06 +0000391#endif
Brian Paule4b23562005-05-04 20:11:35 +0000392
Brian Paul32fe2332005-11-16 14:48:11 +0000393 CheckError(__LINE__);
394
Brian Paul64945412006-03-24 23:17:06 +0000395#if STENCIL
Brian Paul32fe2332005-11-16 14:48:11 +0000396 if (UsePackedDepthStencil) {
397 /* DepthRb is a combined depth/stencil renderbuffer */
398 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
399 GL_STENCIL_ATTACHMENT_EXT,
400 GL_RENDERBUFFER_EXT, DepthRB);
401 }
402 else {
403 /* make stencil renderbuffer */
404 glGenRenderbuffersEXT(1, &StencilRB);
405 assert(StencilRB);
406 assert(!glIsRenderbufferEXT(StencilRB));
407 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilRB);
408 assert(glIsRenderbufferEXT(StencilRB));
409 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX,
410 TexWidth, TexHeight);
411 /* attach StencilRB to MyFB */
412 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
413 GL_STENCIL_ATTACHMENT_EXT,
414 GL_RENDERBUFFER_EXT, StencilRB);
415 }
416 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
417 GL_RENDERBUFFER_STENCIL_SIZE_EXT, &i);
418 CheckError(__LINE__);
419 printf("Stencil renderbuffer size = %d bits\n", i);
420 assert(i > 0);
Brian Paul64945412006-03-24 23:17:06 +0000421#endif
Brian Paule4b23562005-05-04 20:11:35 +0000422
Brian Paul64945412006-03-24 23:17:06 +0000423 CheckError(__LINE__);
Brian Paule4b23562005-05-04 20:11:35 +0000424
425 /* bind regular framebuffer */
426 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
427
Brian Paul32fe2332005-11-16 14:48:11 +0000428
Brian Paul64945412006-03-24 23:17:06 +0000429 /* lighting */
430 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat);
Brian Paule4b23562005-05-04 20:11:35 +0000431}
432
433
434int
435main(int argc, char *argv[])
436{
437 glutInit(&argc, argv);
438 glutInitWindowPosition(0, 0);
439 glutInitWindowSize(Width, Height);
440 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
Brian2282d812007-03-06 16:33:00 -0700441 Win = glutCreateWindow(argv[0]);
Brian Paule4b23562005-05-04 20:11:35 +0000442 glutReshapeFunc(Reshape);
443 glutKeyboardFunc(Key);
444 glutDisplayFunc(Display);
445 if (Anim)
446 glutIdleFunc(Idle);
Brian Paul32fe2332005-11-16 14:48:11 +0000447 Init(argc, argv);
Briandf198d22007-12-04 10:48:05 -0700448 Usage();
Brian Paule4b23562005-05-04 20:11:35 +0000449 glutMainLoop();
450 return 0;
451}