blob: 13a29db3f35d556ff17c04eacdf4a72232bb1c60 [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
26static int Width = 400, Height = 400;
Brian Paul64945412006-03-24 23:17:06 +000027
28static GLenum TexTarget = GL_TEXTURE_2D; /*GL_TEXTURE_RECTANGLE_ARB;*/
Brian Paule4b23562005-05-04 20:11:35 +000029static int TexWidth = 512, TexHeight = 512;
Brian Paul64945412006-03-24 23:17:06 +000030/*static int TexWidth = 600, TexHeight = 600;*/
31
Brian Paule4b23562005-05-04 20:11:35 +000032static GLuint MyFB;
33static GLuint TexObj;
34static GLuint DepthRB, StencilRB;
35static GLboolean Anim = GL_FALSE;
36static GLfloat Rot = 0.0;
Brian Paul32fe2332005-11-16 14:48:11 +000037static GLboolean UsePackedDepthStencil = GL_FALSE;
Brian Paul64945412006-03-24 23:17:06 +000038static GLuint TextureLevel = 1; /* which texture level to render to */
39static GLenum TexIntFormat = GL_RGB; /* either GL_RGB or GL_RGBA */
Brian Paule4b23562005-05-04 20:11:35 +000040
41
42static void
43CheckError(int line)
44{
45 GLenum err = glGetError();
46 if (err) {
47 printf("GL Error 0x%x at line %d\n", (int) err, line);
48 }
49}
50
51
52static void
53Idle(void)
54{
Brian Paul64945412006-03-24 23:17:06 +000055 Rot = glutGet(GLUT_ELAPSED_TIME) * 0.1;
Brian Paule4b23562005-05-04 20:11:35 +000056 glutPostRedisplay();
57}
58
59
60static void
61RenderTexture(void)
62{
Brian Paule4b23562005-05-04 20:11:35 +000063 GLenum status;
64
65 glMatrixMode(GL_PROJECTION);
66 glLoadIdentity();
67 glOrtho(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
68 glMatrixMode(GL_MODELVIEW);
69 glLoadIdentity();
70 glTranslatef(0.0, 0.0, -15.0);
71
Brian Paul7edf1e82005-10-04 15:16:27 +000072 /* draw to texture image */
Brian Paule4b23562005-05-04 20:11:35 +000073 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
Brian Paule4b23562005-05-04 20:11:35 +000074
75 status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
76 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
77 printf("Framebuffer incomplete!!!\n");
78 }
79
80 glViewport(0, 0, TexWidth, TexHeight);
81
82 glClearColor(0.5, 0.5, 1.0, 0.0);
83 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
Brian Paul32fe2332005-11-16 14:48:11 +000084 CheckError(__LINE__);
Brian Paule4b23562005-05-04 20:11:35 +000085
Brian Paul64945412006-03-24 23:17:06 +000086#if DEPTH
Brian Paule4b23562005-05-04 20:11:35 +000087 glEnable(GL_DEPTH_TEST);
Brian Paul64945412006-03-24 23:17:06 +000088#endif
89
90#if STENCIL
Brian Paule4b23562005-05-04 20:11:35 +000091 glEnable(GL_STENCIL_TEST);
92 glStencilFunc(GL_NEVER, 1, ~0);
93 glStencilOp(GL_REPLACE, GL_KEEP, GL_REPLACE);
Brian Paul64945412006-03-24 23:17:06 +000094#endif
Brian Paule4b23562005-05-04 20:11:35 +000095
Brian Paul32fe2332005-11-16 14:48:11 +000096 CheckError(__LINE__);
97
Brian Paul64945412006-03-24 23:17:06 +000098#if DEPTH || STENCIL
Brian Paule4b23562005-05-04 20:11:35 +000099 /* draw diamond-shaped stencil pattern */
100 glColor3f(0, 1, 0);
101 glBegin(GL_POLYGON);
102 glVertex2f(-0.2, 0.0);
103 glVertex2f( 0.0, -0.2);
104 glVertex2f( 0.2, 0.0);
105 glVertex2f( 0.0, 0.2);
106 glEnd();
Brian Paul64945412006-03-24 23:17:06 +0000107#endif
Brian Paule4b23562005-05-04 20:11:35 +0000108
109 /* draw teapot where stencil != 1 */
Brian Paul64945412006-03-24 23:17:06 +0000110#if STENCIL
Brian Paule4b23562005-05-04 20:11:35 +0000111 glStencilFunc(GL_NOTEQUAL, 1, ~0);
112 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
Brian Paul64945412006-03-24 23:17:06 +0000113#endif
Brian Paule4b23562005-05-04 20:11:35 +0000114
Brian Paul32fe2332005-11-16 14:48:11 +0000115 CheckError(__LINE__);
116
Brian Paule4b23562005-05-04 20:11:35 +0000117#if 0
118 glBegin(GL_POLYGON);
119 glColor3f(1, 0, 0);
120 glVertex2f(-1, -1);
121 glColor3f(0, 1, 0);
122 glVertex2f(1, -1);
123 glColor3f(0, 0, 1);
124 glVertex2f(0, 1);
125 glEnd();
126#else
127 glEnable(GL_LIGHTING);
128 glEnable(GL_LIGHT0);
129 glPushMatrix();
130 glRotatef(0.5 * Rot, 1.0, 0.0, 0.0);
131 glutSolidTeapot(0.5);
132 glPopMatrix();
133 glDisable(GL_LIGHTING);
Brian Paul64945412006-03-24 23:17:06 +0000134 /*
135 PrintStencilHistogram(TexWidth, TexHeight);
136 */
Brian Paule4b23562005-05-04 20:11:35 +0000137#endif
Brian Paul64945412006-03-24 23:17:06 +0000138
Brian Paule4b23562005-05-04 20:11:35 +0000139 glDisable(GL_DEPTH_TEST);
140 glDisable(GL_STENCIL_TEST);
141
Brian Paul64945412006-03-24 23:17:06 +0000142#if DRAW
Brian Paule4b23562005-05-04 20:11:35 +0000143 /* Bind normal framebuffer */
144 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
Brian Paul64945412006-03-24 23:17:06 +0000145#endif
Brian Paule4b23562005-05-04 20:11:35 +0000146
147 CheckError(__LINE__);
148}
149
150
151
152static void
153Display(void)
154{
155 float ar = (float) Width / (float) Height;
156
157 RenderTexture();
158
159 /* draw textured quad in the window */
Brian Paul64945412006-03-24 23:17:06 +0000160#if DRAW
Brian Paule4b23562005-05-04 20:11:35 +0000161 glMatrixMode(GL_PROJECTION);
162 glLoadIdentity();
163 glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0);
164 glMatrixMode(GL_MODELVIEW);
165 glLoadIdentity();
166 glTranslatef(0.0, 0.0, -7.0);
167
168 glViewport(0, 0, Width, Height);
169
170 glClearColor(0.25, 0.25, 0.25, 0);
171 glClear(GL_COLOR_BUFFER_BIT);
172
173 glPushMatrix();
174 glRotatef(Rot, 0, 1, 0);
Brian Paul64945412006-03-24 23:17:06 +0000175 glEnable(TexTarget);
176 glBindTexture(TexTarget, TexObj);
Brian Paule4b23562005-05-04 20:11:35 +0000177 glBegin(GL_POLYGON);
178 glColor3f(0.25, 0.25, 0.25);
Brian Paul64945412006-03-24 23:17:06 +0000179 if (TexTarget == GL_TEXTURE_2D) {
180 glTexCoord2f(0, 0);
181 glVertex2f(-1, -1);
182 glTexCoord2f(1, 0);
183 glVertex2f(1, -1);
184 glColor3f(1.0, 1.0, 1.0);
185 glTexCoord2f(1, 1);
186 glVertex2f(1, 1);
187 glTexCoord2f(0, 1);
188 glVertex2f(-1, 1);
189 }
190 else {
191 assert(TexTarget == GL_TEXTURE_RECTANGLE_ARB);
192 glTexCoord2f(0, 0);
193 glVertex2f(-1, -1);
194 glTexCoord2f(TexWidth, 0);
195 glVertex2f(1, -1);
196 glColor3f(1.0, 1.0, 1.0);
197 glTexCoord2f(TexWidth, TexHeight);
198 glVertex2f(1, 1);
199 glTexCoord2f(0, TexHeight);
200 glVertex2f(-1, 1);
201 }
Brian Paule4b23562005-05-04 20:11:35 +0000202 glEnd();
203 glPopMatrix();
Brian Paul64945412006-03-24 23:17:06 +0000204 glDisable(TexTarget);
205#endif
206
Brian Paule4b23562005-05-04 20:11:35 +0000207 glutSwapBuffers();
208 CheckError(__LINE__);
209}
210
211
212static void
213Reshape(int width, int height)
214{
215 glViewport(0, 0, width, height);
216 Width = width;
217 Height = height;
218}
219
220
221static void
Brian Paul32fe2332005-11-16 14:48:11 +0000222CleanUp(void)
223{
Brian Paul64945412006-03-24 23:17:06 +0000224#if DEPTH
Brian Paul32fe2332005-11-16 14:48:11 +0000225 glDeleteRenderbuffersEXT(1, &DepthRB);
Brian Paul64945412006-03-24 23:17:06 +0000226#endif
227#if STENCIL
Brian Paul32fe2332005-11-16 14:48:11 +0000228 if (!UsePackedDepthStencil)
229 glDeleteRenderbuffersEXT(1, &StencilRB);
Brian Paul64945412006-03-24 23:17:06 +0000230#endif
Brian Paul32fe2332005-11-16 14:48:11 +0000231 glDeleteFramebuffersEXT(1, &MyFB);
232
233 glDeleteTextures(1, &TexObj);
234
235 exit(0);
236}
237
238
239static void
Brian Paule4b23562005-05-04 20:11:35 +0000240Key(unsigned char key, int x, int y)
241{
242 (void) x;
243 (void) y;
244 switch (key) {
245 case 'a':
246 Anim = !Anim;
247 if (Anim)
248 glutIdleFunc(Idle);
249 else
250 glutIdleFunc(NULL);
251 break;
Brian Paul32fe2332005-11-16 14:48:11 +0000252 case 's':
253 Rot += 2.0;
254 break;
Brian Paule4b23562005-05-04 20:11:35 +0000255 case 27:
Brian Paul32fe2332005-11-16 14:48:11 +0000256 CleanUp();
Brian Paule4b23562005-05-04 20:11:35 +0000257 break;
258 }
259 glutPostRedisplay();
260}
261
262
263static void
Brian Paul32fe2332005-11-16 14:48:11 +0000264Init(int argc, char *argv[])
Brian Paule4b23562005-05-04 20:11:35 +0000265{
Brian Paul64945412006-03-24 23:17:06 +0000266 static const GLfloat mat[4] = { 1.0, 0.5, 0.5, 1.0 };
Brian Paule4b23562005-05-04 20:11:35 +0000267 GLint i;
268
269 if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
270 printf("GL_EXT_framebuffer_object not found!\n");
271 exit(0);
272 }
Brian Paul32fe2332005-11-16 14:48:11 +0000273
274 if (argc > 1 && strcmp(argv[1], "-ds") == 0) {
275 if (!glutExtensionSupported("GL_EXT_packed_depth_stencil")) {
276 printf("GL_EXT_packed_depth_stencil not found!\n");
277 exit(0);
278 }
279 UsePackedDepthStencil = GL_TRUE;
280 printf("Using GL_EXT_packed_depth_stencil\n");
281 }
282
Brian Paule4b23562005-05-04 20:11:35 +0000283 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
284
Brian Paul7edf1e82005-10-04 15:16:27 +0000285 /* gen framebuffer id, delete it, do some assertions, just for testing */
Brian Paule4b23562005-05-04 20:11:35 +0000286 glGenFramebuffersEXT(1, &MyFB);
287 assert(MyFB);
Brian Paul9e920fb2005-10-04 15:01:51 +0000288 assert(!glIsFramebufferEXT(MyFB));
Brian Paule4b23562005-05-04 20:11:35 +0000289 glDeleteFramebuffersEXT(1, &MyFB);
290 assert(!glIsFramebufferEXT(MyFB));
291 /* Note, continue to use MyFB below */
292
293 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
294 assert(glIsFramebufferEXT(MyFB));
295 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &i);
296 assert(i == MyFB);
297
Brian Paul64945412006-03-24 23:17:06 +0000298 /* Make texture object/image */
299 glGenTextures(1, &TexObj);
300 glBindTexture(TexTarget, TexObj);
301 /* make two image levels */
302 glTexImage2D(TexTarget, 0, TexIntFormat, TexWidth, TexHeight, 0,
303 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
304 glTexImage2D(TexTarget, 1, TexIntFormat, TexWidth/2, TexHeight/2, 0,
305 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
306 TexWidth = TexWidth >> TextureLevel;
307 TexHeight = TexHeight >> TextureLevel;
308
309 glTexParameteri(TexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
310 glTexParameteri(TexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
311 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
312 glTexParameteri(TexTarget, GL_TEXTURE_BASE_LEVEL, TextureLevel);
313 glTexParameteri(TexTarget, GL_TEXTURE_MAX_LEVEL, TextureLevel);
314
315 CheckError(__LINE__);
316
317 /* Render color to texture */
318 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
319 TexTarget, TexObj, TextureLevel);
320
321
322#if DEPTH
Brian Paule4b23562005-05-04 20:11:35 +0000323 /* make depth renderbuffer */
324 glGenRenderbuffersEXT(1, &DepthRB);
325 assert(DepthRB);
Brian Paul9e920fb2005-10-04 15:01:51 +0000326 assert(!glIsRenderbufferEXT(DepthRB));
Brian Paule4b23562005-05-04 20:11:35 +0000327 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRB);
Brian Paul7edf1e82005-10-04 15:16:27 +0000328 assert(glIsRenderbufferEXT(DepthRB));
Brian Paul32fe2332005-11-16 14:48:11 +0000329 if (UsePackedDepthStencil)
330 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT,
331 TexWidth, TexHeight);
332 else
333 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
334 TexWidth, TexHeight);
335 CheckError(__LINE__);
Brian Paul58a95732005-07-01 01:34:29 +0000336 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
337 GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
Brian Paul32fe2332005-11-16 14:48:11 +0000338 CheckError(__LINE__);
Brian Paul58a95732005-07-01 01:34:29 +0000339 printf("Depth renderbuffer size = %d bits\n", i);
340 assert(i > 0);
Brian Paule4b23562005-05-04 20:11:35 +0000341
Brian Paule4b23562005-05-04 20:11:35 +0000342 /* attach DepthRB to MyFB */
343 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
344 GL_RENDERBUFFER_EXT, DepthRB);
Brian Paul64945412006-03-24 23:17:06 +0000345#endif
Brian Paule4b23562005-05-04 20:11:35 +0000346
Brian Paul32fe2332005-11-16 14:48:11 +0000347 CheckError(__LINE__);
348
Brian Paul64945412006-03-24 23:17:06 +0000349#if STENCIL
Brian Paul32fe2332005-11-16 14:48:11 +0000350 if (UsePackedDepthStencil) {
351 /* DepthRb is a combined depth/stencil renderbuffer */
352 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
353 GL_STENCIL_ATTACHMENT_EXT,
354 GL_RENDERBUFFER_EXT, DepthRB);
355 }
356 else {
357 /* make stencil renderbuffer */
358 glGenRenderbuffersEXT(1, &StencilRB);
359 assert(StencilRB);
360 assert(!glIsRenderbufferEXT(StencilRB));
361 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilRB);
362 assert(glIsRenderbufferEXT(StencilRB));
363 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX,
364 TexWidth, TexHeight);
365 /* attach StencilRB to MyFB */
366 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
367 GL_STENCIL_ATTACHMENT_EXT,
368 GL_RENDERBUFFER_EXT, StencilRB);
369 }
370 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
371 GL_RENDERBUFFER_STENCIL_SIZE_EXT, &i);
372 CheckError(__LINE__);
373 printf("Stencil renderbuffer size = %d bits\n", i);
374 assert(i > 0);
Brian Paul64945412006-03-24 23:17:06 +0000375#endif
Brian Paule4b23562005-05-04 20:11:35 +0000376
Brian Paul64945412006-03-24 23:17:06 +0000377 CheckError(__LINE__);
Brian Paule4b23562005-05-04 20:11:35 +0000378
379 /* bind regular framebuffer */
380 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
381
Brian Paul32fe2332005-11-16 14:48:11 +0000382
Brian Paul64945412006-03-24 23:17:06 +0000383 /* lighting */
384 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat);
Brian Paule4b23562005-05-04 20:11:35 +0000385}
386
387
388int
389main(int argc, char *argv[])
390{
391 glutInit(&argc, argv);
392 glutInitWindowPosition(0, 0);
393 glutInitWindowSize(Width, Height);
394 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
395 glutCreateWindow(argv[0]);
396 glutReshapeFunc(Reshape);
397 glutKeyboardFunc(Key);
398 glutDisplayFunc(Display);
399 if (Anim)
400 glutIdleFunc(Idle);
Brian Paul32fe2332005-11-16 14:48:11 +0000401 Init(argc, argv);
Brian Paule4b23562005-05-04 20:11:35 +0000402 glutMainLoop();
403 return 0;
404}