blob: aa9f6171221ce5950b7d60e22dc38166f06a9d0d [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 */
Brian Paule4b23562005-05-04 20:11:35 +000041
42
43static void
44CheckError(int line)
45{
46 GLenum err = glGetError();
47 if (err) {
48 printf("GL Error 0x%x at line %d\n", (int) err, line);
49 }
50}
51
52
53static void
54Idle(void)
55{
Brian Paul64945412006-03-24 23:17:06 +000056 Rot = glutGet(GLUT_ELAPSED_TIME) * 0.1;
Brian Paule4b23562005-05-04 20:11:35 +000057 glutPostRedisplay();
58}
59
60
61static void
62RenderTexture(void)
63{
Brian Paule4b23562005-05-04 20:11:35 +000064 GLenum status;
65
66 glMatrixMode(GL_PROJECTION);
67 glLoadIdentity();
68 glOrtho(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
69 glMatrixMode(GL_MODELVIEW);
70 glLoadIdentity();
71 glTranslatef(0.0, 0.0, -15.0);
72
Brian Paul7edf1e82005-10-04 15:16:27 +000073 /* draw to texture image */
Brian Paule4b23562005-05-04 20:11:35 +000074 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
Brian Paule4b23562005-05-04 20:11:35 +000075
76 status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
77 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
78 printf("Framebuffer incomplete!!!\n");
79 }
80
81 glViewport(0, 0, TexWidth, TexHeight);
82
83 glClearColor(0.5, 0.5, 1.0, 0.0);
84 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
Brian Paul32fe2332005-11-16 14:48:11 +000085 CheckError(__LINE__);
Brian Paule4b23562005-05-04 20:11:35 +000086
Brian Paul64945412006-03-24 23:17:06 +000087#if DEPTH
Brian Paule4b23562005-05-04 20:11:35 +000088 glEnable(GL_DEPTH_TEST);
Brian Paul64945412006-03-24 23:17:06 +000089#endif
90
91#if STENCIL
Brian Paule4b23562005-05-04 20:11:35 +000092 glEnable(GL_STENCIL_TEST);
93 glStencilFunc(GL_NEVER, 1, ~0);
94 glStencilOp(GL_REPLACE, GL_KEEP, GL_REPLACE);
Brian Paul64945412006-03-24 23:17:06 +000095#endif
Brian Paule4b23562005-05-04 20:11:35 +000096
Brian Paul32fe2332005-11-16 14:48:11 +000097 CheckError(__LINE__);
98
Brian Paul64945412006-03-24 23:17:06 +000099#if DEPTH || STENCIL
Brian Paule4b23562005-05-04 20:11:35 +0000100 /* draw diamond-shaped stencil pattern */
101 glColor3f(0, 1, 0);
102 glBegin(GL_POLYGON);
103 glVertex2f(-0.2, 0.0);
104 glVertex2f( 0.0, -0.2);
105 glVertex2f( 0.2, 0.0);
106 glVertex2f( 0.0, 0.2);
107 glEnd();
Brian Paul64945412006-03-24 23:17:06 +0000108#endif
Brian Paule4b23562005-05-04 20:11:35 +0000109
110 /* draw teapot where stencil != 1 */
Brian Paul64945412006-03-24 23:17:06 +0000111#if STENCIL
Brian Paule4b23562005-05-04 20:11:35 +0000112 glStencilFunc(GL_NOTEQUAL, 1, ~0);
113 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
Brian Paul64945412006-03-24 23:17:06 +0000114#endif
Brian Paule4b23562005-05-04 20:11:35 +0000115
Brian Paul32fe2332005-11-16 14:48:11 +0000116 CheckError(__LINE__);
117
Brian Paule4b23562005-05-04 20:11:35 +0000118#if 0
119 glBegin(GL_POLYGON);
120 glColor3f(1, 0, 0);
121 glVertex2f(-1, -1);
122 glColor3f(0, 1, 0);
123 glVertex2f(1, -1);
124 glColor3f(0, 0, 1);
125 glVertex2f(0, 1);
126 glEnd();
127#else
128 glEnable(GL_LIGHTING);
129 glEnable(GL_LIGHT0);
130 glPushMatrix();
131 glRotatef(0.5 * Rot, 1.0, 0.0, 0.0);
132 glutSolidTeapot(0.5);
133 glPopMatrix();
134 glDisable(GL_LIGHTING);
Brian Paul64945412006-03-24 23:17:06 +0000135 /*
136 PrintStencilHistogram(TexWidth, TexHeight);
137 */
Brian Paule4b23562005-05-04 20:11:35 +0000138#endif
Brian Paul64945412006-03-24 23:17:06 +0000139
Brian Paule4b23562005-05-04 20:11:35 +0000140 glDisable(GL_DEPTH_TEST);
141 glDisable(GL_STENCIL_TEST);
142
Brian Paul64945412006-03-24 23:17:06 +0000143#if DRAW
Brian Paule4b23562005-05-04 20:11:35 +0000144 /* Bind normal framebuffer */
145 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
Brian Paul64945412006-03-24 23:17:06 +0000146#endif
Brian Paule4b23562005-05-04 20:11:35 +0000147
148 CheckError(__LINE__);
149}
150
151
152
153static void
154Display(void)
155{
156 float ar = (float) Width / (float) Height;
157
158 RenderTexture();
159
160 /* draw textured quad in the window */
Brian Paul64945412006-03-24 23:17:06 +0000161#if DRAW
Brian Paule4b23562005-05-04 20:11:35 +0000162 glMatrixMode(GL_PROJECTION);
163 glLoadIdentity();
164 glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0);
165 glMatrixMode(GL_MODELVIEW);
166 glLoadIdentity();
167 glTranslatef(0.0, 0.0, -7.0);
168
169 glViewport(0, 0, Width, Height);
170
171 glClearColor(0.25, 0.25, 0.25, 0);
172 glClear(GL_COLOR_BUFFER_BIT);
173
174 glPushMatrix();
175 glRotatef(Rot, 0, 1, 0);
Brian Paul64945412006-03-24 23:17:06 +0000176 glEnable(TexTarget);
177 glBindTexture(TexTarget, TexObj);
Brian Paule4b23562005-05-04 20:11:35 +0000178 glBegin(GL_POLYGON);
179 glColor3f(0.25, 0.25, 0.25);
Brian Paul64945412006-03-24 23:17:06 +0000180 if (TexTarget == GL_TEXTURE_2D) {
181 glTexCoord2f(0, 0);
182 glVertex2f(-1, -1);
183 glTexCoord2f(1, 0);
184 glVertex2f(1, -1);
185 glColor3f(1.0, 1.0, 1.0);
186 glTexCoord2f(1, 1);
187 glVertex2f(1, 1);
188 glTexCoord2f(0, 1);
189 glVertex2f(-1, 1);
190 }
191 else {
192 assert(TexTarget == GL_TEXTURE_RECTANGLE_ARB);
193 glTexCoord2f(0, 0);
194 glVertex2f(-1, -1);
195 glTexCoord2f(TexWidth, 0);
196 glVertex2f(1, -1);
197 glColor3f(1.0, 1.0, 1.0);
198 glTexCoord2f(TexWidth, TexHeight);
199 glVertex2f(1, 1);
200 glTexCoord2f(0, TexHeight);
201 glVertex2f(-1, 1);
202 }
Brian Paule4b23562005-05-04 20:11:35 +0000203 glEnd();
204 glPopMatrix();
Brian Paul64945412006-03-24 23:17:06 +0000205 glDisable(TexTarget);
206#endif
207
Brian Paule4b23562005-05-04 20:11:35 +0000208 glutSwapBuffers();
209 CheckError(__LINE__);
210}
211
212
213static void
214Reshape(int width, int height)
215{
216 glViewport(0, 0, width, height);
217 Width = width;
218 Height = height;
219}
220
221
222static void
Brian Paul32fe2332005-11-16 14:48:11 +0000223CleanUp(void)
224{
Brian Paul64945412006-03-24 23:17:06 +0000225#if DEPTH
Brian Paul32fe2332005-11-16 14:48:11 +0000226 glDeleteRenderbuffersEXT(1, &DepthRB);
Brian Paul64945412006-03-24 23:17:06 +0000227#endif
228#if STENCIL
Brian Paul32fe2332005-11-16 14:48:11 +0000229 if (!UsePackedDepthStencil)
230 glDeleteRenderbuffersEXT(1, &StencilRB);
Brian Paul64945412006-03-24 23:17:06 +0000231#endif
Brian Paul32fe2332005-11-16 14:48:11 +0000232 glDeleteFramebuffersEXT(1, &MyFB);
233
234 glDeleteTextures(1, &TexObj);
235
Brian2282d812007-03-06 16:33:00 -0700236 glutDestroyWindow(Win);
237
Brian Paul32fe2332005-11-16 14:48:11 +0000238 exit(0);
239}
240
241
242static void
Brian Paule4b23562005-05-04 20:11:35 +0000243Key(unsigned char key, int x, int y)
244{
245 (void) x;
246 (void) y;
247 switch (key) {
248 case 'a':
249 Anim = !Anim;
250 if (Anim)
251 glutIdleFunc(Idle);
252 else
253 glutIdleFunc(NULL);
254 break;
Brian Paul32fe2332005-11-16 14:48:11 +0000255 case 's':
256 Rot += 2.0;
257 break;
Brian Paule4b23562005-05-04 20:11:35 +0000258 case 27:
Brian Paul32fe2332005-11-16 14:48:11 +0000259 CleanUp();
Brian Paule4b23562005-05-04 20:11:35 +0000260 break;
261 }
262 glutPostRedisplay();
263}
264
265
266static void
Brian Paul32fe2332005-11-16 14:48:11 +0000267Init(int argc, char *argv[])
Brian Paule4b23562005-05-04 20:11:35 +0000268{
Brian Paul64945412006-03-24 23:17:06 +0000269 static const GLfloat mat[4] = { 1.0, 0.5, 0.5, 1.0 };
Brian Paule4b23562005-05-04 20:11:35 +0000270 GLint i;
271
272 if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
273 printf("GL_EXT_framebuffer_object not found!\n");
274 exit(0);
275 }
Brian Paul32fe2332005-11-16 14:48:11 +0000276
277 if (argc > 1 && strcmp(argv[1], "-ds") == 0) {
278 if (!glutExtensionSupported("GL_EXT_packed_depth_stencil")) {
279 printf("GL_EXT_packed_depth_stencil not found!\n");
280 exit(0);
281 }
282 UsePackedDepthStencil = GL_TRUE;
283 printf("Using GL_EXT_packed_depth_stencil\n");
284 }
285
Brian Paule4b23562005-05-04 20:11:35 +0000286 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
287
Brian Paul7edf1e82005-10-04 15:16:27 +0000288 /* gen framebuffer id, delete it, do some assertions, just for testing */
Brian Paule4b23562005-05-04 20:11:35 +0000289 glGenFramebuffersEXT(1, &MyFB);
290 assert(MyFB);
Brian Paul9e920fb2005-10-04 15:01:51 +0000291 assert(!glIsFramebufferEXT(MyFB));
Brian Paule4b23562005-05-04 20:11:35 +0000292 glDeleteFramebuffersEXT(1, &MyFB);
293 assert(!glIsFramebufferEXT(MyFB));
294 /* Note, continue to use MyFB below */
295
296 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
297 assert(glIsFramebufferEXT(MyFB));
298 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &i);
299 assert(i == MyFB);
300
Brian Paul64945412006-03-24 23:17:06 +0000301 /* Make texture object/image */
302 glGenTextures(1, &TexObj);
303 glBindTexture(TexTarget, TexObj);
304 /* make two image levels */
305 glTexImage2D(TexTarget, 0, TexIntFormat, TexWidth, TexHeight, 0,
306 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
307 glTexImage2D(TexTarget, 1, TexIntFormat, TexWidth/2, TexHeight/2, 0,
308 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
309 TexWidth = TexWidth >> TextureLevel;
310 TexHeight = TexHeight >> TextureLevel;
311
312 glTexParameteri(TexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
313 glTexParameteri(TexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
314 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
315 glTexParameteri(TexTarget, GL_TEXTURE_BASE_LEVEL, TextureLevel);
316 glTexParameteri(TexTarget, GL_TEXTURE_MAX_LEVEL, TextureLevel);
317
318 CheckError(__LINE__);
319
320 /* Render color to texture */
321 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
322 TexTarget, TexObj, TextureLevel);
323
324
325#if DEPTH
Brian Paule4b23562005-05-04 20:11:35 +0000326 /* make depth renderbuffer */
327 glGenRenderbuffersEXT(1, &DepthRB);
328 assert(DepthRB);
Brian Paul9e920fb2005-10-04 15:01:51 +0000329 assert(!glIsRenderbufferEXT(DepthRB));
Brian Paule4b23562005-05-04 20:11:35 +0000330 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRB);
Brian Paul7edf1e82005-10-04 15:16:27 +0000331 assert(glIsRenderbufferEXT(DepthRB));
Brian Paul32fe2332005-11-16 14:48:11 +0000332 if (UsePackedDepthStencil)
333 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT,
334 TexWidth, TexHeight);
335 else
336 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
337 TexWidth, TexHeight);
338 CheckError(__LINE__);
Brian Paul58a95732005-07-01 01:34:29 +0000339 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
340 GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
Brian Paul32fe2332005-11-16 14:48:11 +0000341 CheckError(__LINE__);
Brian Paul58a95732005-07-01 01:34:29 +0000342 printf("Depth renderbuffer size = %d bits\n", i);
343 assert(i > 0);
Brian Paule4b23562005-05-04 20:11:35 +0000344
Brian Paule4b23562005-05-04 20:11:35 +0000345 /* attach DepthRB to MyFB */
346 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
347 GL_RENDERBUFFER_EXT, DepthRB);
Brian Paul64945412006-03-24 23:17:06 +0000348#endif
Brian Paule4b23562005-05-04 20:11:35 +0000349
Brian Paul32fe2332005-11-16 14:48:11 +0000350 CheckError(__LINE__);
351
Brian Paul64945412006-03-24 23:17:06 +0000352#if STENCIL
Brian Paul32fe2332005-11-16 14:48:11 +0000353 if (UsePackedDepthStencil) {
354 /* DepthRb is a combined depth/stencil renderbuffer */
355 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
356 GL_STENCIL_ATTACHMENT_EXT,
357 GL_RENDERBUFFER_EXT, DepthRB);
358 }
359 else {
360 /* make stencil renderbuffer */
361 glGenRenderbuffersEXT(1, &StencilRB);
362 assert(StencilRB);
363 assert(!glIsRenderbufferEXT(StencilRB));
364 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilRB);
365 assert(glIsRenderbufferEXT(StencilRB));
366 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX,
367 TexWidth, TexHeight);
368 /* attach StencilRB to MyFB */
369 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
370 GL_STENCIL_ATTACHMENT_EXT,
371 GL_RENDERBUFFER_EXT, StencilRB);
372 }
373 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
374 GL_RENDERBUFFER_STENCIL_SIZE_EXT, &i);
375 CheckError(__LINE__);
376 printf("Stencil renderbuffer size = %d bits\n", i);
377 assert(i > 0);
Brian Paul64945412006-03-24 23:17:06 +0000378#endif
Brian Paule4b23562005-05-04 20:11:35 +0000379
Brian Paul64945412006-03-24 23:17:06 +0000380 CheckError(__LINE__);
Brian Paule4b23562005-05-04 20:11:35 +0000381
382 /* bind regular framebuffer */
383 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
384
Brian Paul32fe2332005-11-16 14:48:11 +0000385
Brian Paul64945412006-03-24 23:17:06 +0000386 /* lighting */
387 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat);
Brian Paule4b23562005-05-04 20:11:35 +0000388}
389
390
391int
392main(int argc, char *argv[])
393{
394 glutInit(&argc, argv);
395 glutInitWindowPosition(0, 0);
396 glutInitWindowSize(Width, Height);
397 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
Brian2282d812007-03-06 16:33:00 -0700398 Win = glutCreateWindow(argv[0]);
Brian Paule4b23562005-05-04 20:11:35 +0000399 glutReshapeFunc(Reshape);
400 glutKeyboardFunc(Key);
401 glutDisplayFunc(Display);
402 if (Anim)
403 glutIdleFunc(Idle);
Brian Paul32fe2332005-11-16 14:48:11 +0000404 Init(argc, argv);
Brian Paule4b23562005-05-04 20:11:35 +0000405 glutMainLoop();
406 return 0;
407}