From ccb80d7ec4e4415c5443031ec26447117e20e4de Mon Sep 17 00:00:00 2001 From: Brian Date: Sun, 11 Mar 2007 17:03:29 -0600 Subject: Test the GL_ARB_draw_buffers extension. Also requires GL_EXT_framebuffer_object and OpenGL 2.0 (for GLSL). --- progs/tests/drawbuffers.c | 298 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 progs/tests/drawbuffers.c (limited to 'progs/tests') diff --git a/progs/tests/drawbuffers.c b/progs/tests/drawbuffers.c new file mode 100644 index 0000000000..8583bac0dd --- /dev/null +++ b/progs/tests/drawbuffers.c @@ -0,0 +1,298 @@ +/* + * Test GL_ARB_draw_buffers, GL_EXT_framebuffer_object + * and GLSL's gl_FragData[]. + * + * Brian Paul + * 11 March 2007 + */ + + +#define GL_GLEXT_PROTOTYPES +#include +#include +#include +#include +#include +#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 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 + }; + + /* draw to user framebuffer */ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject); + + /* Clear color buffer 0 (blue) */ + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glClearColor(0.5, 0.5, 1.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + /* Clear color buffer 1 (1 - blue) */ + glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); + glClearColor(0.5, 0.5, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + glClear(GL_DEPTH_BUFFER_BIT); + + /* draw to two buffers w/ fragment shader */ + glDrawBuffersARB(2, buffers); + + glPushMatrix(); + glRotatef(Xrot, 1, 0, 0); + glRotatef(Yrot, 0, 1, 0); + glutSolidTorus(0.75, 2.0, 10, 20); + glPopMatrix(); + + /* read from user framebuffer */ + /* bottom half = colorbuffer 0 */ + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glReadPixels(0, 0, Width, Height / 2, GL_RGBA, GL_UNSIGNED_BYTE, + buffer); + /* top half = colorbuffer 1 */ + glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); + glReadPixels(0, Height/2, Width, Height / 2, GL_RGBA, GL_UNSIGNED_BYTE, + buffer + Width * Height / 2 * 4); + + /* draw to window */ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glWindowPos2iARB(0, 0); + glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + + free(buffer); + glutSwapBuffers(); + CheckError(__LINE__); +} + + +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 'x': + Xrot += 5.0; + break; + case 'y': + Yrot += 5.0; + break; + case 27: + CleanUp(); + break; + } + glutPostRedisplay(); +} + + +static void +CheckExtensions(void) +{ + const char *version = (const char *) glGetString(GL_VERSION); + GLint numBuf; + + if (!glutExtensionSupported("GL_EXT_framebuffer_object")) { + printf("Sorry, GL_EXT_framebuffer_object is required!\n"); + exit(1); + } + if (!glutExtensionSupported("GL_ARB_draw_buffers")) { + printf("Sorry, GL_ARB_draw_buffers is required!\n"); + 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) +{ + /* second color output = 1 - first color */ + static const char *fragShaderText = + "void main() {\n" + " gl_FragData[0] = gl_Color; \n" + " gl_FragData[1] = vec4(1.0) - gl_Color; \n" + "}\n"; + + GLuint fragShader, program; + + 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 frontMat[4] = { 1.0, 0.5, 0.5, 1.0 }; + static const GLfloat backMat[4] = { 1.0, 0.5, 0.5, 1.0 }; + + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, frontMat); + glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, backMat); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHTING); +} + + +static void +Init(void) +{ + CheckExtensions(); + GetExtensionFuncs(); + SetupRenderbuffers(); + SetupShaders(); + SetupLighting(); + glEnable(GL_DEPTH_TEST); +} + + +int +main(int argc, char *argv[]) +{ + glutInit(&argc, argv); + glutInitWindowPosition(0, 0); + glutInitWindowSize(Width, Height); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + Win = glutCreateWindow(argv[0]); + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutDisplayFunc(Display); + Init(); + glutMainLoop(); + return 0; +} -- cgit v1.2.3