blob: fa231abddb63f79ed60a799ef967c65577dee5a5 [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 Paulaed74032009-01-19 16:12:17 -0700313 GLboolean ARB_fbo = glutExtensionSupported("GL_ARB_framebuffer_object");
Brian Paule4b23562005-05-04 20:11:35 +0000314 GLint i;
315
316 if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
317 printf("GL_EXT_framebuffer_object not found!\n");
318 exit(0);
319 }
Brian Paul32fe2332005-11-16 14:48:11 +0000320
321 if (argc > 1 && strcmp(argv[1], "-ds") == 0) {
322 if (!glutExtensionSupported("GL_EXT_packed_depth_stencil")) {
323 printf("GL_EXT_packed_depth_stencil not found!\n");
324 exit(0);
325 }
326 UsePackedDepthStencil = GL_TRUE;
327 printf("Using GL_EXT_packed_depth_stencil\n");
328 }
329
Brian Paule4b23562005-05-04 20:11:35 +0000330 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
331
Brian Paul7edf1e82005-10-04 15:16:27 +0000332 /* gen framebuffer id, delete it, do some assertions, just for testing */
Brian Paule4b23562005-05-04 20:11:35 +0000333 glGenFramebuffersEXT(1, &MyFB);
334 assert(MyFB);
Brian Paul9e920fb2005-10-04 15:01:51 +0000335 assert(!glIsFramebufferEXT(MyFB));
Brian Paulaed74032009-01-19 16:12:17 -0700336 if (!ARB_fbo) {
337 glDeleteFramebuffersEXT(1, &MyFB);
338 assert(!glIsFramebufferEXT(MyFB));
339 }
Brian Paule4b23562005-05-04 20:11:35 +0000340 /* Note, continue to use MyFB below */
341
342 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
343 assert(glIsFramebufferEXT(MyFB));
344 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &i);
345 assert(i == MyFB);
346
Brian Paul64945412006-03-24 23:17:06 +0000347 /* Make texture object/image */
348 glGenTextures(1, &TexObj);
349 glBindTexture(TexTarget, TexObj);
350 /* make two image levels */
351 glTexImage2D(TexTarget, 0, TexIntFormat, TexWidth, TexHeight, 0,
352 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
353 glTexImage2D(TexTarget, 1, TexIntFormat, TexWidth/2, TexHeight/2, 0,
354 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
355 TexWidth = TexWidth >> TextureLevel;
356 TexHeight = TexHeight >> TextureLevel;
357
358 glTexParameteri(TexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
359 glTexParameteri(TexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
360 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
361 glTexParameteri(TexTarget, GL_TEXTURE_BASE_LEVEL, TextureLevel);
362 glTexParameteri(TexTarget, GL_TEXTURE_MAX_LEVEL, TextureLevel);
363
364 CheckError(__LINE__);
365
366 /* Render color to texture */
367 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
368 TexTarget, TexObj, TextureLevel);
369
370
371#if DEPTH
Brian Paule4b23562005-05-04 20:11:35 +0000372 /* make depth renderbuffer */
373 glGenRenderbuffersEXT(1, &DepthRB);
374 assert(DepthRB);
Brian Paul9e920fb2005-10-04 15:01:51 +0000375 assert(!glIsRenderbufferEXT(DepthRB));
Brian Paule4b23562005-05-04 20:11:35 +0000376 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRB);
Brian Paul7edf1e82005-10-04 15:16:27 +0000377 assert(glIsRenderbufferEXT(DepthRB));
Brian Paul32fe2332005-11-16 14:48:11 +0000378 if (UsePackedDepthStencil)
379 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT,
380 TexWidth, TexHeight);
381 else
382 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
383 TexWidth, TexHeight);
384 CheckError(__LINE__);
Brian Paul58a95732005-07-01 01:34:29 +0000385 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
386 GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
Brian Paul32fe2332005-11-16 14:48:11 +0000387 CheckError(__LINE__);
Brian Paul58a95732005-07-01 01:34:29 +0000388 printf("Depth renderbuffer size = %d bits\n", i);
389 assert(i > 0);
Brian Paule4b23562005-05-04 20:11:35 +0000390
Brian Paule4b23562005-05-04 20:11:35 +0000391 /* attach DepthRB to MyFB */
392 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
393 GL_RENDERBUFFER_EXT, DepthRB);
Brian Paul64945412006-03-24 23:17:06 +0000394#endif
Brian Paule4b23562005-05-04 20:11:35 +0000395
Brian Paul32fe2332005-11-16 14:48:11 +0000396 CheckError(__LINE__);
397
Brian Paul64945412006-03-24 23:17:06 +0000398#if STENCIL
Brian Paul32fe2332005-11-16 14:48:11 +0000399 if (UsePackedDepthStencil) {
400 /* DepthRb is a combined depth/stencil renderbuffer */
401 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
402 GL_STENCIL_ATTACHMENT_EXT,
403 GL_RENDERBUFFER_EXT, DepthRB);
404 }
405 else {
406 /* make stencil renderbuffer */
407 glGenRenderbuffersEXT(1, &StencilRB);
408 assert(StencilRB);
409 assert(!glIsRenderbufferEXT(StencilRB));
410 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilRB);
411 assert(glIsRenderbufferEXT(StencilRB));
412 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX,
413 TexWidth, TexHeight);
414 /* attach StencilRB to MyFB */
415 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
416 GL_STENCIL_ATTACHMENT_EXT,
417 GL_RENDERBUFFER_EXT, StencilRB);
418 }
419 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
420 GL_RENDERBUFFER_STENCIL_SIZE_EXT, &i);
421 CheckError(__LINE__);
422 printf("Stencil renderbuffer size = %d bits\n", i);
423 assert(i > 0);
Brian Paul64945412006-03-24 23:17:06 +0000424#endif
Brian Paule4b23562005-05-04 20:11:35 +0000425
Brian Paul64945412006-03-24 23:17:06 +0000426 CheckError(__LINE__);
Brian Paule4b23562005-05-04 20:11:35 +0000427
428 /* bind regular framebuffer */
429 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
430
Brian Paul32fe2332005-11-16 14:48:11 +0000431
Brian Paul64945412006-03-24 23:17:06 +0000432 /* lighting */
433 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat);
Brian Paule4b23562005-05-04 20:11:35 +0000434}
435
436
437int
438main(int argc, char *argv[])
439{
440 glutInit(&argc, argv);
441 glutInitWindowPosition(0, 0);
442 glutInitWindowSize(Width, Height);
443 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
Brian2282d812007-03-06 16:33:00 -0700444 Win = glutCreateWindow(argv[0]);
Brian Paule4b23562005-05-04 20:11:35 +0000445 glutReshapeFunc(Reshape);
446 glutKeyboardFunc(Key);
447 glutDisplayFunc(Display);
448 if (Anim)
449 glutIdleFunc(Idle);
Brian Paul32fe2332005-11-16 14:48:11 +0000450 Init(argc, argv);
Briandf198d22007-12-04 10:48:05 -0700451 Usage();
Brian Paule4b23562005-05-04 20:11:35 +0000452 glutMainLoop();
453 return 0;
454}