132001f49Smrg
232001f49Smrg/* Copyright (c) Mark J. Kilgard, 1994. */
332001f49Smrg
432001f49Smrg/*
532001f49Smrg * (c) Copyright 1993, Silicon Graphics, Inc.
632001f49Smrg * ALL RIGHTS RESERVED
732001f49Smrg * Permission to use, copy, modify, and distribute this software for
832001f49Smrg * any purpose and without fee is hereby granted, provided that the above
932001f49Smrg * copyright notice appear in all copies and that both the copyright notice
1032001f49Smrg * and this permission notice appear in supporting documentation, and that
1132001f49Smrg * the name of Silicon Graphics, Inc. not be used in advertising
1232001f49Smrg * or publicity pertaining to distribution of the software without specific,
1332001f49Smrg * written prior permission.
1432001f49Smrg *
1532001f49Smrg * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
1632001f49Smrg * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
1732001f49Smrg * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
1832001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
1932001f49Smrg * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
2032001f49Smrg * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
2132001f49Smrg * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
2232001f49Smrg * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
2332001f49Smrg * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
2432001f49Smrg * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
2532001f49Smrg * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
2632001f49Smrg * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
2732001f49Smrg *
2832001f49Smrg * US Government Users Restricted Rights
2932001f49Smrg * Use, duplication, or disclosure by the Government is subject to
3032001f49Smrg * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
3132001f49Smrg * (c)(1)(ii) of the Rights in Technical Data and Computer Software
3232001f49Smrg * clause at DFARS 252.227-7013 and/or in similar or successor
3332001f49Smrg * clauses in the FAR or the DOD or NASA FAR Supplement.
3432001f49Smrg * Unpublished-- rights reserved under the copyright laws of the
3532001f49Smrg * United States.  Contractor/manufacturer is Silicon Graphics,
3632001f49Smrg * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
3732001f49Smrg *
3832001f49Smrg * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
3932001f49Smrg */
4032001f49Smrg/*
4132001f49Smrg *  dof.c
4232001f49Smrg *  This program demonstrates use of the accumulation buffer to
4332001f49Smrg *  create an out-of-focus depth-of-field effect.  The teapots
4432001f49Smrg *  are drawn several times into the accumulation buffer.  The
4532001f49Smrg *  viewing volume is jittered, except at the focal point, where
4632001f49Smrg *  the viewing volume is at the same position, each time.  In
4732001f49Smrg *  this case, the gold teapot remains in focus.
4832001f49Smrg */
4932001f49Smrg#include <stdlib.h>
5032001f49Smrg#include <math.h>
5132001f49Smrg#include "glut_wrap.h"
5232001f49Smrg#include "jitter.h"
5332001f49Smrg
5432001f49Smrg#define PI_ 3.14159265358979323846
5532001f49Smrg
5632001f49Smrg/*	accFrustum()
5732001f49Smrg *  The first 6 arguments are identical to the glFrustum() call.
5832001f49Smrg *
5932001f49Smrg *  pixdx and pixdy are anti-alias jitter in pixels.
6032001f49Smrg *  Set both equal to 0.0 for no anti-alias jitter.
6132001f49Smrg *  eyedx and eyedy are depth-of field jitter in pixels.
6232001f49Smrg *  Set both equal to 0.0 for no depth of field effects.
6332001f49Smrg *
6432001f49Smrg *  focus is distance from eye to plane in focus.
6532001f49Smrg *  focus must be greater than, but not equal to 0.0.
6632001f49Smrg *
6732001f49Smrg *  Note that accFrustum() calls glTranslatef().  You will
6832001f49Smrg *  probably want to insure that your ModelView matrix has been
6932001f49Smrg *  initialized to identity before calling accFrustum().
7032001f49Smrg */
7132001f49Smrgstatic void accFrustum(GLdouble left, GLdouble right, GLdouble bottom,
7232001f49Smrg    GLdouble top, GLdouble nnear, GLdouble ffar, GLdouble pixdx,
7332001f49Smrg    GLdouble pixdy, GLdouble eyedx, GLdouble eyedy, GLdouble focus)
7432001f49Smrg{
7532001f49Smrg    GLdouble xwsize, ywsize;
7632001f49Smrg    GLdouble dx, dy;
7732001f49Smrg    GLint viewport[4];
7832001f49Smrg
7932001f49Smrg    glGetIntegerv (GL_VIEWPORT, viewport);
8032001f49Smrg
8132001f49Smrg    xwsize = right - left;
8232001f49Smrg    ywsize = top - bottom;
8332001f49Smrg
8432001f49Smrg    dx = -(pixdx*xwsize/(GLdouble) viewport[2] + eyedx*nnear/focus);
8532001f49Smrg    dy = -(pixdy*ywsize/(GLdouble) viewport[3] + eyedy*nnear/focus);
8632001f49Smrg
8732001f49Smrg    glMatrixMode(GL_PROJECTION);
8832001f49Smrg    glLoadIdentity();
8932001f49Smrg    glFrustum (left + dx, right + dx, bottom + dy, top + dy, nnear, ffar);
9032001f49Smrg    glMatrixMode(GL_MODELVIEW);
9132001f49Smrg    glLoadIdentity();
9232001f49Smrg    glTranslatef (-eyedx, -eyedy, 0.0);
9332001f49Smrg}
9432001f49Smrg
9532001f49Smrg/*  accPerspective()
9632001f49Smrg *
9732001f49Smrg *  The first 4 arguments are identical to the gluPerspective() call.
9832001f49Smrg *  pixdx and pixdy are anti-alias jitter in pixels.
9932001f49Smrg *  Set both equal to 0.0 for no anti-alias jitter.
10032001f49Smrg *  eyedx and eyedy are depth-of field jitter in pixels.
10132001f49Smrg *  Set both equal to 0.0 for no depth of field effects.
10232001f49Smrg *
10332001f49Smrg *  focus is distance from eye to plane in focus.
10432001f49Smrg *  focus must be greater than, but not equal to 0.0.
10532001f49Smrg *
10632001f49Smrg *  Note that accPerspective() calls accFrustum().
10732001f49Smrg */
10832001f49Smrgstatic void accPerspective(GLdouble fovy, GLdouble aspect,
10932001f49Smrg    GLdouble nnear, GLdouble ffar, GLdouble pixdx, GLdouble pixdy,
11032001f49Smrg    GLdouble eyedx, GLdouble eyedy, GLdouble focus)
11132001f49Smrg{
11232001f49Smrg    GLdouble fov2,left,right,bottom,top;
11332001f49Smrg
11432001f49Smrg    fov2 = ((fovy*PI_) / 180.0) / 2.0;
11532001f49Smrg
11632001f49Smrg    top = nnear / (cos(fov2) / sin(fov2));
11732001f49Smrg    bottom = -top;
11832001f49Smrg
11932001f49Smrg    right = top * aspect;
12032001f49Smrg    left = -right;
12132001f49Smrg
12232001f49Smrg    accFrustum (left, right, bottom, top, nnear, ffar,
12332001f49Smrg	pixdx, pixdy, eyedx, eyedy, focus);
12432001f49Smrg}
12532001f49Smrg
12632001f49Smrgstatic void myinit(void)
12732001f49Smrg{
12832001f49Smrg    GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
12932001f49Smrg    GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
13032001f49Smrg    GLfloat position[] = { 0.0, 3.0, 3.0, 0.0 };
13132001f49Smrg
13232001f49Smrg    GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
13332001f49Smrg    GLfloat local_view[] = { 0.0 };
13432001f49Smrg
13532001f49Smrg    glEnable(GL_DEPTH_TEST);
13632001f49Smrg    glDepthFunc(GL_LESS);
13732001f49Smrg
13832001f49Smrg    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
13932001f49Smrg    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
14032001f49Smrg    glLightfv(GL_LIGHT0, GL_POSITION, position);
14132001f49Smrg
14232001f49Smrg    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
14332001f49Smrg    glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);
14432001f49Smrg
14532001f49Smrg    glFrontFace (GL_CW);
14632001f49Smrg    glEnable(GL_LIGHTING);
14732001f49Smrg    glEnable(GL_LIGHT0);
14832001f49Smrg    glEnable(GL_AUTO_NORMAL);
14932001f49Smrg    glEnable(GL_NORMALIZE);
15032001f49Smrg
15132001f49Smrg    glMatrixMode (GL_MODELVIEW);
15232001f49Smrg    glLoadIdentity ();
15332001f49Smrg
15432001f49Smrg    glClearColor(0.0, 0.0, 0.0, 0.0);
15532001f49Smrg    glClearAccum(0.0, 0.0, 0.0, 0.0);
15632001f49Smrg}
15732001f49Smrg
15832001f49Smrgstatic void renderTeapot (GLfloat x, GLfloat y, GLfloat z,
15932001f49Smrg    GLfloat ambr, GLfloat ambg, GLfloat ambb,
16032001f49Smrg    GLfloat difr, GLfloat difg, GLfloat difb,
16132001f49Smrg    GLfloat specr, GLfloat specg, GLfloat specb, GLfloat shine)
16232001f49Smrg{
16332001f49Smrg    float mat[4];
16432001f49Smrg
16532001f49Smrg    glPushMatrix();
16632001f49Smrg    glTranslatef (x, y, z);
16732001f49Smrg    mat[0] = ambr; mat[1] = ambg; mat[2] = ambb; mat[3] = 1.0;
16832001f49Smrg    glMaterialfv (GL_FRONT, GL_AMBIENT, mat);
16932001f49Smrg    mat[0] = difr; mat[1] = difg; mat[2] = difb;
17032001f49Smrg    glMaterialfv (GL_FRONT, GL_DIFFUSE, mat);
17132001f49Smrg    mat[0] = specr; mat[1] = specg; mat[2] = specb;
17232001f49Smrg    glMaterialfv (GL_FRONT, GL_SPECULAR, mat);
17332001f49Smrg    glMaterialf (GL_FRONT, GL_SHININESS, shine*128.0);
17432001f49Smrg    glutSolidTeapot(0.5);
17532001f49Smrg    glPopMatrix();
17632001f49Smrg}
17732001f49Smrg
17832001f49Smrg/*  display() draws 5 teapots into the accumulation buffer
17932001f49Smrg *  several times; each time with a jittered perspective.
18032001f49Smrg *  The focal point is at z = 5.0, so the gold teapot will
18132001f49Smrg *  stay in focus.  The amount of jitter is adjusted by the
18232001f49Smrg *  magnitude of the accPerspective() jitter; in this example, 0.33.
18332001f49Smrg *  In this example, the teapots are drawn 8 times.  See jitter.h
18432001f49Smrg */
18532001f49Smrgstatic void display(void)
18632001f49Smrg{
18732001f49Smrg    int jitter;
18832001f49Smrg    GLint viewport[4];
18932001f49Smrg
19032001f49Smrg    glGetIntegerv (GL_VIEWPORT, viewport);
19132001f49Smrg    glClear(GL_ACCUM_BUFFER_BIT);
19232001f49Smrg
19332001f49Smrg    for (jitter = 0; jitter < 8; jitter++) {
19432001f49Smrg	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
19532001f49Smrg	accPerspective (45.0,
19632001f49Smrg		(GLdouble) viewport[2]/(GLdouble) viewport[3],
19732001f49Smrg		1.0, 15.0, 0.0, 0.0,
19832001f49Smrg		0.33*j8[jitter].x, 0.33*j8[jitter].y, 5.0);
19932001f49Smrg/*	ruby, gold, silver, emerald, and cyan teapots	*/
20032001f49Smrg	renderTeapot (-1.1, -0.5, -4.5, 0.1745, 0.01175, 0.01175,
20132001f49Smrg	    0.61424, 0.04136, 0.04136, 0.727811, 0.626959, 0.626959, 0.6);
20232001f49Smrg	renderTeapot (-0.5, -0.5, -5.0, 0.24725, 0.1995, 0.0745,
20332001f49Smrg	    0.75164, 0.60648, 0.22648, 0.628281, 0.555802, 0.366065, 0.4);
20432001f49Smrg	renderTeapot (0.2, -0.5, -5.5, 0.19225, 0.19225, 0.19225,
20532001f49Smrg	    0.50754, 0.50754, 0.50754, 0.508273, 0.508273, 0.508273, 0.4);
20632001f49Smrg	renderTeapot (1.0, -0.5, -6.0, 0.0215, 0.1745, 0.0215,
20732001f49Smrg	    0.07568, 0.61424, 0.07568, 0.633, 0.727811, 0.633, 0.6);
20832001f49Smrg	renderTeapot (1.8, -0.5, -6.5, 0.0, 0.1, 0.06, 0.0, 0.50980392,
20932001f49Smrg	    0.50980392, 0.50196078, 0.50196078, 0.50196078, .25);
21032001f49Smrg	glAccum (GL_ACCUM, 0.125);
21132001f49Smrg    }
21232001f49Smrg
21332001f49Smrg    glAccum (GL_RETURN, 1.0);
21432001f49Smrg    glFlush();
21532001f49Smrg}
21632001f49Smrg
21732001f49Smrgstatic void myReshape(int w, int h)
21832001f49Smrg{
21932001f49Smrg    glViewport(0, 0, w, h);
22032001f49Smrg}
22132001f49Smrg
22232001f49Smrgstatic void
22332001f49Smrgkey(unsigned char k, int x, int y)
22432001f49Smrg{
22532001f49Smrg  switch (k) {
22632001f49Smrg  case 27:  /* Escape */
22732001f49Smrg    exit(0);
22832001f49Smrg    break;
22932001f49Smrg  default:
23032001f49Smrg    return;
23132001f49Smrg  }
23232001f49Smrg  glutPostRedisplay();
23332001f49Smrg}
23432001f49Smrg
23532001f49Smrg/*  Main Loop
23632001f49Smrg *  Open window with initial window size, title bar,
23732001f49Smrg *  RGBA display mode, depth buffer, and handle input events.
23832001f49Smrg */
23932001f49Smrgint main(int argc, char** argv)
24032001f49Smrg{
24132001f49Smrg    glutInit(&argc, argv);
24232001f49Smrg    glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB
24332001f49Smrg			| GLUT_ACCUM | GLUT_DEPTH);
24432001f49Smrg    glutCreateWindow (argv[0]);
24532001f49Smrg    myinit();
24632001f49Smrg    glutReshapeFunc(myReshape);
24732001f49Smrg    glutDisplayFunc(display);
24832001f49Smrg    glutKeyboardFunc(key);
24932001f49Smrg    glutMainLoop();
25032001f49Smrg    return 0;             /* ANSI C requires main to return int. */
25132001f49Smrg}
252