blob: ca6d39351120068db103006a00d87d8366349dc8 [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 Paule4b23562005-05-04 20:11:35 +000020
21static int Width = 400, Height = 400;
22static int TexWidth = 512, TexHeight = 512;
23static GLuint MyFB;
24static GLuint TexObj;
25static GLuint DepthRB, StencilRB;
26static GLboolean Anim = GL_FALSE;
27static GLfloat Rot = 0.0;
Brian Paul32fe2332005-11-16 14:48:11 +000028static GLboolean UsePackedDepthStencil = GL_FALSE;
Brian Paule4b23562005-05-04 20:11:35 +000029
30
31static void
32CheckError(int line)
33{
34 GLenum err = glGetError();
35 if (err) {
36 printf("GL Error 0x%x at line %d\n", (int) err, line);
37 }
38}
39
40
41static void
42Idle(void)
43{
44 Rot = glutGet(GLUT_ELAPSED_TIME) * 0.05;
45 glutPostRedisplay();
46}
47
48
49static void
50RenderTexture(void)
51{
52 GLint level = 0;
53 GLenum status;
54
55 glMatrixMode(GL_PROJECTION);
56 glLoadIdentity();
57 glOrtho(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
58 glMatrixMode(GL_MODELVIEW);
59 glLoadIdentity();
60 glTranslatef(0.0, 0.0, -15.0);
61
Brian Paul7edf1e82005-10-04 15:16:27 +000062 /* draw to texture image */
63 glBindTexture(GL_TEXTURE_2D, 0);
Brian Paule4b23562005-05-04 20:11:35 +000064 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
65 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
66 GL_TEXTURE_2D, TexObj, level);
67
68 status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
69 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
70 printf("Framebuffer incomplete!!!\n");
71 }
72
73 glViewport(0, 0, TexWidth, TexHeight);
74
75 glClearColor(0.5, 0.5, 1.0, 0.0);
76 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
Brian Paul32fe2332005-11-16 14:48:11 +000077 CheckError(__LINE__);
Brian Paule4b23562005-05-04 20:11:35 +000078
79 glEnable(GL_DEPTH_TEST);
80 glEnable(GL_STENCIL_TEST);
81 glStencilFunc(GL_NEVER, 1, ~0);
82 glStencilOp(GL_REPLACE, GL_KEEP, GL_REPLACE);
83
Brian Paul32fe2332005-11-16 14:48:11 +000084 CheckError(__LINE__);
85
Brian Paule4b23562005-05-04 20:11:35 +000086 /* draw diamond-shaped stencil pattern */
87 glColor3f(0, 1, 0);
88 glBegin(GL_POLYGON);
89 glVertex2f(-0.2, 0.0);
90 glVertex2f( 0.0, -0.2);
91 glVertex2f( 0.2, 0.0);
92 glVertex2f( 0.0, 0.2);
93 glEnd();
94
95 /* draw teapot where stencil != 1 */
96 glStencilFunc(GL_NOTEQUAL, 1, ~0);
97 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
98
Brian Paul32fe2332005-11-16 14:48:11 +000099 CheckError(__LINE__);
100
Brian Paule4b23562005-05-04 20:11:35 +0000101#if 0
102 glBegin(GL_POLYGON);
103 glColor3f(1, 0, 0);
104 glVertex2f(-1, -1);
105 glColor3f(0, 1, 0);
106 glVertex2f(1, -1);
107 glColor3f(0, 0, 1);
108 glVertex2f(0, 1);
109 glEnd();
110#else
111 glEnable(GL_LIGHTING);
112 glEnable(GL_LIGHT0);
113 glPushMatrix();
114 glRotatef(0.5 * Rot, 1.0, 0.0, 0.0);
115 glutSolidTeapot(0.5);
116 glPopMatrix();
117 glDisable(GL_LIGHTING);
118#endif
119 glDisable(GL_DEPTH_TEST);
120 glDisable(GL_STENCIL_TEST);
121
122 /* Bind normal framebuffer */
123 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
124
125 CheckError(__LINE__);
126}
127
128
129
130static void
131Display(void)
132{
133 float ar = (float) Width / (float) Height;
134
135 RenderTexture();
136
137 /* draw textured quad in the window */
138
139 glMatrixMode(GL_PROJECTION);
140 glLoadIdentity();
141 glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0);
142 glMatrixMode(GL_MODELVIEW);
143 glLoadIdentity();
144 glTranslatef(0.0, 0.0, -7.0);
145
146 glViewport(0, 0, Width, Height);
147
148 glClearColor(0.25, 0.25, 0.25, 0);
149 glClear(GL_COLOR_BUFFER_BIT);
150
151 glPushMatrix();
152 glRotatef(Rot, 0, 1, 0);
153 glEnable(GL_TEXTURE_2D);
Brian Paul7edf1e82005-10-04 15:16:27 +0000154 glBindTexture(GL_TEXTURE_2D, TexObj);
Brian Paule4b23562005-05-04 20:11:35 +0000155 glBegin(GL_POLYGON);
156 glColor3f(0.25, 0.25, 0.25);
157 glTexCoord2f(0, 0);
158 glVertex2f(-1, -1);
159 glTexCoord2f(1, 0);
160 glVertex2f(1, -1);
161 glColor3f(1.0, 1.0, 1.0);
162 glTexCoord2f(1, 1);
163 glVertex2f(1, 1);
164 glTexCoord2f(0, 1);
165 glVertex2f(-1, 1);
166 glEnd();
167 glPopMatrix();
168 glDisable(GL_TEXTURE_2D);
169
170 glutSwapBuffers();
171 CheckError(__LINE__);
172}
173
174
175static void
176Reshape(int width, int height)
177{
178 glViewport(0, 0, width, height);
179 Width = width;
180 Height = height;
181}
182
183
184static void
Brian Paul32fe2332005-11-16 14:48:11 +0000185CleanUp(void)
186{
187 glDeleteRenderbuffersEXT(1, &DepthRB);
188 if (!UsePackedDepthStencil)
189 glDeleteRenderbuffersEXT(1, &StencilRB);
190 glDeleteFramebuffersEXT(1, &MyFB);
191
192 glDeleteTextures(1, &TexObj);
193
194 exit(0);
195}
196
197
198static void
Brian Paule4b23562005-05-04 20:11:35 +0000199Key(unsigned char key, int x, int y)
200{
201 (void) x;
202 (void) y;
203 switch (key) {
204 case 'a':
205 Anim = !Anim;
206 if (Anim)
207 glutIdleFunc(Idle);
208 else
209 glutIdleFunc(NULL);
210 break;
Brian Paul32fe2332005-11-16 14:48:11 +0000211 case 's':
212 Rot += 2.0;
213 break;
Brian Paule4b23562005-05-04 20:11:35 +0000214 case 27:
Brian Paul32fe2332005-11-16 14:48:11 +0000215 CleanUp();
Brian Paule4b23562005-05-04 20:11:35 +0000216 break;
217 }
218 glutPostRedisplay();
219}
220
221
222static void
Brian Paul32fe2332005-11-16 14:48:11 +0000223Init(int argc, char *argv[])
Brian Paule4b23562005-05-04 20:11:35 +0000224{
225 GLint i;
226
227 if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
228 printf("GL_EXT_framebuffer_object not found!\n");
229 exit(0);
230 }
Brian Paul32fe2332005-11-16 14:48:11 +0000231
232 if (argc > 1 && strcmp(argv[1], "-ds") == 0) {
233 if (!glutExtensionSupported("GL_EXT_packed_depth_stencil")) {
234 printf("GL_EXT_packed_depth_stencil not found!\n");
235 exit(0);
236 }
237 UsePackedDepthStencil = GL_TRUE;
238 printf("Using GL_EXT_packed_depth_stencil\n");
239 }
240
Brian Paule4b23562005-05-04 20:11:35 +0000241 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
242
Brian Paul7edf1e82005-10-04 15:16:27 +0000243 /* gen framebuffer id, delete it, do some assertions, just for testing */
Brian Paule4b23562005-05-04 20:11:35 +0000244 glGenFramebuffersEXT(1, &MyFB);
245 assert(MyFB);
Brian Paul9e920fb2005-10-04 15:01:51 +0000246 assert(!glIsFramebufferEXT(MyFB));
Brian Paule4b23562005-05-04 20:11:35 +0000247 glDeleteFramebuffersEXT(1, &MyFB);
248 assert(!glIsFramebufferEXT(MyFB));
249 /* Note, continue to use MyFB below */
250
251 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
252 assert(glIsFramebufferEXT(MyFB));
253 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &i);
254 assert(i == MyFB);
255
256 /* make depth renderbuffer */
257 glGenRenderbuffersEXT(1, &DepthRB);
258 assert(DepthRB);
Brian Paul9e920fb2005-10-04 15:01:51 +0000259 assert(!glIsRenderbufferEXT(DepthRB));
Brian Paule4b23562005-05-04 20:11:35 +0000260 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRB);
Brian Paul7edf1e82005-10-04 15:16:27 +0000261 assert(glIsRenderbufferEXT(DepthRB));
Brian Paul32fe2332005-11-16 14:48:11 +0000262 if (UsePackedDepthStencil)
263 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT,
264 TexWidth, TexHeight);
265 else
266 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
267 TexWidth, TexHeight);
268 CheckError(__LINE__);
Brian Paul58a95732005-07-01 01:34:29 +0000269 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
270 GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
Brian Paul32fe2332005-11-16 14:48:11 +0000271 CheckError(__LINE__);
Brian Paul58a95732005-07-01 01:34:29 +0000272 printf("Depth renderbuffer size = %d bits\n", i);
273 assert(i > 0);
Brian Paule4b23562005-05-04 20:11:35 +0000274
Brian Paule4b23562005-05-04 20:11:35 +0000275 /* attach DepthRB to MyFB */
276 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
277 GL_RENDERBUFFER_EXT, DepthRB);
278
Brian Paul32fe2332005-11-16 14:48:11 +0000279 CheckError(__LINE__);
280
281 if (UsePackedDepthStencil) {
282 /* DepthRb is a combined depth/stencil renderbuffer */
283 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
284 GL_STENCIL_ATTACHMENT_EXT,
285 GL_RENDERBUFFER_EXT, DepthRB);
286 }
287 else {
288 /* make stencil renderbuffer */
289 glGenRenderbuffersEXT(1, &StencilRB);
290 assert(StencilRB);
291 assert(!glIsRenderbufferEXT(StencilRB));
292 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilRB);
293 assert(glIsRenderbufferEXT(StencilRB));
294 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX,
295 TexWidth, TexHeight);
296 /* attach StencilRB to MyFB */
297 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
298 GL_STENCIL_ATTACHMENT_EXT,
299 GL_RENDERBUFFER_EXT, StencilRB);
300 }
301 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
302 GL_RENDERBUFFER_STENCIL_SIZE_EXT, &i);
303 CheckError(__LINE__);
304 printf("Stencil renderbuffer size = %d bits\n", i);
305 assert(i > 0);
Brian Paule4b23562005-05-04 20:11:35 +0000306
307
308 /* bind regular framebuffer */
309 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
310
Brian Paul32fe2332005-11-16 14:48:11 +0000311 CheckError(__LINE__);
312
Brian Paule4b23562005-05-04 20:11:35 +0000313 /* Make texture object/image */
314 glGenTextures(1, &TexObj);
315 glBindTexture(GL_TEXTURE_2D, TexObj);
316 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TexWidth, TexHeight, 0,
317 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
319 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
320 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
321
322 CheckError(__LINE__);
323}
324
325
326int
327main(int argc, char *argv[])
328{
329 glutInit(&argc, argv);
330 glutInitWindowPosition(0, 0);
331 glutInitWindowSize(Width, Height);
332 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
333 glutCreateWindow(argv[0]);
334 glutReshapeFunc(Reshape);
335 glutKeyboardFunc(Key);
336 glutDisplayFunc(Display);
337 if (Anim)
338 glutIdleFunc(Idle);
Brian Paul32fe2332005-11-16 14:48:11 +0000339 Init(argc, argv);
Brian Paule4b23562005-05-04 20:11:35 +0000340 glutMainLoop();
341 return 0;
342}