2 * Test GL_EXT_framebuffer_object render-to-texture
4 * Draw a teapot into a texture image with stenciling.
5 * Then draw a textured quad using that texture.
12 #define GL_GLEXT_PROTOTYPES
27 static int Width
= 400, Height
= 400;
29 static GLenum TexTarget
= GL_TEXTURE_2D
; /*GL_TEXTURE_RECTANGLE_ARB;*/
30 static int TexWidth
= 512, TexHeight
= 512;
31 /*static int TexWidth = 600, TexHeight = 600;*/
35 static GLuint DepthRB
, StencilRB
;
36 static GLboolean Anim
= GL_FALSE
;
37 static GLfloat Rot
= 0.0;
38 static GLboolean UsePackedDepthStencil
= GL_FALSE
;
39 static GLuint TextureLevel
= 1; /* which texture level to render to */
40 static GLenum TexIntFormat
= GL_RGB
; /* either GL_RGB or GL_RGBA */
41 static GLboolean Cull
= GL_FALSE
;
42 static GLboolean Wireframe
= GL_FALSE
;
48 GLenum err
= glGetError();
50 printf("GL Error 0x%x at line %d\n", (int) err
, line
);
58 Rot
= glutGet(GLUT_ELAPSED_TIME
) * 0.1;
68 glMatrixMode(GL_PROJECTION
);
70 glOrtho(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
71 glMatrixMode(GL_MODELVIEW
);
73 glTranslatef(0.0, 0.0, -15.0);
75 /* draw to texture image */
76 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, MyFB
);
78 status
= glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT
);
79 if (status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
80 printf("Framebuffer incomplete!!!\n");
83 glViewport(0, 0, TexWidth
, TexHeight
);
85 glClearColor(0.5, 0.5, 1.0, 0.0);
86 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
90 glEnable(GL_DEPTH_TEST
);
94 glEnable(GL_STENCIL_TEST
);
95 glStencilFunc(GL_NEVER
, 1, ~0);
96 glStencilOp(GL_REPLACE
, GL_KEEP
, GL_REPLACE
);
102 /* draw diamond-shaped stencil pattern */
105 glVertex2f(-0.2, 0.0);
106 glVertex2f( 0.0, -0.2);
107 glVertex2f( 0.2, 0.0);
108 glVertex2f( 0.0, 0.2);
112 /* draw teapot where stencil != 1 */
114 glStencilFunc(GL_NOTEQUAL
, 1, ~0);
115 glStencilOp(GL_KEEP
, GL_KEEP
, GL_KEEP
);
118 CheckError(__LINE__
);
121 glPolygonMode(GL_FRONT
, GL_LINE
);
124 glPolygonMode(GL_FRONT
, GL_FILL
);
130 glEnable(GL_CULL_FACE
);
133 glDisable(GL_CULL_FACE
);
146 glEnable(GL_LIGHTING
);
149 glRotatef(0.5 * Rot
, 1.0, 0.0, 0.0);
150 glFrontFace(GL_CW
); /* Teapot patches backward */
151 glutSolidTeapot(0.5);
154 glDisable(GL_LIGHTING
);
156 PrintStencilHistogram(TexWidth, TexHeight);
160 glDisable(GL_DEPTH_TEST
);
161 glDisable(GL_STENCIL_TEST
);
162 glDisable(GL_CULL_FACE
);
163 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
166 /* Bind normal framebuffer */
167 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
170 CheckError(__LINE__
);
178 float ar
= (float) Width
/ (float) Height
;
182 /* draw textured quad in the window */
184 glMatrixMode(GL_PROJECTION
);
186 glFrustum(-ar
, ar
, -1.0, 1.0, 5.0, 25.0);
187 glMatrixMode(GL_MODELVIEW
);
189 glTranslatef(0.0, 0.0, -7.0);
191 glViewport(0, 0, Width
, Height
);
193 glClearColor(0.25, 0.25, 0.25, 0);
194 glClear(GL_COLOR_BUFFER_BIT
);
197 glRotatef(Rot
, 0, 1, 0);
199 glBindTexture(TexTarget
, TexObj
);
201 glColor3f(0.25, 0.25, 0.25);
202 if (TexTarget
== GL_TEXTURE_2D
) {
207 glColor3f(1.0, 1.0, 1.0);
214 assert(TexTarget
== GL_TEXTURE_RECTANGLE_ARB
);
217 glTexCoord2f(TexWidth
, 0);
219 glColor3f(1.0, 1.0, 1.0);
220 glTexCoord2f(TexWidth
, TexHeight
);
222 glTexCoord2f(0, TexHeight
);
227 glDisable(TexTarget
);
231 CheckError(__LINE__
);
236 Reshape(int width
, int height
)
238 glViewport(0, 0, width
, height
);
248 glDeleteRenderbuffersEXT(1, &DepthRB
);
251 if (!UsePackedDepthStencil
)
252 glDeleteRenderbuffersEXT(1, &StencilRB
);
254 glDeleteFramebuffersEXT(1, &MyFB
);
256 glDeleteTextures(1, &TexObj
);
258 glutDestroyWindow(Win
);
265 Key(unsigned char key
, int x
, int y
)
281 Wireframe
= !Wireframe
;
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");
310 Init(int argc
, char *argv
[])
312 static const GLfloat mat
[4] = { 1.0, 0.5, 0.5, 1.0 };
315 if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
316 printf("GL_EXT_framebuffer_object not found!\n");
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");
325 UsePackedDepthStencil
= GL_TRUE
;
326 printf("Using GL_EXT_packed_depth_stencil\n");
329 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
331 /* gen framebuffer id, delete it, do some assertions, just for testing */
332 glGenFramebuffersEXT(1, &MyFB
);
334 assert(!glIsFramebufferEXT(MyFB
));
335 glDeleteFramebuffersEXT(1, &MyFB
);
336 assert(!glIsFramebufferEXT(MyFB
));
337 /* Note, continue to use MyFB below */
339 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, MyFB
);
340 assert(glIsFramebufferEXT(MyFB
));
341 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &i
);
344 /* 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
;
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
);
361 CheckError(__LINE__
);
363 /* Render color to texture */
364 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT
, GL_COLOR_ATTACHMENT0_EXT
,
365 TexTarget
, TexObj
, TextureLevel
);
369 /* make depth renderbuffer */
370 glGenRenderbuffersEXT(1, &DepthRB
);
372 assert(!glIsRenderbufferEXT(DepthRB
));
373 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT
, DepthRB
);
374 assert(glIsRenderbufferEXT(DepthRB
));
375 if (UsePackedDepthStencil
)
376 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, GL_DEPTH_STENCIL_EXT
,
377 TexWidth
, TexHeight
);
379 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, GL_DEPTH_COMPONENT
,
380 TexWidth
, TexHeight
);
381 CheckError(__LINE__
);
382 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT
,
383 GL_RENDERBUFFER_DEPTH_SIZE_EXT
, &i
);
384 CheckError(__LINE__
);
385 printf("Depth renderbuffer size = %d bits\n", i
);
388 /* attach DepthRB to MyFB */
389 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
,
390 GL_RENDERBUFFER_EXT
, DepthRB
);
393 CheckError(__LINE__
);
396 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
);
403 /* make stencil renderbuffer */
404 glGenRenderbuffersEXT(1, &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
);
416 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT
,
417 GL_RENDERBUFFER_STENCIL_SIZE_EXT
, &i
);
418 CheckError(__LINE__
);
419 printf("Stencil renderbuffer size = %d bits\n", i
);
423 CheckError(__LINE__
);
425 /* bind regular framebuffer */
426 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
430 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, mat
);
435 main(int argc
, char *argv
[])
437 glutInit(&argc
, argv
);
438 glutInitWindowPosition(0, 0);
439 glutInitWindowSize(Width
, Height
);
440 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
);
441 Win
= glutCreateWindow(argv
[0]);
442 glutReshapeFunc(Reshape
);
443 glutKeyboardFunc(Key
);
444 glutDisplayFunc(Display
);