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
26 static int Width
= 400, Height
= 400;
28 static GLenum TexTarget
= GL_TEXTURE_2D
; /*GL_TEXTURE_RECTANGLE_ARB;*/
29 static int TexWidth
= 512, TexHeight
= 512;
30 /*static int TexWidth = 600, TexHeight = 600;*/
34 static GLuint DepthRB
, StencilRB
;
35 static GLboolean Anim
= GL_FALSE
;
36 static GLfloat Rot
= 0.0;
37 static GLboolean UsePackedDepthStencil
= GL_FALSE
;
38 static GLuint TextureLevel
= 1; /* which texture level to render to */
39 static GLenum TexIntFormat
= GL_RGB
; /* either GL_RGB or GL_RGBA */
45 GLenum err
= glGetError();
47 printf("GL Error 0x%x at line %d\n", (int) err
, line
);
55 Rot
= glutGet(GLUT_ELAPSED_TIME
) * 0.1;
65 glMatrixMode(GL_PROJECTION
);
67 glOrtho(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
68 glMatrixMode(GL_MODELVIEW
);
70 glTranslatef(0.0, 0.0, -15.0);
72 /* draw to texture image */
73 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, MyFB
);
75 status
= glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT
);
76 if (status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
77 printf("Framebuffer incomplete!!!\n");
80 glViewport(0, 0, TexWidth
, TexHeight
);
82 glClearColor(0.5, 0.5, 1.0, 0.0);
83 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
87 glEnable(GL_DEPTH_TEST
);
91 glEnable(GL_STENCIL_TEST
);
92 glStencilFunc(GL_NEVER
, 1, ~0);
93 glStencilOp(GL_REPLACE
, GL_KEEP
, GL_REPLACE
);
99 /* draw diamond-shaped stencil pattern */
102 glVertex2f(-0.2, 0.0);
103 glVertex2f( 0.0, -0.2);
104 glVertex2f( 0.2, 0.0);
105 glVertex2f( 0.0, 0.2);
109 /* draw teapot where stencil != 1 */
111 glStencilFunc(GL_NOTEQUAL
, 1, ~0);
112 glStencilOp(GL_KEEP
, GL_KEEP
, GL_KEEP
);
115 CheckError(__LINE__
);
127 glEnable(GL_LIGHTING
);
130 glRotatef(0.5 * Rot
, 1.0, 0.0, 0.0);
131 glutSolidTeapot(0.5);
133 glDisable(GL_LIGHTING
);
135 PrintStencilHistogram(TexWidth, TexHeight);
139 glDisable(GL_DEPTH_TEST
);
140 glDisable(GL_STENCIL_TEST
);
143 /* Bind normal framebuffer */
144 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
147 CheckError(__LINE__
);
155 float ar
= (float) Width
/ (float) Height
;
159 /* draw textured quad in the window */
161 glMatrixMode(GL_PROJECTION
);
163 glFrustum(-ar
, ar
, -1.0, 1.0, 5.0, 25.0);
164 glMatrixMode(GL_MODELVIEW
);
166 glTranslatef(0.0, 0.0, -7.0);
168 glViewport(0, 0, Width
, Height
);
170 glClearColor(0.25, 0.25, 0.25, 0);
171 glClear(GL_COLOR_BUFFER_BIT
);
174 glRotatef(Rot
, 0, 1, 0);
176 glBindTexture(TexTarget
, TexObj
);
178 glColor3f(0.25, 0.25, 0.25);
179 if (TexTarget
== GL_TEXTURE_2D
) {
184 glColor3f(1.0, 1.0, 1.0);
191 assert(TexTarget
== GL_TEXTURE_RECTANGLE_ARB
);
194 glTexCoord2f(TexWidth
, 0);
196 glColor3f(1.0, 1.0, 1.0);
197 glTexCoord2f(TexWidth
, TexHeight
);
199 glTexCoord2f(0, TexHeight
);
204 glDisable(TexTarget
);
208 CheckError(__LINE__
);
213 Reshape(int width
, int height
)
215 glViewport(0, 0, width
, height
);
225 glDeleteRenderbuffersEXT(1, &DepthRB
);
228 if (!UsePackedDepthStencil
)
229 glDeleteRenderbuffersEXT(1, &StencilRB
);
231 glDeleteFramebuffersEXT(1, &MyFB
);
233 glDeleteTextures(1, &TexObj
);
240 Key(unsigned char key
, int x
, int y
)
264 Init(int argc
, char *argv
[])
266 static const GLfloat mat
[4] = { 1.0, 0.5, 0.5, 1.0 };
269 if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
270 printf("GL_EXT_framebuffer_object not found!\n");
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");
279 UsePackedDepthStencil
= GL_TRUE
;
280 printf("Using GL_EXT_packed_depth_stencil\n");
283 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
285 /* gen framebuffer id, delete it, do some assertions, just for testing */
286 glGenFramebuffersEXT(1, &MyFB
);
288 assert(!glIsFramebufferEXT(MyFB
));
289 glDeleteFramebuffersEXT(1, &MyFB
);
290 assert(!glIsFramebufferEXT(MyFB
));
291 /* Note, continue to use MyFB below */
293 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, MyFB
);
294 assert(glIsFramebufferEXT(MyFB
));
295 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &i
);
298 /* 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
;
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
);
315 CheckError(__LINE__
);
317 /* Render color to texture */
318 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT
, GL_COLOR_ATTACHMENT0_EXT
,
319 TexTarget
, TexObj
, TextureLevel
);
323 /* make depth renderbuffer */
324 glGenRenderbuffersEXT(1, &DepthRB
);
326 assert(!glIsRenderbufferEXT(DepthRB
));
327 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT
, DepthRB
);
328 assert(glIsRenderbufferEXT(DepthRB
));
329 if (UsePackedDepthStencil
)
330 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, GL_DEPTH_STENCIL_EXT
,
331 TexWidth
, TexHeight
);
333 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, GL_DEPTH_COMPONENT
,
334 TexWidth
, TexHeight
);
335 CheckError(__LINE__
);
336 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT
,
337 GL_RENDERBUFFER_DEPTH_SIZE_EXT
, &i
);
338 CheckError(__LINE__
);
339 printf("Depth renderbuffer size = %d bits\n", i
);
342 /* attach DepthRB to MyFB */
343 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
,
344 GL_RENDERBUFFER_EXT
, DepthRB
);
347 CheckError(__LINE__
);
350 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
);
357 /* make stencil renderbuffer */
358 glGenRenderbuffersEXT(1, &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
);
370 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT
,
371 GL_RENDERBUFFER_STENCIL_SIZE_EXT
, &i
);
372 CheckError(__LINE__
);
373 printf("Stencil renderbuffer size = %d bits\n", i
);
377 CheckError(__LINE__
);
379 /* bind regular framebuffer */
380 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
384 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, mat
);
389 main(int argc
, char *argv
[])
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
);