blob: 8583bac0ddfec0dd14e0b09af62232683e7b7100 [file] [log] [blame]
Brianccb80d72007-03-11 17:03:29 -06001/*
2 * Test GL_ARB_draw_buffers, GL_EXT_framebuffer_object
3 * and GLSL's gl_FragData[].
4 *
5 * Brian Paul
6 * 11 March 2007
7 */
8
9
10#define GL_GLEXT_PROTOTYPES
11#include <assert.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <math.h>
15#include <GL/glut.h>
16#include "extfuncs.h"
17
18static int Win;
19static int Width = 400, Height = 400;
20static GLuint FBobject, RBobjects[3];
21static GLfloat Xrot = 0.0, Yrot = 0.0;
22
23
24static void
25CheckError(int line)
26{
27 GLenum err = glGetError();
28 if (err) {
29 printf("GL Error 0x%x at line %d\n", (int) err, line);
30 }
31}
32
33
34static void
35Display(void)
36{
37 GLubyte *buffer = malloc(Width * Height * 4);
38 static const GLenum buffers[2] = {
39 GL_COLOR_ATTACHMENT0_EXT,
40 GL_COLOR_ATTACHMENT1_EXT
41 };
42
43 /* draw to user framebuffer */
44 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject);
45
46 /* Clear color buffer 0 (blue) */
47 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
48 glClearColor(0.5, 0.5, 1.0, 0.0);
49 glClear(GL_COLOR_BUFFER_BIT);
50
51 /* Clear color buffer 1 (1 - blue) */
52 glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
53 glClearColor(0.5, 0.5, 0.0, 0.0);
54 glClear(GL_COLOR_BUFFER_BIT);
55
56 glClear(GL_DEPTH_BUFFER_BIT);
57
58 /* draw to two buffers w/ fragment shader */
59 glDrawBuffersARB(2, buffers);
60
61 glPushMatrix();
62 glRotatef(Xrot, 1, 0, 0);
63 glRotatef(Yrot, 0, 1, 0);
64 glutSolidTorus(0.75, 2.0, 10, 20);
65 glPopMatrix();
66
67 /* read from user framebuffer */
68 /* bottom half = colorbuffer 0 */
69 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
70 glReadPixels(0, 0, Width, Height / 2, GL_RGBA, GL_UNSIGNED_BYTE,
71 buffer);
72 /* top half = colorbuffer 1 */
73 glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
74 glReadPixels(0, Height/2, Width, Height / 2, GL_RGBA, GL_UNSIGNED_BYTE,
75 buffer + Width * Height / 2 * 4);
76
77 /* draw to window */
78 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
79 glWindowPos2iARB(0, 0);
80 glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
81
82 free(buffer);
83 glutSwapBuffers();
84 CheckError(__LINE__);
85}
86
87
88static void
89Reshape(int width, int height)
90{
91 float ar = (float) width / (float) height;
92
93 glViewport(0, 0, width, height);
94 glMatrixMode(GL_PROJECTION);
95 glLoadIdentity();
96 glFrustum(-ar, ar, -1.0, 1.0, 5.0, 35.0);
97 glMatrixMode(GL_MODELVIEW);
98 glLoadIdentity();
99 glTranslatef(0.0, 0.0, -20.0);
100
101 Width = width;
102 Height = height;
103
104 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[0]);
105 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
106 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[1]);
107 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
108 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[2]);
109 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
110 Width, Height);
111}
112
113
114static void
115CleanUp(void)
116{
117 glDeleteFramebuffersEXT(1, &FBobject);
118 glDeleteRenderbuffersEXT(3, RBobjects);
119 glutDestroyWindow(Win);
120 exit(0);
121}
122
123
124static void
125Key(unsigned char key, int x, int y)
126{
127 (void) x;
128 (void) y;
129 switch (key) {
130 case 'x':
131 Xrot += 5.0;
132 break;
133 case 'y':
134 Yrot += 5.0;
135 break;
136 case 27:
137 CleanUp();
138 break;
139 }
140 glutPostRedisplay();
141}
142
143
144static void
145CheckExtensions(void)
146{
147 const char *version = (const char *) glGetString(GL_VERSION);
148 GLint numBuf;
149
150 if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
151 printf("Sorry, GL_EXT_framebuffer_object is required!\n");
152 exit(1);
153 }
154 if (!glutExtensionSupported("GL_ARB_draw_buffers")) {
155 printf("Sorry, GL_ARB_draw_buffers is required!\n");
156 exit(1);
157 }
158 if (version[0] != '2') {
159 printf("Sorry, OpenGL 2.0 is required!\n");
160 exit(1);
161 }
162
163 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &numBuf);
164 printf("GL_MAX_DRAW_BUFFERS_ARB = %d\n", numBuf);
165 if (numBuf < 2) {
166 printf("Sorry, GL_MAX_DRAW_BUFFERS_ARB needs to be >= 2\n");
167 exit(1);
168 }
169
170 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
171}
172
173
174static void
175SetupRenderbuffers(void)
176{
177 glGenFramebuffersEXT(1, &FBobject);
178 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject);
179
180 glGenRenderbuffersEXT(3, RBobjects);
181
182 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[0]);
183 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
184
185 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[1]);
186 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
187
188 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[2]);
189 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
190 Width, Height);
191
192 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
193 GL_RENDERBUFFER_EXT, RBobjects[0]);
194 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
195 GL_RENDERBUFFER_EXT, RBobjects[1]);
196 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
197 GL_RENDERBUFFER_EXT, RBobjects[2]);
198
199 CheckError(__LINE__);
200}
201
202
203static GLuint
204LoadAndCompileShader(GLenum target, const char *text)
205{
206 GLint stat;
207 GLuint shader = glCreateShader_func(target);
208 glShaderSource_func(shader, 1, (const GLchar **) &text, NULL);
209 glCompileShader_func(shader);
210 glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat);
211 if (!stat) {
212 GLchar log[1000];
213 GLsizei len;
214 glGetShaderInfoLog_func(shader, 1000, &len, log);
215 fprintf(stderr, "drawbuffers: problem compiling shader:\n%s\n", log);
216 exit(1);
217 }
218 return shader;
219}
220
221
222static void
223CheckLink(GLuint prog)
224{
225 GLint stat;
226 glGetProgramiv_func(prog, GL_LINK_STATUS, &stat);
227 if (!stat) {
228 GLchar log[1000];
229 GLsizei len;
230 glGetProgramInfoLog_func(prog, 1000, &len, log);
231 fprintf(stderr, "drawbuffers: shader link error:\n%s\n", log);
232 }
233}
234
235
236static void
237SetupShaders(void)
238{
239 /* second color output = 1 - first color */
240 static const char *fragShaderText =
241 "void main() {\n"
242 " gl_FragData[0] = gl_Color; \n"
243 " gl_FragData[1] = vec4(1.0) - gl_Color; \n"
244 "}\n";
245
246 GLuint fragShader, program;
247
248 fragShader = LoadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText);
249 program = glCreateProgram_func();
250
251 glAttachShader_func(program, fragShader);
252 glLinkProgram_func(program);
253 CheckLink(program);
254 glUseProgram_func(program);
255}
256
257
258static void
259SetupLighting(void)
260{
261 static const GLfloat frontMat[4] = { 1.0, 0.5, 0.5, 1.0 };
262 static const GLfloat backMat[4] = { 1.0, 0.5, 0.5, 1.0 };
263
264 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, frontMat);
265 glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, backMat);
266 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
267 glEnable(GL_LIGHT0);
268 glEnable(GL_LIGHTING);
269}
270
271
272static void
273Init(void)
274{
275 CheckExtensions();
276 GetExtensionFuncs();
277 SetupRenderbuffers();
278 SetupShaders();
279 SetupLighting();
280 glEnable(GL_DEPTH_TEST);
281}
282
283
284int
285main(int argc, char *argv[])
286{
287 glutInit(&argc, argv);
288 glutInitWindowPosition(0, 0);
289 glutInitWindowSize(Width, Height);
290 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
291 Win = glutCreateWindow(argv[0]);
292 glutReshapeFunc(Reshape);
293 glutKeyboardFunc(Key);
294 glutDisplayFunc(Display);
295 Init();
296 glutMainLoop();
297 return 0;
298}