diff options
Diffstat (limited to 'progs/tests/drawbuffers2.c')
-rw-r--r-- | progs/tests/drawbuffers2.c | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/progs/tests/drawbuffers2.c b/progs/tests/drawbuffers2.c new file mode 100644 index 00000000000..7b8cc5ca6a3 --- /dev/null +++ b/progs/tests/drawbuffers2.c @@ -0,0 +1,364 @@ +/* + * Test GL_ARB_draw_buffers2, GL_ARB_draw_buffers, GL_EXT_framebuffer_object + * and GLSL's gl_FragData[]. + * + * We draw to two color buffers and show the left half of the first + * color buffer on the left side of the window, and show the right + * half of the second color buffer on the right side of the window. + * + * Different color masks are used for the two color buffers. + * Blending is enabled for the second buffer only. + * + * Brian Paul + * 31 Dec 2009 + */ + + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <GL/glew.h> +#include <GL/glut.h> +#include "extfuncs.h" + +static int Win; +static int Width = 400, Height = 400; +static GLuint FBobject, RBobjects[3]; +static GLfloat Xrot = 0.0, Yrot = 0.0; +static GLuint Program; +static GLboolean Anim = GL_TRUE; + + +static void +CheckError(int line) +{ + GLenum err = glGetError(); + if (err) { + printf("GL Error 0x%x at line %d\n", (int) err, line); + } +} + + +static void +Display(void) +{ + GLubyte *buffer = malloc(Width * Height * 4); + static const GLenum buffers[2] = { + GL_COLOR_ATTACHMENT0_EXT, + GL_COLOR_ATTACHMENT1_EXT + }; + + glUseProgram_func(Program); + + glEnable(GL_DEPTH_TEST); + + /* draw to user framebuffer */ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject); + + /* Clear color buffer 0 (blue) */ + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glClear(GL_COLOR_BUFFER_BIT); + + /* Clear color buffer 1 (1 - blue) */ + glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); + glClear(GL_COLOR_BUFFER_BIT); + + glClear(GL_DEPTH_BUFFER_BIT); + + /* draw to two buffers w/ fragment shader */ + glDrawBuffersARB(2, buffers); + + /* different color masks for each buffer */ + if (1) { + glColorMaskIndexedEXT(0, GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE); + glColorMaskIndexedEXT(1, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); + } + + glPushMatrix(); + glRotatef(Xrot, 1, 0, 0); + glRotatef(Yrot, 0, 1, 0); + glPushMatrix(); + glTranslatef(1, 0, 0); + glutSolidTorus(1.0, 2.0, 10, 20); + glPopMatrix(); + glPushMatrix(); + glTranslatef(-1, 0, 0); + glRotatef(90, 1, 0, 0); + glutSolidTorus(1.0, 2.0, 10, 20); + glPopMatrix(); + glPopMatrix(); + + /* restore default color masks */ + glColorMaskIndexedEXT(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glColorMaskIndexedEXT(1, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + /* read from user framebuffer */ + /* left half = colorbuffer 0 */ + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glPixelStorei(GL_PACK_ROW_LENGTH, Width); + glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + glReadPixels(0, 0, Width / 2, Height, GL_RGBA, GL_UNSIGNED_BYTE, + buffer); + + /* right half = colorbuffer 1 */ + glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); + glPixelStorei(GL_PACK_SKIP_PIXELS, Width / 2); + glReadPixels(Width / 2, 0, Width - Width / 2, Height, + GL_RGBA, GL_UNSIGNED_BYTE, + buffer); + + /* draw to window */ + glUseProgram_func(0); + glDisable(GL_DEPTH_TEST); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glWindowPos2iARB(0, 0); + glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + + free(buffer); + glutSwapBuffers(); + CheckError(__LINE__); +} + + +static void +Idle(void) +{ + Xrot = glutGet(GLUT_ELAPSED_TIME) * 0.05; + glutPostRedisplay(); +} + + +static void +Reshape(int width, int height) +{ + float ar = (float) width / (float) height; + + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-ar, ar, -1.0, 1.0, 5.0, 35.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -20.0); + + Width = width; + Height = height; + + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[0]); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[1]); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[2]); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, + Width, Height); +} + + +static void +CleanUp(void) +{ + glDeleteFramebuffersEXT(1, &FBobject); + glDeleteRenderbuffersEXT(3, RBobjects); + glutDestroyWindow(Win); + exit(0); +} + + +static void +Key(unsigned char key, int x, int y) +{ + (void) x; + (void) y; + switch (key) { + case ' ': + Anim = !Anim; + glutIdleFunc(Anim ? Idle : NULL); + break; + case 'x': + Xrot += 5.0; + break; + case 'X': + Xrot -= 5.0; + break; + case 'y': + Yrot += 5.0; + break; + case 'Y': + Yrot -= 5.0; + break; + case 27: + CleanUp(); + break; + } + glutPostRedisplay(); +} + + +static void +CheckExtensions(void) +{ + const char *req[] = { + "GL_EXT_framebuffer_object", + "GL_ARB_draw_buffers", + "GL_EXT_draw_buffers2" + }; + + const char *version = (const char *) glGetString(GL_VERSION); + GLint numBuf; + GLint i; + + for (i = 0; i < 3; i++) { + if (!glutExtensionSupported(req[i])) { + printf("Sorry, %s extension is required!\n", req[i]); + exit(1); + } + } + if (version[0] != '2') { + printf("Sorry, OpenGL 2.0 is required!\n"); + exit(1); + } + + glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &numBuf); + printf("GL_MAX_DRAW_BUFFERS_ARB = %d\n", numBuf); + if (numBuf < 2) { + printf("Sorry, GL_MAX_DRAW_BUFFERS_ARB needs to be >= 2\n"); + exit(1); + } + + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); +} + + +static void +SetupRenderbuffers(void) +{ + glGenFramebuffersEXT(1, &FBobject); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject); + + glGenRenderbuffersEXT(3, RBobjects); + + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[0]); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); + + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[1]); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); + + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[2]); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, + Width, Height); + + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_RENDERBUFFER_EXT, RBobjects[0]); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, + GL_RENDERBUFFER_EXT, RBobjects[1]); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, RBobjects[2]); + + CheckError(__LINE__); +} + + +static GLuint +LoadAndCompileShader(GLenum target, const char *text) +{ + GLint stat; + GLuint shader = glCreateShader_func(target); + glShaderSource_func(shader, 1, (const GLchar **) &text, NULL); + glCompileShader_func(shader); + glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat); + if (!stat) { + GLchar log[1000]; + GLsizei len; + glGetShaderInfoLog_func(shader, 1000, &len, log); + fprintf(stderr, "drawbuffers: problem compiling shader:\n%s\n", log); + exit(1); + } + return shader; +} + + +static void +CheckLink(GLuint prog) +{ + GLint stat; + glGetProgramiv_func(prog, GL_LINK_STATUS, &stat); + if (!stat) { + GLchar log[1000]; + GLsizei len; + glGetProgramInfoLog_func(prog, 1000, &len, log); + fprintf(stderr, "drawbuffers: shader link error:\n%s\n", log); + } +} + + +static void +SetupShaders(void) +{ + /* emit same color to both draw buffers */ + static const char *fragShaderText = + "void main() {\n" + " gl_FragData[0] = gl_Color; \n" + " gl_FragData[1] = gl_Color; \n" + "}\n"; + + GLuint fragShader; + + fragShader = LoadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText); + Program = glCreateProgram_func(); + + glAttachShader_func(Program, fragShader); + glLinkProgram_func(Program); + CheckLink(Program); + glUseProgram_func(Program); +} + + +static void +SetupLighting(void) +{ + static const GLfloat ambient[4] = { 0.0, 0.0, 0.0, 0.0 }; + static const GLfloat diffuse[4] = { 1.0, 1.0, 1.0, 0.75 }; + + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); + + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHTING); +} + + +static void +Init(void) +{ + CheckExtensions(); + GetExtensionFuncs(); + SetupRenderbuffers(); + SetupShaders(); + SetupLighting(); + glEnable(GL_DEPTH_TEST); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnableIndexedEXT(GL_BLEND, 1); +} + + +int +main(int argc, char *argv[]) +{ + glutInit(&argc, argv); + glutInitWindowPosition(0, 0); + glutInitWindowSize(Width, Height); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + Win = glutCreateWindow(argv[0]); + glewInit(); + glutIdleFunc(Anim ? Idle : NULL); + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutDisplayFunc(Display); + Init(); + glutMainLoop(); + return 0; +} |