e1f10c94185ce307401717653cb2370915355525
[mesa.git] / progs / tests / fbotexture.c
1 /*
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
13 #include <assert.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <math.h>
17 #include <GL/glut.h>
18
19 static int Width = 400, Height = 400;
20 static int TexWidth = 512, TexHeight = 512;
21 static GLuint MyFB;
22 static GLuint TexObj;
23 static GLuint DepthRB, StencilRB;
24 static GLboolean Anim = GL_FALSE;
25 static GLfloat Rot = 0.0;
26
27
28 static void
29 CheckError(int line)
30 {
31 GLenum err = glGetError();
32 if (err) {
33 printf("GL Error 0x%x at line %d\n", (int) err, line);
34 }
35 }
36
37
38 static void
39 Idle(void)
40 {
41 Rot = glutGet(GLUT_ELAPSED_TIME) * 0.05;
42 glutPostRedisplay();
43 }
44
45
46 static void
47 RenderTexture(void)
48 {
49 GLint level = 0;
50 GLenum status;
51
52 glMatrixMode(GL_PROJECTION);
53 glLoadIdentity();
54 glOrtho(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
55 glMatrixMode(GL_MODELVIEW);
56 glLoadIdentity();
57 glTranslatef(0.0, 0.0, -15.0);
58
59 /* draw to texture */
60 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
61 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
62 GL_TEXTURE_2D, TexObj, level);
63
64 status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
65 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
66 printf("Framebuffer incomplete!!!\n");
67 }
68
69 glViewport(0, 0, TexWidth, TexHeight);
70
71 glClearColor(0.5, 0.5, 1.0, 0.0);
72 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
73
74 glEnable(GL_DEPTH_TEST);
75 glEnable(GL_STENCIL_TEST);
76 glStencilFunc(GL_NEVER, 1, ~0);
77 glStencilOp(GL_REPLACE, GL_KEEP, GL_REPLACE);
78
79 /* draw diamond-shaped stencil pattern */
80 glColor3f(0, 1, 0);
81 glBegin(GL_POLYGON);
82 glVertex2f(-0.2, 0.0);
83 glVertex2f( 0.0, -0.2);
84 glVertex2f( 0.2, 0.0);
85 glVertex2f( 0.0, 0.2);
86 glEnd();
87
88 /* draw teapot where stencil != 1 */
89 glStencilFunc(GL_NOTEQUAL, 1, ~0);
90 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
91
92 #if 0
93 glBegin(GL_POLYGON);
94 glColor3f(1, 0, 0);
95 glVertex2f(-1, -1);
96 glColor3f(0, 1, 0);
97 glVertex2f(1, -1);
98 glColor3f(0, 0, 1);
99 glVertex2f(0, 1);
100 glEnd();
101 #else
102 glEnable(GL_LIGHTING);
103 glEnable(GL_LIGHT0);
104 glPushMatrix();
105 glRotatef(0.5 * Rot, 1.0, 0.0, 0.0);
106 glutSolidTeapot(0.5);
107 glPopMatrix();
108 glDisable(GL_LIGHTING);
109 #endif
110 glDisable(GL_DEPTH_TEST);
111 glDisable(GL_STENCIL_TEST);
112
113 /* Bind normal framebuffer */
114 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
115
116 CheckError(__LINE__);
117 }
118
119
120
121 static void
122 Display(void)
123 {
124 float ar = (float) Width / (float) Height;
125
126 RenderTexture();
127
128 /* draw textured quad in the window */
129
130 glMatrixMode(GL_PROJECTION);
131 glLoadIdentity();
132 glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0);
133 glMatrixMode(GL_MODELVIEW);
134 glLoadIdentity();
135 glTranslatef(0.0, 0.0, -7.0);
136
137 glViewport(0, 0, Width, Height);
138
139 glClearColor(0.25, 0.25, 0.25, 0);
140 glClear(GL_COLOR_BUFFER_BIT);
141
142 glPushMatrix();
143 glRotatef(Rot, 0, 1, 0);
144 glEnable(GL_TEXTURE_2D);
145 glBegin(GL_POLYGON);
146 glColor3f(0.25, 0.25, 0.25);
147 glTexCoord2f(0, 0);
148 glVertex2f(-1, -1);
149 glTexCoord2f(1, 0);
150 glVertex2f(1, -1);
151 glColor3f(1.0, 1.0, 1.0);
152 glTexCoord2f(1, 1);
153 glVertex2f(1, 1);
154 glTexCoord2f(0, 1);
155 glVertex2f(-1, 1);
156 glEnd();
157 glPopMatrix();
158 glDisable(GL_TEXTURE_2D);
159
160 glutSwapBuffers();
161 CheckError(__LINE__);
162 }
163
164
165 static void
166 Reshape(int width, int height)
167 {
168 glViewport(0, 0, width, height);
169 Width = width;
170 Height = height;
171 }
172
173
174 static void
175 Key(unsigned char key, int x, int y)
176 {
177 (void) x;
178 (void) y;
179 switch (key) {
180 case 'a':
181 Anim = !Anim;
182 if (Anim)
183 glutIdleFunc(Idle);
184 else
185 glutIdleFunc(NULL);
186 break;
187 case 27:
188 exit(0);
189 break;
190 }
191 glutPostRedisplay();
192 }
193
194
195 static void
196 Init(void)
197 {
198 GLint i;
199
200 if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
201 printf("GL_EXT_framebuffer_object not found!\n");
202 exit(0);
203 }
204 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
205
206 /* make framebuffer */
207 glGenFramebuffersEXT(1, &MyFB);
208 assert(MyFB);
209 assert(!glIsFramebufferEXT(MyFB));
210 glDeleteFramebuffersEXT(1, &MyFB);
211 assert(!glIsFramebufferEXT(MyFB));
212 /* Note, continue to use MyFB below */
213
214 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
215 assert(glIsFramebufferEXT(MyFB));
216 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &i);
217 assert(i == MyFB);
218
219 /* make depth renderbuffer */
220 glGenRenderbuffersEXT(1, &DepthRB);
221 assert(DepthRB);
222 assert(!glIsRenderbufferEXT(DepthRB));
223 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRB);
224 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
225 TexWidth, TexHeight);
226 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
227 GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
228 printf("Depth renderbuffer size = %d bits\n", i);
229 assert(i > 0);
230
231 /* make stencil renderbuffer */
232 glGenRenderbuffersEXT(1, &StencilRB);
233 assert(StencilRB);
234 assert(!glIsRenderbufferEXT(StencilRB));
235 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilRB);
236 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX,
237 TexWidth, TexHeight);
238 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
239 GL_RENDERBUFFER_STENCIL_SIZE_EXT, &i);
240 printf("Stencil renderbuffer size = %d bits\n", i);
241 assert(i > 0);
242
243 /* attach DepthRB to MyFB */
244 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
245 GL_RENDERBUFFER_EXT, DepthRB);
246
247 /* attach StencilRB to MyFB */
248 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
249 GL_RENDERBUFFER_EXT, StencilRB);
250
251
252 /* bind regular framebuffer */
253 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
254
255 /* Make texture object/image */
256 glGenTextures(1, &TexObj);
257 glBindTexture(GL_TEXTURE_2D, TexObj);
258 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TexWidth, TexHeight, 0,
259 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
262 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
263
264 CheckError(__LINE__);
265 }
266
267
268 int
269 main(int argc, char *argv[])
270 {
271 glutInit(&argc, argv);
272 glutInitWindowPosition(0, 0);
273 glutInitWindowSize(Width, Height);
274 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
275 glutCreateWindow(argv[0]);
276 glutReshapeFunc(Reshape);
277 glutKeyboardFunc(Key);
278 glutDisplayFunc(Display);
279 if (Anim)
280 glutIdleFunc(Idle);
281 Init();
282 glutMainLoop();
283 return 0;
284 }