132001f49Smrg/**
232001f49Smrg * Test Z compositing with glDrawPixels(GL_DEPTH_COMPONENT) and stencil test.
332001f49Smrg */
432001f49Smrg
532001f49Smrg#include <stdio.h>
632001f49Smrg#include <stdlib.h>
732001f49Smrg#include <math.h>
832001f49Smrg#include <GL/glew.h>
932001f49Smrg#include "glut_wrap.h"
1032001f49Smrg
1132001f49Smrg
1232001f49Smrgstatic int Win;
1332001f49Smrgstatic GLfloat Xrot = 0, Yrot = 0, Zpos = 6;
1432001f49Smrgstatic GLboolean Anim = GL_FALSE;
1532001f49Smrg
1632001f49Smrgstatic int Width = 400, Height = 200;
1732001f49Smrgstatic GLfloat *Zimg;
1832001f49Smrgstatic GLubyte *Cimg;
1932001f49Smrgstatic GLboolean showZ = 0;
2032001f49Smrg
2132001f49Smrg
2232001f49Smrgstatic void
2332001f49SmrgIdle(void)
2432001f49Smrg{
2532001f49Smrg   Xrot += 3.0;
2632001f49Smrg   Yrot += 4.0;
2732001f49Smrg   glutPostRedisplay();
2832001f49Smrg}
2932001f49Smrg
3032001f49Smrg
3132001f49Smrg/**
3232001f49Smrg * Draw first object, save color+Z images
3332001f49Smrg */
3432001f49Smrgstatic void
3532001f49SmrgDrawFirst(void)
3632001f49Smrg{
3732001f49Smrg   static const GLfloat red[4] = { 1.0, 0.0, 0.0, 0.0 };
3832001f49Smrg
3932001f49Smrg   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
4032001f49Smrg
4132001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4232001f49Smrg
4332001f49Smrg   glPushMatrix();
4432001f49Smrg   glTranslatef(-1, 0, 0);
4532001f49Smrg   glRotatef(45 + Xrot, 1, 0, 0);
4632001f49Smrg
4732001f49Smrg   glutSolidTorus(0.75, 2.0, 10, 20);
4832001f49Smrg
4932001f49Smrg   glPopMatrix();
5032001f49Smrg
5132001f49Smrg   glReadPixels(0, 0, Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT, Zimg);
5232001f49Smrg   glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, Cimg);
5332001f49Smrg}
5432001f49Smrg
5532001f49Smrg
5632001f49Smrg/**
5732001f49Smrg * Draw second object.
5832001f49Smrg */
5932001f49Smrgstatic void
6032001f49SmrgDrawSecond(void)
6132001f49Smrg{
6232001f49Smrg   static const GLfloat blue[4] = { 0.0, 0.0, 1.0, 0.0 };
6332001f49Smrg
6432001f49Smrg   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue);
6532001f49Smrg
6632001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
6732001f49Smrg
6832001f49Smrg   glPushMatrix();
6932001f49Smrg   glTranslatef(+1, 0, 0);
7032001f49Smrg   glRotatef(-45 + Xrot, 1, 0, 0);
7132001f49Smrg
7232001f49Smrg   glutSolidTorus(0.75, 2.0, 10, 20);
7332001f49Smrg
7432001f49Smrg   glPopMatrix();
7532001f49Smrg}
7632001f49Smrg
7732001f49Smrg
7832001f49Smrg/**
7932001f49Smrg * Composite first/saved image over second rendering.
8032001f49Smrg */
8132001f49Smrgstatic void
8232001f49SmrgComposite(void)
8332001f49Smrg{
8432001f49Smrg   glWindowPos2i(0, 0);
8532001f49Smrg
8632001f49Smrg   /* Draw Z values, set stencil where Z test passes */
8732001f49Smrg   glEnable(GL_STENCIL_TEST);
8832001f49Smrg   glStencilFunc(GL_ALWAYS, 1, ~0);
8932001f49Smrg   glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
9032001f49Smrg   glColorMask(0,0,0,0);
9132001f49Smrg   glDrawPixels(Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT, Zimg);
9232001f49Smrg   glColorMask(1,1,1,1);
9332001f49Smrg
9432001f49Smrg   /* Draw color where stencil==1 */
9532001f49Smrg   glStencilFunc(GL_EQUAL, 1, ~0);
9632001f49Smrg   glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
9732001f49Smrg   glDisable(GL_DEPTH_TEST);
9832001f49Smrg   glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, Cimg);
9932001f49Smrg   glEnable(GL_DEPTH_TEST);
10032001f49Smrg
10132001f49Smrg   glDisable(GL_STENCIL_TEST);
10232001f49Smrg}
10332001f49Smrg
10432001f49Smrg
10532001f49Smrgstatic void
10632001f49SmrgDraw(void)
10732001f49Smrg{
10832001f49Smrg   DrawFirst();
10932001f49Smrg   DrawSecond();
11032001f49Smrg   Composite();
11132001f49Smrg   glutSwapBuffers();
11232001f49Smrg}
11332001f49Smrg
11432001f49Smrg
11532001f49Smrgstatic void
11632001f49SmrgReshape(int width, int height)
11732001f49Smrg{
11832001f49Smrg   GLfloat ar = (float) width / height;
11932001f49Smrg   glViewport(0, 0, width, height);
12032001f49Smrg   glMatrixMode(GL_PROJECTION);
12132001f49Smrg   glLoadIdentity();
12232001f49Smrg   glFrustum(-ar, ar, -1.0, 1.0, 5.0, 30.0);
12332001f49Smrg   glMatrixMode(GL_MODELVIEW);
12432001f49Smrg   glLoadIdentity();
12532001f49Smrg   glTranslatef(0.0, 0.0, -15.0);
12632001f49Smrg
12732001f49Smrg   Width = width;
12832001f49Smrg   Height = height;
12932001f49Smrg
13032001f49Smrg   if (Zimg)
13132001f49Smrg      free(Zimg);
13232001f49Smrg   if (Cimg)
13332001f49Smrg      free(Cimg);
13432001f49Smrg   Zimg = (float *) malloc(width * height * 4);
13532001f49Smrg   Cimg = (GLubyte *) malloc(width * height * 4);
13632001f49Smrg}
13732001f49Smrg
13832001f49Smrg
13932001f49Smrgstatic void
14032001f49SmrgKey(unsigned char key, int x, int y)
14132001f49Smrg{
14232001f49Smrg   const GLfloat step = 1.0;
14332001f49Smrg   (void) x;
14432001f49Smrg   (void) y;
14532001f49Smrg   switch (key) {
14632001f49Smrg      case 'a':
14732001f49Smrg         Anim = !Anim;
14832001f49Smrg         if (Anim)
14932001f49Smrg            glutIdleFunc(Idle);
15032001f49Smrg         else
15132001f49Smrg            glutIdleFunc(NULL);
15232001f49Smrg         break;
15332001f49Smrg      case 'd':
15432001f49Smrg         showZ = !showZ;
15532001f49Smrg         break;
15632001f49Smrg      case 'z':
15732001f49Smrg         Zpos -= step;
15832001f49Smrg         break;
15932001f49Smrg      case 'Z':
16032001f49Smrg         Zpos += step;
16132001f49Smrg         break;
16232001f49Smrg      case 27:
16332001f49Smrg         glutDestroyWindow(Win);
16432001f49Smrg         exit(0);
16532001f49Smrg         break;
16632001f49Smrg   }
16732001f49Smrg   glutPostRedisplay();
16832001f49Smrg}
16932001f49Smrg
17032001f49Smrg
17132001f49Smrgstatic void
17232001f49SmrgSpecialKey(int key, int x, int y)
17332001f49Smrg{
17432001f49Smrg   const GLfloat step = 3.0;
17532001f49Smrg   (void) x;
17632001f49Smrg   (void) y;
17732001f49Smrg   switch (key) {
17832001f49Smrg      case GLUT_KEY_UP:
17932001f49Smrg         Xrot -= step;
18032001f49Smrg         break;
18132001f49Smrg      case GLUT_KEY_DOWN:
18232001f49Smrg         Xrot += step;
18332001f49Smrg         break;
18432001f49Smrg      case GLUT_KEY_LEFT:
18532001f49Smrg         Yrot -= step;
18632001f49Smrg         break;
18732001f49Smrg      case GLUT_KEY_RIGHT:
18832001f49Smrg         Yrot += step;
18932001f49Smrg         break;
19032001f49Smrg   }
19132001f49Smrg   glutPostRedisplay();
19232001f49Smrg}
19332001f49Smrg
19432001f49Smrg
19532001f49Smrgstatic void
19632001f49SmrgInit(void)
19732001f49Smrg{
19832001f49Smrg   /* setup lighting, etc */
19932001f49Smrg   glEnable(GL_DEPTH_TEST);
20032001f49Smrg   glEnable(GL_LIGHTING);
20132001f49Smrg   glEnable(GL_LIGHT0);
20232001f49Smrg}
20332001f49Smrg
20432001f49Smrg
20532001f49Smrgint
20632001f49Smrgmain(int argc, char *argv[])
20732001f49Smrg{
20832001f49Smrg   glutInit(&argc, argv);
20932001f49Smrg   glutInitWindowPosition(0, 0);
21032001f49Smrg   glutInitWindowSize(Width, Height);
21132001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);
21232001f49Smrg   Win = glutCreateWindow(argv[0]);
21332001f49Smrg   glewInit();
21432001f49Smrg   glutReshapeFunc(Reshape);
21532001f49Smrg   glutKeyboardFunc(Key);
21632001f49Smrg   glutSpecialFunc(SpecialKey);
21732001f49Smrg   glutDisplayFunc(Draw);
21832001f49Smrg   if (Anim)
21932001f49Smrg      glutIdleFunc(Idle);
22032001f49Smrg   Init();
22132001f49Smrg   glutMainLoop();
22232001f49Smrg   return 0;
22332001f49Smrg}
224