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 */
46 GLenum err
= glGetError();
48 printf("GL Error 0x%x at line %d\n", (int) err
, line
);
56 Rot
= glutGet(GLUT_ELAPSED_TIME
) * 0.1;
66 glMatrixMode(GL_PROJECTION
);
68 glOrtho(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
69 glMatrixMode(GL_MODELVIEW
);
71 glTranslatef(0.0, 0.0, -15.0);
73 /* draw to texture image */
74 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, MyFB
);
76 status
= glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT
);
77 if (status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
78 printf("Framebuffer incomplete!!!\n");
81 glViewport(0, 0, TexWidth
, TexHeight
);
83 glClearColor(0.5, 0.5, 1.0, 0.0);
84 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
88 glEnable(GL_DEPTH_TEST
);
92 glEnable(GL_STENCIL_TEST
);
93 glStencilFunc(GL_NEVER
, 1, ~0);
94 glStencilOp(GL_REPLACE
, GL_KEEP
, GL_REPLACE
);
100 /* draw diamond-shaped stencil pattern */
103 glVertex2f(-0.2, 0.0);
104 glVertex2f( 0.0, -0.2);
105 glVertex2f( 0.2, 0.0);
106 glVertex2f( 0.0, 0.2);
110 /* draw teapot where stencil != 1 */
112 glStencilFunc(GL_NOTEQUAL
, 1, ~0);
113 glStencilOp(GL_KEEP
, GL_KEEP
, GL_KEEP
);
116 CheckError(__LINE__
);
128 glEnable(GL_LIGHTING
);
131 glRotatef(0.5 * Rot
, 1.0, 0.0, 0.0);
132 glutSolidTeapot(0.5);
134 glDisable(GL_LIGHTING
);
136 PrintStencilHistogram(TexWidth, TexHeight);
140 glDisable(GL_DEPTH_TEST
);
141 glDisable(GL_STENCIL_TEST
);
144 /* Bind normal framebuffer */
145 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
148 CheckError(__LINE__
);
156 float ar
= (float) Width
/ (float) Height
;
160 /* draw textured quad in the window */
162 glMatrixMode(GL_PROJECTION
);
164 glFrustum(-ar
, ar
, -1.0, 1.0, 5.0, 25.0);
165 glMatrixMode(GL_MODELVIEW
);
167 glTranslatef(0.0, 0.0, -7.0);
169 glViewport(0, 0, Width
, Height
);
171 glClearColor(0.25, 0.25, 0.25, 0);
172 glClear(GL_COLOR_BUFFER_BIT
);
175 glRotatef(Rot
, 0, 1, 0);
177 glBindTexture(TexTarget
, TexObj
);
179 glColor3f(0.25, 0.25, 0.25);
180 if (TexTarget
== GL_TEXTURE_2D
) {
185 glColor3f(1.0, 1.0, 1.0);
192 assert(TexTarget
== GL_TEXTURE_RECTANGLE_ARB
);
195 glTexCoord2f(TexWidth
, 0);
197 glColor3f(1.0, 1.0, 1.0);
198 glTexCoord2f(TexWidth
, TexHeight
);
200 glTexCoord2f(0, TexHeight
);
205 glDisable(TexTarget
);
209 CheckError(__LINE__
);
214 Reshape(int width
, int height
)
216 glViewport(0, 0, width
, height
);
226 glDeleteRenderbuffersEXT(1, &DepthRB
);
229 if (!UsePackedDepthStencil
)
230 glDeleteRenderbuffersEXT(1, &StencilRB
);
232 glDeleteFramebuffersEXT(1, &MyFB
);
234 glDeleteTextures(1, &TexObj
);
236 glutDestroyWindow(Win
);
243 Key(unsigned char key
, int x
, int y
)
267 Init(int argc
, char *argv
[])
269 static const GLfloat mat
[4] = { 1.0, 0.5, 0.5, 1.0 };
272 if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
273 printf("GL_EXT_framebuffer_object not found!\n");
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");
282 UsePackedDepthStencil
= GL_TRUE
;
283 printf("Using GL_EXT_packed_depth_stencil\n");
286 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
288 /* gen framebuffer id, delete it, do some assertions, just for testing */
289 glGenFramebuffersEXT(1, &MyFB
);
291 assert(!glIsFramebufferEXT(MyFB
));
292 glDeleteFramebuffersEXT(1, &MyFB
);
293 assert(!glIsFramebufferEXT(MyFB
));
294 /* Note, continue to use MyFB below */
296 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, MyFB
);
297 assert(glIsFramebufferEXT(MyFB
));
298 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &i
);
301 /* 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
;
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
);
318 CheckError(__LINE__
);
320 /* Render color to texture */
321 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT
, GL_COLOR_ATTACHMENT0_EXT
,
322 TexTarget
, TexObj
, TextureLevel
);
326 /* make depth renderbuffer */
327 glGenRenderbuffersEXT(1, &DepthRB
);
329 assert(!glIsRenderbufferEXT(DepthRB
));
330 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT
, DepthRB
);
331 assert(glIsRenderbufferEXT(DepthRB
));
332 if (UsePackedDepthStencil
)
333 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, GL_DEPTH_STENCIL_EXT
,
334 TexWidth
, TexHeight
);
336 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, GL_DEPTH_COMPONENT
,
337 TexWidth
, TexHeight
);
338 CheckError(__LINE__
);
339 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT
,
340 GL_RENDERBUFFER_DEPTH_SIZE_EXT
, &i
);
341 CheckError(__LINE__
);
342 printf("Depth renderbuffer size = %d bits\n", i
);
345 /* attach DepthRB to MyFB */
346 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
,
347 GL_RENDERBUFFER_EXT
, DepthRB
);
350 CheckError(__LINE__
);
353 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
);
360 /* make stencil renderbuffer */
361 glGenRenderbuffersEXT(1, &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
);
373 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT
,
374 GL_RENDERBUFFER_STENCIL_SIZE_EXT
, &i
);
375 CheckError(__LINE__
);
376 printf("Stencil renderbuffer size = %d bits\n", i
);
380 CheckError(__LINE__
);
382 /* bind regular framebuffer */
383 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
387 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, mat
);
392 main(int argc
, char *argv
[])
394 glutInit(&argc
, argv
);
395 glutInitWindowPosition(0, 0);
396 glutInitWindowSize(Width
, Height
);
397 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
);
398 Win
= glutCreateWindow(argv
[0]);
399 glutReshapeFunc(Reshape
);
400 glutKeyboardFunc(Key
);
401 glutDisplayFunc(Display
);