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