diff options
Diffstat (limited to 'progs/tests/fbotexture.c')
-rw-r--r-- | progs/tests/fbotexture.c | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/progs/tests/fbotexture.c b/progs/tests/fbotexture.c new file mode 100644 index 00000000000..13a29db3f35 --- /dev/null +++ b/progs/tests/fbotexture.c @@ -0,0 +1,404 @@ +/* + * Test GL_EXT_framebuffer_object render-to-texture + * + * Draw a teapot into a texture image with stenciling. + * Then draw a textured quad using that texture. + * + * Brian Paul + * 18 Apr 2005 + */ + + +#define GL_GLEXT_PROTOTYPES +#include <GL/glut.h> +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +/* For debug */ +#define DEPTH 1 +#define STENCIL 1 +#define DRAW 1 + + +static int Width = 400, Height = 400; + +static GLenum TexTarget = GL_TEXTURE_2D; /*GL_TEXTURE_RECTANGLE_ARB;*/ +static int TexWidth = 512, TexHeight = 512; +/*static int TexWidth = 600, TexHeight = 600;*/ + +static GLuint MyFB; +static GLuint TexObj; +static GLuint DepthRB, StencilRB; +static GLboolean Anim = GL_FALSE; +static GLfloat Rot = 0.0; +static GLboolean UsePackedDepthStencil = GL_FALSE; +static GLuint TextureLevel = 1; /* which texture level to render to */ +static GLenum TexIntFormat = GL_RGB; /* either GL_RGB or GL_RGBA */ + + +static void +CheckError(int line) +{ + GLenum err = glGetError(); + if (err) { + printf("GL Error 0x%x at line %d\n", (int) err, line); + } +} + + +static void +Idle(void) +{ + Rot = glutGet(GLUT_ELAPSED_TIME) * 0.1; + glutPostRedisplay(); +} + + +static void +RenderTexture(void) +{ + GLenum status; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -15.0); + + /* draw to texture image */ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB); + + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { + printf("Framebuffer incomplete!!!\n"); + } + + glViewport(0, 0, TexWidth, TexHeight); + + glClearColor(0.5, 0.5, 1.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + CheckError(__LINE__); + +#if DEPTH + glEnable(GL_DEPTH_TEST); +#endif + +#if STENCIL + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_NEVER, 1, ~0); + glStencilOp(GL_REPLACE, GL_KEEP, GL_REPLACE); +#endif + + CheckError(__LINE__); + +#if DEPTH || STENCIL + /* draw diamond-shaped stencil pattern */ + glColor3f(0, 1, 0); + glBegin(GL_POLYGON); + glVertex2f(-0.2, 0.0); + glVertex2f( 0.0, -0.2); + glVertex2f( 0.2, 0.0); + glVertex2f( 0.0, 0.2); + glEnd(); +#endif + + /* draw teapot where stencil != 1 */ +#if STENCIL + glStencilFunc(GL_NOTEQUAL, 1, ~0); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); +#endif + + CheckError(__LINE__); + +#if 0 + glBegin(GL_POLYGON); + glColor3f(1, 0, 0); + glVertex2f(-1, -1); + glColor3f(0, 1, 0); + glVertex2f(1, -1); + glColor3f(0, 0, 1); + glVertex2f(0, 1); + glEnd(); +#else + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glPushMatrix(); + glRotatef(0.5 * Rot, 1.0, 0.0, 0.0); + glutSolidTeapot(0.5); + glPopMatrix(); + glDisable(GL_LIGHTING); + /* + PrintStencilHistogram(TexWidth, TexHeight); + */ +#endif + + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + +#if DRAW + /* Bind normal framebuffer */ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +#endif + + CheckError(__LINE__); +} + + + +static void +Display(void) +{ + float ar = (float) Width / (float) Height; + + RenderTexture(); + + /* draw textured quad in the window */ +#if DRAW + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -7.0); + + glViewport(0, 0, Width, Height); + + glClearColor(0.25, 0.25, 0.25, 0); + glClear(GL_COLOR_BUFFER_BIT); + + glPushMatrix(); + glRotatef(Rot, 0, 1, 0); + glEnable(TexTarget); + glBindTexture(TexTarget, TexObj); + glBegin(GL_POLYGON); + glColor3f(0.25, 0.25, 0.25); + if (TexTarget == GL_TEXTURE_2D) { + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f(1, 0); + glVertex2f(1, -1); + glColor3f(1.0, 1.0, 1.0); + glTexCoord2f(1, 1); + glVertex2f(1, 1); + glTexCoord2f(0, 1); + glVertex2f(-1, 1); + } + else { + assert(TexTarget == GL_TEXTURE_RECTANGLE_ARB); + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f(TexWidth, 0); + glVertex2f(1, -1); + glColor3f(1.0, 1.0, 1.0); + glTexCoord2f(TexWidth, TexHeight); + glVertex2f(1, 1); + glTexCoord2f(0, TexHeight); + glVertex2f(-1, 1); + } + glEnd(); + glPopMatrix(); + glDisable(TexTarget); +#endif + + glutSwapBuffers(); + CheckError(__LINE__); +} + + +static void +Reshape(int width, int height) +{ + glViewport(0, 0, width, height); + Width = width; + Height = height; +} + + +static void +CleanUp(void) +{ +#if DEPTH + glDeleteRenderbuffersEXT(1, &DepthRB); +#endif +#if STENCIL + if (!UsePackedDepthStencil) + glDeleteRenderbuffersEXT(1, &StencilRB); +#endif + glDeleteFramebuffersEXT(1, &MyFB); + + glDeleteTextures(1, &TexObj); + + exit(0); +} + + +static void +Key(unsigned char key, int x, int y) +{ + (void) x; + (void) y; + switch (key) { + case 'a': + Anim = !Anim; + if (Anim) + glutIdleFunc(Idle); + else + glutIdleFunc(NULL); + break; + case 's': + Rot += 2.0; + break; + case 27: + CleanUp(); + break; + } + glutPostRedisplay(); +} + + +static void +Init(int argc, char *argv[]) +{ + static const GLfloat mat[4] = { 1.0, 0.5, 0.5, 1.0 }; + GLint i; + + if (!glutExtensionSupported("GL_EXT_framebuffer_object")) { + printf("GL_EXT_framebuffer_object not found!\n"); + exit(0); + } + + if (argc > 1 && strcmp(argv[1], "-ds") == 0) { + if (!glutExtensionSupported("GL_EXT_packed_depth_stencil")) { + printf("GL_EXT_packed_depth_stencil not found!\n"); + exit(0); + } + UsePackedDepthStencil = GL_TRUE; + printf("Using GL_EXT_packed_depth_stencil\n"); + } + + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); + + /* gen framebuffer id, delete it, do some assertions, just for testing */ + glGenFramebuffersEXT(1, &MyFB); + assert(MyFB); + assert(!glIsFramebufferEXT(MyFB)); + glDeleteFramebuffersEXT(1, &MyFB); + assert(!glIsFramebufferEXT(MyFB)); + /* Note, continue to use MyFB below */ + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB); + assert(glIsFramebufferEXT(MyFB)); + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &i); + assert(i == MyFB); + + /* Make texture object/image */ + glGenTextures(1, &TexObj); + glBindTexture(TexTarget, TexObj); + /* make two image levels */ + glTexImage2D(TexTarget, 0, TexIntFormat, TexWidth, TexHeight, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(TexTarget, 1, TexIntFormat, TexWidth/2, TexHeight/2, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + TexWidth = TexWidth >> TextureLevel; + TexHeight = TexHeight >> TextureLevel; + + glTexParameteri(TexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(TexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameteri(TexTarget, GL_TEXTURE_BASE_LEVEL, TextureLevel); + glTexParameteri(TexTarget, GL_TEXTURE_MAX_LEVEL, TextureLevel); + + CheckError(__LINE__); + + /* Render color to texture */ + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + TexTarget, TexObj, TextureLevel); + + +#if DEPTH + /* make depth renderbuffer */ + glGenRenderbuffersEXT(1, &DepthRB); + assert(DepthRB); + assert(!glIsRenderbufferEXT(DepthRB)); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRB); + assert(glIsRenderbufferEXT(DepthRB)); + if (UsePackedDepthStencil) + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, + TexWidth, TexHeight); + else + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, + TexWidth, TexHeight); + CheckError(__LINE__); + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, + GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i); + CheckError(__LINE__); + printf("Depth renderbuffer size = %d bits\n", i); + assert(i > 0); + + /* attach DepthRB to MyFB */ + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, DepthRB); +#endif + + CheckError(__LINE__); + +#if STENCIL + if (UsePackedDepthStencil) { + /* DepthRb is a combined depth/stencil renderbuffer */ + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, + GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, DepthRB); + } + else { + /* make stencil renderbuffer */ + glGenRenderbuffersEXT(1, &StencilRB); + assert(StencilRB); + assert(!glIsRenderbufferEXT(StencilRB)); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilRB); + assert(glIsRenderbufferEXT(StencilRB)); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, + TexWidth, TexHeight); + /* attach StencilRB to MyFB */ + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, + GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, StencilRB); + } + glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, + GL_RENDERBUFFER_STENCIL_SIZE_EXT, &i); + CheckError(__LINE__); + printf("Stencil renderbuffer size = %d bits\n", i); + assert(i > 0); +#endif + + CheckError(__LINE__); + + /* bind regular framebuffer */ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + + /* lighting */ + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat); +} + + +int +main(int argc, char *argv[]) +{ + glutInit(&argc, argv); + glutInitWindowPosition(0, 0); + glutInitWindowSize(Width, Height); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutCreateWindow(argv[0]); + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutDisplayFunc(Display); + if (Anim) + glutIdleFunc(Idle); + Init(argc, argv); + glutMainLoop(); + return 0; +} |