blob: d6b9c0702236f0451f6484b26b93f5e43318f679 [file] [log] [blame]
/**
* Test Z compositing with glDrawPixels(GL_DEPTH_COMPONENT) and stencil test.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/glut.h>
static int Win;
static GLfloat Xrot = 0, Yrot = 0, Zpos = 6;
static GLboolean Anim = GL_FALSE;
static int Width = 400, Height = 200;
static GLfloat *Zimg;
static GLubyte *Cimg;
static GLboolean showZ = 0;
static void
Idle(void)
{
Xrot += 3.0;
Yrot += 4.0;
glutPostRedisplay();
}
/**
* Draw first object, save color+Z images
*/
static void
DrawFirst(void)
{
static const GLfloat red[4] = { 1.0, 0.0, 0.0, 0.0 };
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(-1, 0, 0);
glRotatef(45 + Xrot, 1, 0, 0);
glutSolidTorus(0.75, 2.0, 10, 20);
glPopMatrix();
glReadPixels(0, 0, Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT, Zimg);
glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, Cimg);
}
/**
* Draw second object.
*/
static void
DrawSecond(void)
{
static const GLfloat blue[4] = { 0.0, 0.0, 1.0, 0.0 };
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glPushMatrix();
glTranslatef(+1, 0, 0);
glRotatef(-45 + Xrot, 1, 0, 0);
glutSolidTorus(0.75, 2.0, 10, 20);
glPopMatrix();
}
/**
* Composite first/saved image over second rendering.
*/
static void
Composite(void)
{
glWindowPos2i(0, 0);
/* Draw Z values, set stencil where Z test passes */
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, ~0);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glColorMask(0,0,0,0);
glDrawPixels(Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT, Zimg);
glColorMask(1,1,1,1);
/* Draw color where stencil==1 */
glStencilFunc(GL_EQUAL, 1, ~0);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glDisable(GL_DEPTH_TEST);
glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, Cimg);
glEnable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
}
static void
Draw(void)
{
DrawFirst();
DrawSecond();
Composite();
glutSwapBuffers();
}
static void
Reshape(int width, int height)
{
GLfloat ar = (float) width / height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 5.0, 30.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -15.0);
Width = width;
Height = height;
if (Zimg)
free(Zimg);
if (Cimg)
free(Cimg);
Zimg = (float *) malloc(width * height * 4);
Cimg = (GLubyte *) malloc(width * height * 4);
}
static void
Key(unsigned char key, int x, int y)
{
const GLfloat step = 1.0;
(void) x;
(void) y;
switch (key) {
case 'a':
Anim = !Anim;
if (Anim)
glutIdleFunc(Idle);
else
glutIdleFunc(NULL);
break;
case 'd':
showZ = !showZ;
break;
case 'z':
Zpos -= step;
break;
case 'Z':
Zpos += step;
break;
case 27:
glutDestroyWindow(Win);
exit(0);
break;
}
glutPostRedisplay();
}
static void
SpecialKey(int key, int x, int y)
{
const GLfloat step = 3.0;
(void) x;
(void) y;
switch (key) {
case GLUT_KEY_UP:
Xrot -= step;
break;
case GLUT_KEY_DOWN:
Xrot += step;
break;
case GLUT_KEY_LEFT:
Yrot -= step;
break;
case GLUT_KEY_RIGHT:
Yrot += step;
break;
}
glutPostRedisplay();
}
static void
Init(void)
{
/* setup lighting, etc */
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
int
main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowPosition(0, 0);
glutInitWindowSize(Width, Height);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);
Win = glutCreateWindow(argv[0]);
glewInit();
glutReshapeFunc(Reshape);
glutKeyboardFunc(Key);
glutSpecialFunc(SpecialKey);
glutDisplayFunc(Draw);
if (Anim)
glutIdleFunc(Idle);
Init();
glutMainLoop();
return 0;
}