2 * Test GL_ARB_draw_buffers2, GL_ARB_draw_buffers, GL_EXT_framebuffer_object
3 * and GLSL's gl_FragData[].
5 * We draw to two color buffers and show the left half of the first
6 * color buffer on the left side of the window, and show the right
7 * half of the second color buffer on the right side of the window.
9 * Different color masks are used for the two color buffers.
10 * Blending is enabled for the second buffer only.
26 static int Width
= 400, Height
= 400;
27 static GLuint FBobject
, RBobjects
[3];
28 static GLfloat Xrot
= 0.0, Yrot
= 0.0;
29 static GLuint Program
;
30 static GLboolean Anim
= GL_TRUE
;
36 GLenum err
= glGetError();
38 printf("GL Error 0x%x at line %d\n", (int) err
, line
);
46 GLubyte
*buffer
= malloc(Width
* Height
* 4);
47 static const GLenum buffers
[2] = {
48 GL_COLOR_ATTACHMENT0_EXT
,
49 GL_COLOR_ATTACHMENT1_EXT
52 glUseProgram_func(Program
);
54 glEnable(GL_DEPTH_TEST
);
56 /* draw to user framebuffer */
57 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, FBobject
);
59 /* Clear color buffer 0 (blue) */
60 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT
);
61 glClear(GL_COLOR_BUFFER_BIT
);
63 /* Clear color buffer 1 (1 - blue) */
64 glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT
);
65 glClear(GL_COLOR_BUFFER_BIT
);
67 glClear(GL_DEPTH_BUFFER_BIT
);
69 /* draw to two buffers w/ fragment shader */
70 glDrawBuffersARB(2, buffers
);
72 /* different color masks for each buffer */
74 glColorMaskIndexedEXT(0, GL_TRUE
, GL_FALSE
, GL_FALSE
, GL_FALSE
);
75 glColorMaskIndexedEXT(1, GL_FALSE
, GL_TRUE
, GL_FALSE
, GL_FALSE
);
79 glRotatef(Xrot
, 1, 0, 0);
80 glRotatef(Yrot
, 0, 1, 0);
82 glTranslatef(1, 0, 0);
83 glutSolidTorus(1.0, 2.0, 10, 20);
86 glTranslatef(-1, 0, 0);
87 glRotatef(90, 1, 0, 0);
88 glutSolidTorus(1.0, 2.0, 10, 20);
92 /* restore default color masks */
93 glColorMaskIndexedEXT(0, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
94 glColorMaskIndexedEXT(1, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
96 /* read from user framebuffer */
97 /* left half = colorbuffer 0 */
98 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT
);
99 glPixelStorei(GL_PACK_ROW_LENGTH
, Width
);
100 glPixelStorei(GL_PACK_SKIP_PIXELS
, 0);
101 glReadPixels(0, 0, Width
/ 2, Height
, GL_RGBA
, GL_UNSIGNED_BYTE
,
104 /* right half = colorbuffer 1 */
105 glReadBuffer(GL_COLOR_ATTACHMENT1_EXT
);
106 glPixelStorei(GL_PACK_SKIP_PIXELS
, Width
/ 2);
107 glReadPixels(Width
/ 2, 0, Width
- Width
/ 2, Height
,
108 GL_RGBA
, GL_UNSIGNED_BYTE
,
112 glUseProgram_func(0);
113 glDisable(GL_DEPTH_TEST
);
114 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
115 glWindowPos2iARB(0, 0);
116 glDrawPixels(Width
, Height
, GL_RGBA
, GL_UNSIGNED_BYTE
, buffer
);
120 CheckError(__LINE__
);
127 Xrot
= glutGet(GLUT_ELAPSED_TIME
) * 0.05;
133 Reshape(int width
, int height
)
135 float ar
= (float) width
/ (float) height
;
137 glViewport(0, 0, width
, height
);
138 glMatrixMode(GL_PROJECTION
);
140 glFrustum(-ar
, ar
, -1.0, 1.0, 5.0, 35.0);
141 glMatrixMode(GL_MODELVIEW
);
143 glTranslatef(0.0, 0.0, -20.0);
148 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT
, RBobjects
[0]);
149 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, GL_RGB
, Width
, Height
);
150 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT
, RBobjects
[1]);
151 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, GL_RGB
, Width
, Height
);
152 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT
, RBobjects
[2]);
153 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, GL_DEPTH_COMPONENT
,
161 glDeleteFramebuffersEXT(1, &FBobject
);
162 glDeleteRenderbuffersEXT(3, RBobjects
);
163 glutDestroyWindow(Win
);
169 Key(unsigned char key
, int x
, int y
)
176 glutIdleFunc(Anim
? Idle
: NULL
);
199 CheckExtensions(void)
201 const char *req
[] = {
202 "GL_EXT_framebuffer_object",
203 "GL_ARB_draw_buffers",
204 "GL_EXT_draw_buffers2"
207 const char *version
= (const char *) glGetString(GL_VERSION
);
211 for (i
= 0; i
< 3; i
++) {
212 if (!glutExtensionSupported(req
[i
])) {
213 printf("Sorry, %s extension is required!\n", req
[i
]);
217 if (version
[0] != '2') {
218 printf("Sorry, OpenGL 2.0 is required!\n");
222 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB
, &numBuf
);
223 printf("GL_MAX_DRAW_BUFFERS_ARB = %d\n", numBuf
);
225 printf("Sorry, GL_MAX_DRAW_BUFFERS_ARB needs to be >= 2\n");
229 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
234 SetupRenderbuffers(void)
236 glGenFramebuffersEXT(1, &FBobject
);
237 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, FBobject
);
239 glGenRenderbuffersEXT(3, RBobjects
);
241 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT
, RBobjects
[0]);
242 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, GL_RGB
, Width
, Height
);
244 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT
, RBobjects
[1]);
245 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, GL_RGB
, Width
, Height
);
247 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT
, RBobjects
[2]);
248 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, GL_DEPTH_COMPONENT
,
251 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT
, GL_COLOR_ATTACHMENT0_EXT
,
252 GL_RENDERBUFFER_EXT
, RBobjects
[0]);
253 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT
, GL_COLOR_ATTACHMENT1_EXT
,
254 GL_RENDERBUFFER_EXT
, RBobjects
[1]);
255 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
,
256 GL_RENDERBUFFER_EXT
, RBobjects
[2]);
258 CheckError(__LINE__
);
263 LoadAndCompileShader(GLenum target
, const char *text
)
266 GLuint shader
= glCreateShader_func(target
);
267 glShaderSource_func(shader
, 1, (const GLchar
**) &text
, NULL
);
268 glCompileShader_func(shader
);
269 glGetShaderiv_func(shader
, GL_COMPILE_STATUS
, &stat
);
273 glGetShaderInfoLog_func(shader
, 1000, &len
, log
);
274 fprintf(stderr
, "drawbuffers: problem compiling shader:\n%s\n", log
);
282 CheckLink(GLuint prog
)
285 glGetProgramiv_func(prog
, GL_LINK_STATUS
, &stat
);
289 glGetProgramInfoLog_func(prog
, 1000, &len
, log
);
290 fprintf(stderr
, "drawbuffers: shader link error:\n%s\n", log
);
298 /* emit same color to both draw buffers */
299 static const char *fragShaderText
=
301 " gl_FragData[0] = gl_Color; \n"
302 " gl_FragData[1] = gl_Color; \n"
307 fragShader
= LoadAndCompileShader(GL_FRAGMENT_SHADER
, fragShaderText
);
308 Program
= glCreateProgram_func();
310 glAttachShader_func(Program
, fragShader
);
311 glLinkProgram_func(Program
);
313 glUseProgram_func(Program
);
320 static const GLfloat ambient
[4] = { 0.0, 0.0, 0.0, 0.0 };
321 static const GLfloat diffuse
[4] = { 1.0, 1.0, 1.0, 0.75 };
323 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, ambient
);
324 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, ambient
);
325 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, diffuse
);
327 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE
, 0);
329 glEnable(GL_LIGHTING
);
338 SetupRenderbuffers();
341 glEnable(GL_DEPTH_TEST
);
343 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
344 glEnableIndexedEXT(GL_BLEND
, 1);
349 main(int argc
, char *argv
[])
351 glutInit(&argc
, argv
);
352 glutInitWindowPosition(0, 0);
353 glutInitWindowSize(Width
, Height
);
354 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
);
355 Win
= glutCreateWindow(argv
[0]);
357 glutIdleFunc(Anim
? Idle
: NULL
);
358 glutReshapeFunc(Reshape
);
359 glutKeyboardFunc(Key
);
360 glutDisplayFunc(Display
);