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