132001f49Smrg/*
232001f49Smrg * Use scissor to clear the four quadrants of the FBO to different
332001f49Smrg * colors.  Then draw a grey triangle in the middle.
432001f49Smrg */
532001f49Smrg
632001f49Smrg
732001f49Smrg#include <assert.h>
832001f49Smrg#include <stdio.h>
932001f49Smrg#include <stdlib.h>
1032001f49Smrg#include <math.h>
1132001f49Smrg#include <string.h>
1232001f49Smrg#include <GL/glew.h>
1332001f49Smrg#include "glut_wrap.h"
1432001f49Smrg
1532001f49Smrg
1632001f49Smrgstatic int Width = 512, Height = 512;
1732001f49Smrgstatic GLuint MyFB, MyRB;
1832001f49Smrgstatic GLboolean UseTex = GL_FALSE;
1932001f49Smrgstatic GLboolean UseCopyPix = GL_FALSE;
2032001f49Smrg
2132001f49Smrg
2232001f49Smrg#define CheckError() \
2332001f49Smrg   do { \
2432001f49Smrg      GLenum err = glGetError(); \
2532001f49Smrg      if (err != GL_NO_ERROR) \
2632001f49Smrg         printf("Error: %s\n", gluErrorString(err)); \
2732001f49Smrg      assert(err == GL_NO_ERROR); \
2832001f49Smrg   } while (0)
2932001f49Smrg
3032001f49Smrg
3132001f49Smrgstatic void
3232001f49SmrgInit(void)
3332001f49Smrg{
3432001f49Smrg   GLenum status;
3532001f49Smrg
3632001f49Smrg   fprintf(stderr, "GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
3732001f49Smrg   fprintf(stderr, "GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
3832001f49Smrg   fprintf(stderr, "GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
3932001f49Smrg   fflush(stderr);
4032001f49Smrg
4132001f49Smrg   if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
4232001f49Smrg      printf("GL_EXT_framebuffer_object not found!\n");
4332001f49Smrg      exit(0);
4432001f49Smrg   }
4532001f49Smrg
4632001f49Smrg   glGenFramebuffersEXT(1, &MyFB);
4732001f49Smrg   glGenRenderbuffersEXT(1, &MyRB);
4832001f49Smrg
4932001f49Smrg   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
5032001f49Smrg
5132001f49Smrg   if (UseTex) {
5232001f49Smrg      GLuint tex;
5332001f49Smrg      glGenTextures(1, &tex);
5432001f49Smrg      glBindTexture(GL_TEXTURE_2D, tex);
5532001f49Smrg      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0,
5632001f49Smrg                   GL_RGBA, GL_UNSIGNED_BYTE, NULL);
5732001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5832001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5932001f49Smrg      glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
6032001f49Smrg                                GL_COLOR_ATTACHMENT0_EXT,
6132001f49Smrg                                GL_TEXTURE_2D, tex, 0);
6232001f49Smrg   }
6332001f49Smrg   else {
6432001f49Smrg      glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, MyRB);
6532001f49Smrg
6632001f49Smrg      glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
6732001f49Smrg                                   GL_COLOR_ATTACHMENT0_EXT,
6832001f49Smrg                                   GL_RENDERBUFFER_EXT, MyRB);
6932001f49Smrg
7032001f49Smrg      glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
7132001f49Smrg   }
7232001f49Smrg
7332001f49Smrg   status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
7432001f49Smrg   if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
7532001f49Smrg      fprintf(stderr, "Framebuffer object is incomplete (0x%x)!\n", status);
7632001f49Smrg   }
7732001f49Smrg
7832001f49Smrg   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
7932001f49Smrg}
8032001f49Smrg
8132001f49Smrg
8232001f49Smrgstatic void
8332001f49SmrgReshape(int width, int height)
8432001f49Smrg{
8532001f49Smrg   glViewport(0, 0, width, height);
8632001f49Smrg   glMatrixMode(GL_PROJECTION);
8732001f49Smrg   glLoadIdentity();
8832001f49Smrg   glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
8932001f49Smrg   glMatrixMode(GL_MODELVIEW);
9032001f49Smrg
9132001f49Smrg   Width = width;
9232001f49Smrg   Height = height;
9332001f49Smrg   if (!UseTex) {
9432001f49Smrg      glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
9532001f49Smrg   }
9632001f49Smrg}
9732001f49Smrg
9832001f49Smrg
9932001f49Smrgstatic void
10032001f49SmrgKey(unsigned char key, int x, int y)
10132001f49Smrg{
10232001f49Smrg   if (key == 27) {
10332001f49Smrg      exit(0);
10432001f49Smrg   }
10532001f49Smrg   glutPostRedisplay();
10632001f49Smrg}
10732001f49Smrg
10832001f49Smrg
10932001f49Smrgstatic void
11032001f49SmrgDraw(void)
11132001f49Smrg{
11232001f49Smrg   GLboolean scissor = GL_TRUE;
11332001f49Smrg
11432001f49Smrg   /* draw to user framebuffer */
11532001f49Smrg   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
11632001f49Smrg   glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
11732001f49Smrg   glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
11832001f49Smrg
11932001f49Smrg   glViewport(0, 0, Width, Height);
12032001f49Smrg   CheckError();
12132001f49Smrg
12232001f49Smrg   if (scissor) {
12332001f49Smrg      glEnable(GL_SCISSOR_TEST);
12432001f49Smrg
12532001f49Smrg      /* lower-left = red */
12632001f49Smrg      glClearColor(1, 0, 0, 0);
12732001f49Smrg      glScissor(0, 0, Width / 2, Height / 2);
12832001f49Smrg      glClear(GL_COLOR_BUFFER_BIT);
12932001f49Smrg
13032001f49Smrg      /* lower-right = green */
13132001f49Smrg      glClearColor(0, 1, 0, 0);
13232001f49Smrg      glScissor(Width / 2, 0, Width - Width / 2, Height / 2);
13332001f49Smrg      glClear(GL_COLOR_BUFFER_BIT);
13432001f49Smrg
13532001f49Smrg      /* upper-left = blue */
13632001f49Smrg      glClearColor(0, 0, 1, 0);
13732001f49Smrg      glScissor(0, Height / 2, Width / 2, Height - Height / 2);
13832001f49Smrg      glClear(GL_COLOR_BUFFER_BIT);
13932001f49Smrg
14032001f49Smrg      /* upper-right = white */
14132001f49Smrg      glClearColor(1, 1, 1, 0);
14232001f49Smrg      glScissor(Width / 2, Height / 2, Width - Width / 2, Height - Height / 2);
14332001f49Smrg      glClear(GL_COLOR_BUFFER_BIT);
14432001f49Smrg
14532001f49Smrg      glDisable(GL_SCISSOR_TEST);
14632001f49Smrg   }
14732001f49Smrg   else {
14832001f49Smrg      glClearColor(0, 1, 0, 0);
14932001f49Smrg      glClear(GL_COLOR_BUFFER_BIT);
15032001f49Smrg   }
15132001f49Smrg
15232001f49Smrg   CheckError();
15332001f49Smrg
15432001f49Smrg   /* gray triangle in middle, pointing up */
15532001f49Smrg   glColor3f(0.5, 0.5, 0.5);
15632001f49Smrg   glBegin(GL_TRIANGLES);
15732001f49Smrg   glVertex2f(Width/4, Height/4);
15832001f49Smrg   glVertex2f(Width*3/4, Height/4);
15932001f49Smrg   glVertex2f(Width/2, Height*3/4);
16032001f49Smrg   glVertex2f(-0.5, -0.5);
16132001f49Smrg   glVertex2f(+0.5, -0.5);
16232001f49Smrg   glVertex2f( 0.0, 0.7);
16332001f49Smrg   glEnd();
16432001f49Smrg
16532001f49Smrg   CheckError();
16632001f49Smrg
16732001f49Smrg   /* copy fbo to window */
16832001f49Smrg   glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, MyFB);
16932001f49Smrg   glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
17032001f49Smrg   glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
17132001f49Smrg   glDrawBuffer(GL_BACK);
17232001f49Smrg
17332001f49Smrg   if (UseCopyPix) {
17432001f49Smrg      glWindowPos2i(0, 0);
17532001f49Smrg      glCopyPixels(0, 0, Width, Height, GL_COLOR);
17632001f49Smrg   }
17732001f49Smrg   else {
17832001f49Smrg      GLubyte *buffer = malloc(Width * Height * 4);
17932001f49Smrg
18032001f49Smrg      /* read from user framebuffer */
18132001f49Smrg      glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
18232001f49Smrg
18332001f49Smrg      /* draw to window */
18432001f49Smrg      glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
18532001f49Smrg      glWindowPos2iARB(0, 0);
18632001f49Smrg      glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
18732001f49Smrg
18832001f49Smrg      free(buffer);
18932001f49Smrg   }
19032001f49Smrg
19132001f49Smrg   /* Bind normal framebuffer */
19232001f49Smrg   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
19332001f49Smrg
19432001f49Smrg   glutSwapBuffers();
19532001f49Smrg
19632001f49Smrg   CheckError();
19732001f49Smrg}
19832001f49Smrg
19932001f49Smrg
20032001f49Smrgint
20132001f49Smrgmain(int argc, char *argv[])
20232001f49Smrg{
20332001f49Smrg   int i;
20432001f49Smrg
20532001f49Smrg   glutInit(&argc, argv);
20632001f49Smrg   glutInitWindowPosition(100, 0);
20732001f49Smrg   glutInitWindowSize(Width, Height);
20832001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
20932001f49Smrg
21032001f49Smrg   for (i = 1; i < argc; i++) {
21132001f49Smrg      if (strcmp(argv[i], "-t") == 0)
21232001f49Smrg         UseTex = GL_TRUE;
21332001f49Smrg      else if (strcmp(argv[i], "-c") == 0)
21432001f49Smrg         UseCopyPix = GL_TRUE;
21532001f49Smrg   }
21632001f49Smrg
21732001f49Smrg   if (UseTex)
21832001f49Smrg      printf("Using render to texture\n");
21932001f49Smrg   else
22032001f49Smrg      printf("Using user-created render buffer\n");
22132001f49Smrg
22232001f49Smrg   if (!glutCreateWindow(argv[0])) {
22332001f49Smrg      exit(1);
22432001f49Smrg   }
22532001f49Smrg
22632001f49Smrg   glewInit();
22732001f49Smrg   Init();
22832001f49Smrg   glutReshapeFunc(Reshape);
22932001f49Smrg   glutKeyboardFunc(Key);
23032001f49Smrg   glutDisplayFunc(Draw);
23132001f49Smrg   glutMainLoop();
23232001f49Smrg   return 0;
23332001f49Smrg}
234