#include #include // function prototypes void display(void); void reshape(int width, int height); void keyboard(unsigned char key, int x, int y); void init(void); void shadowMatrixPointLight(float matrix[16], float groundPlane[4], float lightPosition[4]); void drawCube(void); // global yuck float pointLightPosition[]={-3.0f,2.0f,0.0f,1.0f}; int main(int argc, char **argv) { // set up window glutInitWindowSize(400, 400); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutCreateWindow("Shadow Lab"); // register callback functions glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glBlendFunc(GL_SRC_ALPHA,GL_SRC_ALPHA); // initalize opengl parameters init(); // loop until something happens glutMainLoop(); return 0; } void init() { // initialize viewing system glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, 1.0, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); // initialize shade model to smooth glShadeModel(GL_SMOOTH); // initialize background color to white glClearColor(1.0,1.0,1.0,0.0); // initialize stencil value glClearStencil(0.0); // enable depth buffering glEnable(GL_DEPTH_TEST); // create some ambient light float ambient[]={0.5f,.5f,.5f}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); // create a point light float pointLightColor[]={1.0f,1.0f,1.0f,1.0f}; glLightfv(GL_LIGHT0, GL_POSITION, pointLightPosition); glLightfv(GL_LIGHT0, GL_DIFFUSE, pointLightColor); glLightfv(GL_LIGHT0, GL_SPECULAR, pointLightColor); // enable lighting and the point light glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); // set polygon mode glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); // set polygon offset glPolygonOffset(-1.0,-1.0); } void reshape(int width, int height) { glViewport(0,0,width,height); } void display() { // initialize modelview matrix glLoadIdentity(); gluLookAt(0.0,3.0,10.0,0.0,0.0,0.0,0.0,1.0,0.0); // clear buffers glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS,3,3); glStencilOp(GL_REPLACE,GL_REPLACE,GL_REPLACE); // draw a floor float floorDiffuse[]={1.0f, 0.0f, 0.0f}; float floorAmbient[]={1.0f, 0.0f, 0.0f}; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, floorDiffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, floorAmbient); glNormal3f(0,1,0); glBegin(GL_QUADS); glVertex3f(-5,0,-5); glVertex3f(-5,0,5); glVertex3f(5,0,5); glVertex3f(5,0,-5); glEnd(); glDisable(GL_STENCIL_TEST); // draw a cube float cubeDiffuse[]={0.0f, 0.0f, 0.8f}; float cubeAmbient[]={0.0f, 0.0f, 0.8f}; glMaterialfv(GL_FRONT, GL_DIFFUSE, cubeDiffuse); glMaterialfv(GL_FRONT, GL_AMBIENT, cubeAmbient); drawCube(); //shadow glEnable(GL_STENCIL_TEST); glStencilFunc(GL_GREATER,2,3); glStencilOp(GL_KEEP,GL_REPLACE,GL_REPLACE); float groundPlane[] = {0,1,0,0}; float shadowMatrix[16]; float shadow[] = {0,0,0,0.5}; shadowMatrixPointLight(shadowMatrix, groundPlane, pointLightPosition); glPushMatrix(); glEnable(GL_POLYGON_OFFSET_FILL); glEnable(GL_BLEND); glMultMatrixf(shadowMatrix); glMaterialfv(GL_FRONT, GL_DIFFUSE, shadow); glMaterialfv(GL_FRONT, GL_AMBIENT, shadow); drawCube(); glDisable(GL_BLEND); glDisable(GL_POLYGON_OFFSET_FILL); glPopMatrix(); glDisable(GL_STENCIL_TEST); glutSwapBuffers(); } void keyboard(unsigned char key, int mouseX, int mouseY) { } /* Create a matrix that will project the desired shadow. */ void shadowMatrixPointLight(GLfloat shadowMat[16], GLfloat groundplane[4], GLfloat lightpos[4]) { GLfloat dot; /* Find dot product between light position vector and ground plane normal. */ dot = groundplane[0] * lightpos[0] + groundplane[1] * lightpos[1] + groundplane[2] * lightpos[2] + groundplane[3] * lightpos[3]; shadowMat[0] = dot - lightpos[0] * groundplane[0]; shadowMat[4] = 0.f - lightpos[0] * groundplane[1]; shadowMat[8] = 0.f - lightpos[0] * groundplane[2]; shadowMat[12] = 0.f - lightpos[0] * groundplane[3]; shadowMat[1] = 0.f - lightpos[1] * groundplane[0]; shadowMat[5] = dot - lightpos[1] * groundplane[1]; shadowMat[9] = 0.f - lightpos[1] * groundplane[2]; shadowMat[13] = 0.f - lightpos[1] * groundplane[3]; shadowMat[2] = 0.f - lightpos[2] * groundplane[0]; shadowMat[6] = 0.f - lightpos[2] * groundplane[1]; shadowMat[10] = dot - lightpos[2] * groundplane[2]; shadowMat[14] = 0.f - lightpos[2] * groundplane[3]; shadowMat[3] = 0.f - lightpos[3] * groundplane[0]; shadowMat[7] = 0.f - lightpos[3] * groundplane[1]; shadowMat[11] = 0.f - lightpos[3] * groundplane[2]; shadowMat[15] = dot - lightpos[3] * groundplane[3]; } void drawCube(void) { glPushMatrix(); glTranslatef(0.0f,0.5f,0.0f); glutSolidCube( 1.0); glPopMatrix(); }