Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабораторная работа №6 / projshadow
.c// Lab 6 in computer graphics.
// Konstantin Filippov
// SPb ETU LETI / MOEVM 2007
#include <GL/glut.h>
#include <stdlib.h>
#include "texture.h"
enum {SPHERE = 1, CONE, LIGHT};
enum {X, Y, Z, W};
enum {A, B, C, D};
GLfloat dxCone = -40;
GLfloat dyCone = -40;
GLfloat dzCone = -400;
GLfloat dxShere = 60;
GLfloat dyShere = -50;
GLfloat dzShere = -360;
int sphereStripple = 8;
/* create a matrix that will project the desired shadow */
void shadowmatrix(GLfloat shadowMat[4][4], GLfloat groundplane[4], GLfloat lightpos[4])
{
GLfloat dot;
/* find dot product between light position vector and ground plane normal */
dot = groundplane[X] * lightpos[X] +
groundplane[Y] * lightpos[Y] +
groundplane[Z] * lightpos[Z] +
groundplane[W] * lightpos[W];
shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
}
/* find the plane equation given 3 points */
void findplane(GLfloat plane[4], GLfloat v0[3], GLfloat v1[3], GLfloat v2[3])
{
GLfloat vec0[3], vec1[3];
/* need 2 vectors to find cross product */
vec0[X] = v1[X] - v0[X];
vec0[Y] = v1[Y] - v0[Y];
vec0[Z] = v1[Z] - v0[Z];
vec1[X] = v2[X] - v0[X];
vec1[Y] = v2[Y] - v0[Y];
vec1[Z] = v2[Z] - v0[Z];
/* find cross product to get A, B, and C of plane equation */
plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];
plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]);
}
void sphere(float dx, float dy, float dz)
{
glPushMatrix();
glTranslatef(dx, dy, dz);
glCallList(SPHERE);
glPopMatrix();
}
void cone(float dx, float dy, float dz)
{
glPushMatrix();
glTranslatef(dx, dy, dz);
glCallList(CONE);
glPopMatrix();
}
enum {NONE, SHADOW};
//int rendermode = NONE;
int rendermode = SHADOW;
void menu(int mode)
{
rendermode = mode;
glutPostRedisplay();
}
GLfloat leftwallshadow[4][4];
GLfloat floorshadow[4][4];
GLfloat rightwallshadow[4][4];
GLfloat backwallshadow[4][4];
GLfloat ceilingshadow[4][4];
GLfloat x = 0;
GLfloat y = 0;
GLfloat z = 0;
GLfloat lightpos[] = {50.f, 50.f, -320.f, 1.f};
GLfloat plane[4];
GLfloat v0[3], v1[3], v2[3];
void redraw(void)
{
/* material properties for objects in scene */
static GLfloat wall_mat[] = {0.8f, 1.f, 1.f, 1.f};
static GLfloat sphere_mat[] = {1.f, 1.0f, .1f, .5f};
static GLfloat cone_mat[] = {0.2f, .5f, .3f, .8f};
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
/*
** Note: wall verticies are ordered so they are all front facing
** this lets me do back face culling to speed things up.
*/
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
/* floor */
if(rendermode == SHADOW)
{
/* glClear(GL_STENCIL_BUFFER_BIT); *//* set all stencil bits to 0 */
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
//glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glNormal3f(0.f, 1.f, 0.f);
glTexCoord2i(0, 0);
glVertex3f(-100.f, -100.f, -320.f);
glTexCoord2i(1, 0);
glVertex3f( 100.f, -100.f, -320.f);
glTexCoord2i(1, 1);
glVertex3f( 100.f, -100.f, -520.f);
glTexCoord2i(0, 1);
glVertex3f(-100.f, -100.f, -520.f);
glEnd();
// glDisable(GL_TEXTURE_2D);
if(rendermode == SHADOW) {
/* clear stencil buffer where shadow is cast */
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
glDisable(GL_DEPTH_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glPushMatrix();
glMultMatrixf((GLfloat *)floorshadow);
cone(dxCone, dyCone, dzCone);
glPopMatrix();
glEnable(GL_POLYGON_STIPPLE);
glPushMatrix();
glMultMatrixf((GLfloat *)floorshadow);
sphere(dxShere, dyShere, dzShere);
glPopMatrix();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
/* draw unlit wall where stencil == 0 */
glDisable(GL_LIGHT0);
glStencilFunc(GL_EQUAL, 0, 1);
glDepthFunc(GL_LEQUAL);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glNormal3f(0.f, 1.f, 0.f);
glTexCoord2i(0, 0);
glVertex3f(-100.f, -100.f, -320.f);
glTexCoord2i(1, 0);
glVertex3f( 100.f, -100.f, -320.f);
glTexCoord2i(1, 1);
glVertex3f( 100.f, -100.f, -520.f);
glTexCoord2i(0, 1);
glVertex3f(-100.f, -100.f, -520.f);
glEnd();
glDisable(GL_TEXTURE_2D);
glDepthFunc(GL_LESS);
glDisable(GL_STENCIL_TEST);
glEnable(GL_LIGHT0);
}
/* walls */
if(rendermode == SHADOW) {
glClear(GL_STENCIL_BUFFER_BIT); /* set all stencil bits to 0 */
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
/* set stencil = 1 for entire visible wall */
/* (masking out floor) */
glBegin(GL_QUADS);
/* left wall */
glNormal3f(1.f, 0.f, 0.f);
glVertex3f(-100.f, -100.f, -320.f);
glVertex3f(-100.f, -100.f, -520.f);
glVertex3f(-100.f, 100.f, -520.f);
glVertex3f(-100.f, 100.f, -320.f);
glEnd();
if(rendermode == SHADOW) {
/* clear stencil buffer where shadow is cast */
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
glDisable(GL_DEPTH_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glPushMatrix();
glMultMatrixf((GLfloat *)leftwallshadow);
cone(dxCone, dyCone, dzCone);
sphere(dxShere, dyShere, dzShere);
glPopMatrix();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
/* draw unlit wall where stencil == 0 */
glDisable(GL_LIGHT0);
glStencilFunc(GL_EQUAL, 0, 1);
glDepthFunc(GL_LEQUAL);
glBegin(GL_QUADS);
/* left wall */
glNormal3f(1.f, 0.f, 0.f);
glVertex3f(-100.f, -100.f, -320.f);
glVertex3f(-100.f, -100.f, -520.f);
glVertex3f(-100.f, 100.f, -520.f);
glVertex3f(-100.f, 100.f, -320.f);
glEnd();
glDepthFunc(GL_LESS);
glDisable(GL_STENCIL_TEST);
glEnable(GL_LIGHT0);
}
if(rendermode == SHADOW) {
glClear(GL_STENCIL_BUFFER_BIT); /* set all stencil bits to 0 */
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
/* set stencil = 1 for entire visible wall */
/* (masking out floor) */
glBegin(GL_QUADS);
/* right wall */
glNormal3f(-1.f, 0.f, 0.f);
glVertex3f( 100.f, -100.f, -320.f);
glVertex3f( 100.f, 100.f, -320.f);
glVertex3f( 100.f, 100.f, -520.f);
glVertex3f( 100.f, -100.f, -520.f);
glEnd();
if(rendermode == SHADOW) {
/* clear stencil buffer where shadow is cast */
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
glDisable(GL_DEPTH_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glPushMatrix();
glMultMatrixf((GLfloat *)rightwallshadow);
cone(dxCone, dyCone, dzCone);
sphere(dxShere, dyShere, dzShere);
glPopMatrix();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
/* draw unlit wall where stencil == 0 */
glDisable(GL_LIGHT0);
glStencilFunc(GL_EQUAL, 0, 1);
glDepthFunc(GL_LEQUAL);
glBegin(GL_QUADS);
/* right wall */
glNormal3f(-1.f, 0.f, 0.f);
glVertex3f( 100.f, -100.f, -320.f);
glVertex3f( 100.f, 100.f, -320.f);
glVertex3f( 100.f, 100.f, -520.f);
glVertex3f( 100.f, -100.f, -520.f);
glEnd();
glDepthFunc(GL_LESS);
glDisable(GL_STENCIL_TEST);
glEnable(GL_LIGHT0);
}
if(rendermode == SHADOW) {
glClear(GL_STENCIL_BUFFER_BIT); /* set all stencil bits to 0 */
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
/* set stencil = 1 for entire visible wall */
/* (masking out floor) */
glBegin(GL_QUADS);
/* ceiling */
glNormal3f(0.f, -1.f, 0.f);
glVertex3f(-100.f, 100.f, -320.f);
glVertex3f(-100.f, 100.f, -520.f);
glVertex3f( 100.f, 100.f, -520.f);
glVertex3f( 100.f, 100.f, -320.f);
glEnd();
if(rendermode == SHADOW) {
/* clear stencil buffer where shadow is cast */
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
glDisable(GL_DEPTH_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glPushMatrix();
glMultMatrixf((GLfloat *)ceilingshadow);
cone(dxCone, dyCone, dzCone);
sphere(dxShere, dyShere, dzShere);
glPopMatrix();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
/* draw unlit wall where stencil == 0 */
glDisable(GL_LIGHT0);
glStencilFunc(GL_EQUAL, 0, 1);
glDepthFunc(GL_LEQUAL);
glBegin(GL_QUADS);
/* ceiling */
glNormal3f(0.f, -1.f, 0.f);
glVertex3f(-100.f, 100.f, -320.f);
glVertex3f(-100.f, 100.f, -520.f);
glVertex3f( 100.f, 100.f, -520.f);
glVertex3f( 100.f, 100.f, -320.f);
glEnd();
glDepthFunc(GL_LESS);
glDisable(GL_STENCIL_TEST);
glEnable(GL_LIGHT0);
}
if(rendermode == SHADOW) {
glClear(GL_STENCIL_BUFFER_BIT); /* set all stencil bits to 0 */
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
/* set stencil = 1 for entire visible wall */
/* (masking out floor) */
glBegin(GL_QUADS);
/* back wall */
glNormal3f(0.f, 0.f, 1.f);
glVertex3f(-100.f, -100.f, -520.f);
glVertex3f( 100.f, -100.f, -520.f);
glVertex3f( 100.f, 100.f, -520.f);
glVertex3f(-100.f, 100.f, -520.f);
glEnd();
if(rendermode == SHADOW) {
/* clear stencil buffer where shadow is cast */
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
glDisable(GL_DEPTH_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glPushMatrix();
glMultMatrixf((GLfloat *)backwallshadow);
cone(dxCone, dyCone, dzCone);
sphere(dxShere, dyShere, dzShere);
glPopMatrix();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
/* draw unlit wall where stencil == 0 */
glDisable(GL_LIGHT0);
glStencilFunc(GL_EQUAL, 0, 1);
glDepthFunc(GL_LEQUAL);
glBegin(GL_QUADS);
/* back wall */
glNormal3f(0.f, 0.f, 1.f);
glVertex3f(-100.f, -100.f, -520.f);
glVertex3f( 100.f, -100.f, -520.f);
glVertex3f( 100.f, 100.f, -520.f);
glVertex3f(-100.f, 100.f, -520.f);
glEnd();
glDepthFunc(GL_LESS);
glDisable(GL_STENCIL_TEST);
glEnable(GL_LIGHT0);
}
glPushMatrix();
//glTranslatef(lightpos[X], lightpos[Y], lightpos[Z]);
glDisable(GL_LIGHTING);
glColor3f(1.f, 1.f, .7f);
glCallList(LIGHT);
glEnable(GL_LIGHTING);
glPopMatrix();
glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
/* make shadow matricies */
/* 3 points on floor */
v0[X] = -100.f; v0[Y] = -100.f; v0[Z] = -320.f;
v1[X] = 100.f; v1[Y] = -100.f; v1[Z] = -320.f;
v2[X] = 100.f; v2[Y] = -100.f; v2[Z] = -520.f;
findplane(plane, v0, v1, v2);
shadowmatrix(floorshadow, plane, lightpos);
/* 3 points on left wall */
v0[X] = -100.f; v0[Y] = -100.f; v0[Z] = -320.f;
v1[X] = -100.f; v1[Y] = -100.f; v1[Z] = -520.f;
v2[X] = -100.f; v2[Y] = 100.f; v2[Z] = -520.f;
findplane(plane, v0, v1, v2);
shadowmatrix(leftwallshadow, plane, lightpos);
/* 3 points on right wall */
v0[X] = 100.f; v0[Y] = -100.f; v0[Z] = -320.f;
v1[X] = 100.f; v1[Y] = 100.f; v1[Z] = -320.f;
v2[X] = 100.f; v2[Y] = 100.f; v2[Z] = -520.f;
findplane(plane, v0, v1, v2);
shadowmatrix(rightwallshadow, plane, lightpos);
/* 3 points on ceiling */
v0[X] =-100.f; v0[Y] = 100.f; v0[Z] = -320.f;
v1[X] =-100.f; v1[Y] = 100.f; v1[Z] = -520.f;
v2[X] = 100.f; v2[Y] = 100.f; v2[Z] = -520.f;
findplane(plane, v0, v1, v2);
shadowmatrix(ceilingshadow, plane, lightpos);
/* 3 points on back wall */
v0[X] =-100.f; v0[Y] = -100.f; v0[Z] = -520.f;
v1[X] = 100.f; v1[Y] = -100.f; v1[Z] = -520.f;
v2[X] = 100.f; v2[Y] = 100.f; v2[Z] = -520.f;
findplane(plane, v0, v1, v2);
shadowmatrix(backwallshadow, plane, lightpos);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
cone(dxCone, dyCone, dzCone);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
sphere(dxShere, dyShere, dzShere);
glutSwapBuffers(); /* high end machines may need this */
}
void key(unsigned char key, int x, int y)
{
switch(key)
{
case 'q':
dxCone = dxCone - 10;
break;
case 'w':
dxCone = dxCone + 10;
break;
case 'a':
dyCone = dyCone - 10;
break;
case 's':
dyCone = dyCone + 10;
break;
case 'z':
dzCone = dzCone - 10;
break;
case 'x':
dzCone = dzCone + 10;
break;
case 'e':
dxShere = dxShere - 10;
break;
case 'r':
dxShere = dxShere + 10;
break;
case 'd':
dyShere= dyShere - 10;
break;
case 'f':
dyShere = dyShere + 10;
break;
case 'c':
dzShere = dzShere - 10;
break;
case 'v':
dzShere = dzShere + 10;
break;
case 't':
lightpos[0] = lightpos[0] - 10;
break;
case 'y':
lightpos[0] = lightpos[0] + 10;
break;
case 'g':
lightpos[1] = lightpos[1] - 10;
break;
case 'h':
lightpos[1] = lightpos[1] + 10;
break;
case 'b':
lightpos[2] = lightpos[2] - 10;
break;
case 'n':
lightpos[2] = lightpos[2] + 10;
break;
case '\033':
exit(0);
break;
default:
//help();
break;
}
}
const int TEXDIM = 256;
main(int argc, char *argv[])
{
int texwid, texht, texcomps;
unsigned int *tex;
GLUquadricObj *sphere, *cone, *base;
//GLfloat plane[4];
//GLfloat v0[3], v1[3], v2[3];
glutInit(&argc, argv);
glutInitWindowSize(512, 512);
glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL|GLUT_DOUBLE);
(void)glutCreateWindow("KG Lab 6 Task 1.5");
glutDisplayFunc(redraw);
glutKeyboardFunc(key);
glutIdleFunc(redraw);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/*
glutCreateMenu(menu);
glutAddMenuEntry("No Shadows", NONE);
glutAddMenuEntry("Shadows", SHADOW);
glutAttachMenu(GLUT_RIGHT_BUTTON);
*/
/* draw a perspective scene */
glMatrixMode(GL_PROJECTION);
glFrustum(-100., 100., -100., 100., 320., 640.);
glMatrixMode(GL_MODELVIEW);
/* turn on features */
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
/* place light 0 in the right place */
//glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
/* remove back faces to speed things up */
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
/* make display lists for sphere and cone; for efficiency */
glNewList(SPHERE, GL_COMPILE);
sphere = gluNewQuadric();
gluSphere(sphere, 20.f, 20, 20);
gluDeleteQuadric(sphere);
glEndList();
glNewList(LIGHT, GL_COMPILE);
sphere = gluNewQuadric();
gluSphere(sphere, 5.f, 20, 20);
gluDeleteQuadric(sphere);
glEndList();
glNewList(CONE, GL_COMPILE);
cone = gluNewQuadric();
base = gluNewQuadric();
glRotatef(-90.f, 1.f, 0.f, 0.f);
gluDisk(base, 0., 20., 20, 1);
gluCylinder(cone, 20., 0., 60., 20, 20);
gluDeleteQuadric(cone);
gluDeleteQuadric(base);
glEndList();
tex = read_texture("wood0.rgb", &texwid, &texht, &texcomps);
glTexImage2D(GL_TEXTURE_2D, 0, texcomps, texwid, texht, 0, GL_RGBA,
GL_UNSIGNED_BYTE, tex);
free(tex);
glutMainLoop();
return 0;
}
Соседние файлы в папке Лабораторная работа №6