1/* 2 * Use scissor to clear the four quadrants of the FBO to different 3 * colors. Then draw a grey triangle in the middle. 4 */ 5 6 7#include <assert.h> 8#include <stdio.h> 9#include <stdlib.h> 10#include <math.h> 11#include <string.h> 12#include <GL/glew.h> 13#include "glut_wrap.h" 14 15 16static int Width = 512, Height = 512; 17static GLuint MyFB, MyRB; 18static GLboolean UseTex = GL_FALSE; 19static GLboolean UseCopyPix = GL_FALSE; 20 21 22#define CheckError() \ 23 do { \ 24 GLenum err = glGetError(); \ 25 if (err != GL_NO_ERROR) \ 26 printf("Error: %s\n", gluErrorString(err)); \ 27 assert(err == GL_NO_ERROR); \ 28 } while (0) 29 30 31static void 32Init(void) 33{ 34 GLenum status; 35 36 fprintf(stderr, "GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 37 fprintf(stderr, "GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); 38 fprintf(stderr, "GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); 39 fflush(stderr); 40 41 if (!glutExtensionSupported("GL_EXT_framebuffer_object")) { 42 printf("GL_EXT_framebuffer_object not found!\n"); 43 exit(0); 44 } 45 46 glGenFramebuffersEXT(1, &MyFB); 47 glGenRenderbuffersEXT(1, &MyRB); 48 49 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB); 50 51 if (UseTex) { 52 GLuint tex; 53 glGenTextures(1, &tex); 54 glBindTexture(GL_TEXTURE_2D, tex); 55 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, 56 GL_RGBA, GL_UNSIGNED_BYTE, NULL); 57 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 58 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 59 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 60 GL_COLOR_ATTACHMENT0_EXT, 61 GL_TEXTURE_2D, tex, 0); 62 } 63 else { 64 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, MyRB); 65 66 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 67 GL_COLOR_ATTACHMENT0_EXT, 68 GL_RENDERBUFFER_EXT, MyRB); 69 70 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); 71 } 72 73 status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 74 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { 75 fprintf(stderr, "Framebuffer object is incomplete (0x%x)!\n", status); 76 } 77 78 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 79} 80 81 82static void 83Reshape(int width, int height) 84{ 85 glViewport(0, 0, width, height); 86 glMatrixMode(GL_PROJECTION); 87 glLoadIdentity(); 88 glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 89 glMatrixMode(GL_MODELVIEW); 90 91 Width = width; 92 Height = height; 93 if (!UseTex) { 94 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); 95 } 96} 97 98 99static void 100Key(unsigned char key, int x, int y) 101{ 102 if (key == 27) { 103 exit(0); 104 } 105 glutPostRedisplay(); 106} 107 108 109static void 110Draw(void) 111{ 112 GLboolean scissor = GL_TRUE; 113 114 /* draw to user framebuffer */ 115 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB); 116 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); 117 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); 118 119 glViewport(0, 0, Width, Height); 120 CheckError(); 121 122 if (scissor) { 123 glEnable(GL_SCISSOR_TEST); 124 125 /* lower-left = red */ 126 glClearColor(1, 0, 0, 0); 127 glScissor(0, 0, Width / 2, Height / 2); 128 glClear(GL_COLOR_BUFFER_BIT); 129 130 /* lower-right = green */ 131 glClearColor(0, 1, 0, 0); 132 glScissor(Width / 2, 0, Width - Width / 2, Height / 2); 133 glClear(GL_COLOR_BUFFER_BIT); 134 135 /* upper-left = blue */ 136 glClearColor(0, 0, 1, 0); 137 glScissor(0, Height / 2, Width / 2, Height - Height / 2); 138 glClear(GL_COLOR_BUFFER_BIT); 139 140 /* upper-right = white */ 141 glClearColor(1, 1, 1, 0); 142 glScissor(Width / 2, Height / 2, Width - Width / 2, Height - Height / 2); 143 glClear(GL_COLOR_BUFFER_BIT); 144 145 glDisable(GL_SCISSOR_TEST); 146 } 147 else { 148 glClearColor(0, 1, 0, 0); 149 glClear(GL_COLOR_BUFFER_BIT); 150 } 151 152 CheckError(); 153 154 /* gray triangle in middle, pointing up */ 155 glColor3f(0.5, 0.5, 0.5); 156 glBegin(GL_TRIANGLES); 157 glVertex2f(Width/4, Height/4); 158 glVertex2f(Width*3/4, Height/4); 159 glVertex2f(Width/2, Height*3/4); 160 glVertex2f(-0.5, -0.5); 161 glVertex2f(+0.5, -0.5); 162 glVertex2f( 0.0, 0.7); 163 glEnd(); 164 165 CheckError(); 166 167 /* copy fbo to window */ 168 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, MyFB); 169 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); 170 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); 171 glDrawBuffer(GL_BACK); 172 173 if (UseCopyPix) { 174 glWindowPos2i(0, 0); 175 glCopyPixels(0, 0, Width, Height, GL_COLOR); 176 } 177 else { 178 GLubyte *buffer = malloc(Width * Height * 4); 179 180 /* read from user framebuffer */ 181 glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 182 183 /* draw to window */ 184 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 185 glWindowPos2iARB(0, 0); 186 glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 187 188 free(buffer); 189 } 190 191 /* Bind normal framebuffer */ 192 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 193 194 glutSwapBuffers(); 195 196 CheckError(); 197} 198 199 200int 201main(int argc, char *argv[]) 202{ 203 int i; 204 205 glutInit(&argc, argv); 206 glutInitWindowPosition(100, 0); 207 glutInitWindowSize(Width, Height); 208 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 209 210 for (i = 1; i < argc; i++) { 211 if (strcmp(argv[i], "-t") == 0) 212 UseTex = GL_TRUE; 213 else if (strcmp(argv[i], "-c") == 0) 214 UseCopyPix = GL_TRUE; 215 } 216 217 if (UseTex) 218 printf("Using render to texture\n"); 219 else 220 printf("Using user-created render buffer\n"); 221 222 if (!glutCreateWindow(argv[0])) { 223 exit(1); 224 } 225 226 glewInit(); 227 Init(); 228 glutReshapeFunc(Reshape); 229 glutKeyboardFunc(Key); 230 glutDisplayFunc(Draw); 231 glutMainLoop(); 232 return 0; 233} 234