#include "stdafx.h" #define GL_PI 3.1415f #define checkImageWidth 256 #define checkImageHeight 256 #define subImageWidth 64 #define subImageHeight 64 static GLubyte checkImage[checkImageHeight][checkImageWidth][4]; static GLubyte otherImage[checkImageHeight][checkImageWidth][4]; static GLubyte subImage[subImageHeight][subImageWidth][4]; static GLuint texName[1]; GLfloat colors[][3] = { { 0.0, 0.0, 0.0 },{ 1.0, 0.0, 0.0 }, { 1.0, 1.0, 0.0 },{ 0.0, 1.0, 0.0 },{ 0.0, 0.0, 1.0 }, { 1.0, 0.0, 1.0 },{ 1.0, 1.0, 1.0 },{ 0.0, 1.0, 1.0 } }; #define YGROUND 250. GLfloat pis[4] = { 0., 1., 0., YGROUND }, foco[4] = { 75., 150., -35., 1.f }, msobmra[16]; GLfloat ALFA = 0.75f; GLfloat ambientLight[] = { 0.1f, 0.1f, 0.1f, 1.0f }, diffuseLight[] = { 0.9f, 0.9f, 0.9f, 1.0f }, lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 }, specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }, specref[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat local_view[] = { 0.0 }; GLfloat mat_diffuse[] = { 0.8, 0.5, 0.1, 1.0 }; GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat high_shininess[] = { 100.0 }; GLfloat xRot = 0.45f; GLfloat yRot = 0.35f; GLboolean bCull = (GLboolean)true, bDepth = (GLboolean)true, bOutline = (GLboolean)true, bShade = (GLboolean)true; #define CX 0.0f #define CY 0.0f #define CZ 0.0f GLfloat ex = 0.0f; GLfloat ey = 100.0f; GLfloat ez = -700.0f; GLfloat cx = CX, cy = CY, cz = CZ; GLfloat delta = 0.01f; GLfloat deltaR = 0.01f; #define DELTATRANS 0.05f GLfloat deltatrans = DELTATRANS; void normalize(GLfloat v[3]) { GLfloat d = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); if (d == 0.0) { exit(100); return; } // wrong input exit v[0] /= d; v[1] /= d; v[2] /= d; } void normcrossprod(GLfloat v1[3], GLfloat v2[3], GLfloat out[3]) { out[0] = v1[1] * v2[2] - v1[2] * v2[1]; out[1] = v1[2] * v2[0] - v1[0] * v2[2]; out[2] = v1[0] * v2[1] - v1[1] * v2[0]; normalize(out); } void gltGetNormalVector(GLfloat v0[3], GLfloat //build normal 'norm' v1[3], GLfloat v2[3], GLfloat norm[3]) // by the triangle vrtices { GLfloat d1[3], d2[3]; for (int j = 0; j < 3; j++) { d1[j] = v0[j] - v1[j]; d2[j] = v1[j] - v2[j]; } normcrossprod(d1, d2, norm); } void makeCheckImages(void) { int i, j, c; for (i = 0; i < checkImageHeight; i++) { for (j = 0; j < checkImageWidth; j++) { c = ((((i & 0x8) == 0) ^ ((j & 0x8)) == 0)) * 255; checkImage[i][j][0] = (GLubyte)c; checkImage[i][j][1] = (GLubyte)c; checkImage[i][j][2] = (GLubyte)c; checkImage[i][j][3] = (GLubyte)255; c = ((((i & 0x10) == 0) ^ ((j & 0x10)) == 0)) * 255; otherImage[i][j][0] = (GLubyte)0; otherImage[i][j][1] = (GLubyte)0; otherImage[i][j][2] = (GLubyte)c; otherImage[i][j][3] = (GLubyte)255; } } for (i = 0; i < subImageHeight; i++) { for (j = 0; j < subImageWidth; j++) { c = ((((i & 0x4) == 0) ^ ((j & 0x4)) == 0)) * 255; subImage[i][j][0] = (GLubyte)c; subImage[i][j][1] = (GLubyte)0; subImage[i][j][2] = (GLubyte)0; subImage[i][j][3] = (GLubyte)255; } } } void unit_square() { glBegin(GL_QUADS); glNormal3f(0., 0., 1. /*-1.?*/ ); glVertex2f(-1., -1.); glVertex2f(1., -1.); glVertex2f(1., 1.); glVertex2f(-1., 1.); glEnd(); } void unit_square1() { glBegin(GL_QUADS); glNormal3f(0., 0., 1. /*-1.?*/); glColor4f(1., 0., 0., ALFA); glVertex2f(-1., -1.); glVertex2f(1., -1.); glVertex2f(1., 1.); glVertex2f(-1., 1.); glEnd(); } void unit_square_con_textura() { glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glBindTexture(GL_TEXTURE_2D, texName[0]); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex2f(-1., -1.); //glVertex3f(400.0f, -150.0f, -700.0f); //glVertex3f(-2.0, -1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex2f(1., -1.); //glVertex3f(-400.0f, -150.0f, -700.0f); //glVertex3f(-2.0, 1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex2f(1., 1.); //glVertex3f(-400.0f, -150.0f, 200.0f); //glVertex3f(0.0, 1.0, 0.0); glTexCoord2f(1.0, 0.0); glVertex2f(-1., 1.);// glVertex3f(400.0f, -150.0f, 200.0f);//glVertex3f(0.0, -1.0, 0.0); glEnd(); glDisable(GL_TEXTURE_2D); } void rayas() { glBegin(GL_LINES); int i; for (i = 0; i<11; i++) { glVertex2f(-1., -1. + i*2. / 10.); glVertex2f(1., -1. + i*2. / 10.); } for (i = 0; i<11; i++) { glVertex2f(1. - i*2. / 10., -1.); glVertex2f(1. - i*2. / 10., 1.); } glEnd(); } void piso() { glPushMatrix(); glTranslatef(0, -pis[3], 0); glRotatef(270, 1.0f, 0.0f, 0.0f); glScalef(150., 150., 150.); glColor4f(0.75, 0.75, 0.75, ALFA); unit_square(); glColor4f(0., 0., 0., ALFA); rayas(); glPopMatrix(); } void luz() { /*Esta funcion renderiza fuente luz y ademas mediante la 2a instruccion configura su posicion para el modelo de Phong*/ glColor4f(1., 1., 0., 1.); glLightfv(GL_LIGHT0, GL_POSITION, foco/*lightPos*/); glPushMatrix(); glTranslatef(foco[0], foco[1], foco[2]); glScalef(10., 10., 10.); glutSolidSphere(1, 20, 20); glPopMatrix(); } void colorcube2(void) { glPushMatrix(); glScalef(50., 50., 50.); //1a cara glPushMatrix(); glTranslatef(0., 0., 1.); //glColor4f(1.0, 0.0, 0.0, ALFA); unit_square1(); glPopMatrix(); //2a cara glPushMatrix(); glRotatef(90., 0., 1., 0.); glTranslatef(0., 0., 1.); //glColor4f(1./*0.0*/, 0./*1.0*/, 0.0, ALFA);// para la iluminacion unit_square1(); glPopMatrix(); //3a cara glPushMatrix(); glRotatef(180., 0., 1., 0.); glTranslatef(0., 0., 1.); unit_square_con_textura(); glPopMatrix(); //4a cara glPushMatrix(); glRotatef(90., 1., 0., 0.); glTranslatef(0., 0., 1.); unit_square1(); glPopMatrix(); //etc. ... glPopMatrix(); } void cubo_sin_color(void) { glPushMatrix(); glScalef(50., 50., 50.); //1a cara glPushMatrix(); glTranslatef(0., 0., 1.); unit_square(); glPopMatrix(); //2a cara glPushMatrix(); glRotatef(90., 0., 1., 0.); glTranslatef(0., 0., 1.); unit_square(); glPopMatrix(); //3a cara glPushMatrix(); glRotatef(180., 0., 1., 0.); glTranslatef(0., 0., 1.); unit_square(); glPopMatrix(); //4a cara glPushMatrix(); glRotatef(90., 1., 0., 0.); glTranslatef(0., 0., 1.); unit_square(); glPopMatrix(); //etc. ... glPopMatrix(); } /////////////////////////////////////////////////////////// void gltMakeShadowMatrix(GLfloat vPlaneEquation[], GLfloat vLightPos[], GLfloat destMat[]) { GLfloat dot; // Dot product of plane and light position dot = vPlaneEquation[0] * vLightPos[0] + vPlaneEquation[1] * vLightPos[1] + vPlaneEquation[2] * vLightPos[2] + vPlaneEquation[3] * vLightPos[3]; // Now do the projection // First column destMat[0] = dot - vLightPos[0] * vPlaneEquation[0]; destMat[4] = 0.0f - vLightPos[0] * vPlaneEquation[1]; destMat[8] = 0.0f - vLightPos[0] * vPlaneEquation[2]; destMat[12] = 0.0f - vLightPos[0] * vPlaneEquation[3]; // Second column destMat[1] = 0.0f - vLightPos[1] * vPlaneEquation[0]; destMat[5] = dot - vLightPos[1] * vPlaneEquation[1]; destMat[9] = 0.0f - vLightPos[1] * vPlaneEquation[2]; destMat[13] = 0.0f - vLightPos[1] * vPlaneEquation[3]; // Third Column destMat[2] = 0.0f - vLightPos[2] * vPlaneEquation[0]; destMat[6] = 0.0f - vLightPos[2] * vPlaneEquation[1]; destMat[10] = dot - vLightPos[2] * vPlaneEquation[2]; destMat[14] = 0.0f - vLightPos[2] * vPlaneEquation[3]; // Fourth Column destMat[3] = 0.0f - vLightPos[3] * vPlaneEquation[0]; destMat[7] = 0.0f - vLightPos[3] * vPlaneEquation[1]; destMat[11] = 0.0f - vLightPos[3] * vPlaneEquation[2]; destMat[15] = dot - vLightPos[3] * vPlaneEquation[3]; } void SombraCubo() { //glLightfv(GL_LIGHT0, GL_POSITION, foco); glPushMatrix(); gltMakeShadowMatrix(pis, foco, msobmra); glMultMatrixf(msobmra); glColor4f(0.7, 0.7, 0.7, ALFA); cubo_sin_color(); glPopMatrix(); } void SetupRC() { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); // Clockwise-wound polygons are front facing; this is reversed // because we are using triangle fans makeCheckImages(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(1, texName); glBindTexture(GL_TEXTURE_2D, texName[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage); glTexSubImage2D(GL_TEXTURE_2D, 0, 48, 170, subImageWidth, subImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glTexSubImage2D(GL_TEXTURE_2D, 0, 48, 48, subImageWidth, subImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glTexSubImage2D(GL_TEXTURE_2D, 0, 170, 48, subImageWidth, subImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glTexSubImage2D(GL_TEXTURE_2D, 0, 170, 170, subImageWidth, subImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, subImage); // Set up and enable light 0 glFrontFace(GL_CCW); glEnable(GL_LIGHTING); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glPolygonMode(GL_BACK, GL_FILL); GLfloat att[] = {1.}; glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); glLightfv(GL_LIGHT0, GL_SPECULAR, specular); //glLightfv(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, att); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view); glEnable(GL_LIGHT0); //glLightfv(GL_LIGHT0, GL_POSITION, foco); <- se llama en luz() // Enable color tracking glEnable(GL_COLOR_MATERIAL); // Front material ambient and diffuse colors track glColor glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // All materials hereafter have full specular reflectivity // with a high shine glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess); } void Stencil_Config() { // turning off writing to the color buffer and depth buffer so we only // write to stencil buffer glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(GL_FALSE); // enable stencil buffer glEnable(GL_STENCIL_TEST); // write a one to the stencil buffer everywhere we are about to draw glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); // this is to always pass a one to the stencil buffer where we draw glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); // render the plane which the shadow will be on // color and depth buffer are disabled, only the stencil buffer // will be modified piso(); // turn the color and depth buffers back on glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); // until stencil test is diabled, only write to areas where the // stencil buffer has a one. This is to draw the shadow only on // the floor. glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); // don't modify the contents of the stencil buffer glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); } // Called to draw scene void RenderScene(void) { // Reset coordinate system glLoadIdentity(); gluLookAt(ex, ey, ez, cx, cy, cz, 0.0, 1.0, 0.0); GLfloat x, y, angle; // Storage for coordinates and angles int iPivot = 1; // Used to flag alternating colors // Clear the window and the depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Turn culling on if flag is set if (bCull) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); // Enable depth testing if flag is set if (bDepth) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); // Draw the front /*back*/ side as a wireframe only, if flag is set if (bOutline)glPolygonMode(/*GL_BACK*/GL_FRONT, GL_LINE); else glPolygonMode(/*GL_BACK*/GL_FRONT, GL_FILL); glPushMatrix(); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glFrontFace(GL_CW); //cambio de orientacion //para ver objetos reflejados glPushMatrix(); glTranslatef(0., -pis[3], 0.); //trabnsformaciones glScalef(1., -1., 1.); // de glTranslatef(0., pis[3], 0.); //reflejo Stencil_Config(); colorcube2(); //dibujar el mundo luz(); //en espejo glPopMatrix(); //glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDisable(GL_DEPTH_TEST); // para luchar con errores de redondeo glFrontFace(GL_CCW); SombraCubo(); //dibujar sombra mezclandola con reflejo if (bDepth) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); if (bOutline)glPolygonMode(/*GL_BACK*/GL_FRONT, GL_LINE); else glPolygonMode(/*GL_BACK*/GL_FRONT, GL_FILL); piso(); //dibujar piso mezclandolo con reflejo+sombra glDisable(GL_BLEND); colorcube2(); luz(); glPopMatrix(); // Flush drawing commands glFlush();// glutSwapBuffers(); } // Called by GLUT library when the window has changed size void ChangeSize(GLsizei w, GLsizei h) { // Set Viewport to window dimensions glViewport(0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //glOrtho (-100.0, 100.0, -100, 100, -270.0, 270.0); //glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); gluPerspective(60.0, 1.0, 1.5, 2500.0); glMatrixMode(GL_MODELVIEW); } void SpecialKeys(int key, int x, int y) { GLfloat dx, dy, dz, dx0, dy0, dz0; if (key == GLUT_KEY_UP) {//increase distance from camera to origin ex *= (1.0f + deltaR); ey *= (1.0f + deltaR); ez *= (1.0f + deltaR); } if (key == GLUT_KEY_DOWN) {//reduce distance from camera to origin (close up) ex *= (1.0f - deltaR); ey *= (1.0f - deltaR); ez *= (1.0f - deltaR); } if (key == GLUT_KEY_LEFT) //Rotate camera around origin in Oxz plane { dx = -ez; dz = ex; GLfloat s = sqrtf(ex*ex + ey*ey + ez*ez); ex += delta*dx; ez += delta*dz; GLfloat s1 = sqrtf(ex*ex + ey*ey + ez*ez) / s; ex /= s1; ey /= s1; ey /= s1; } if (key == GLUT_KEY_RIGHT) //Rotate camera around origin in Oxz plane { dx = -ez; dz = ex; GLfloat s = sqrtf(ex*ex + ey*ey + ez*ez); ex -= delta*dx; ez -= delta*dz; GLfloat s1 = sqrtf(ex*ex + ey*ey + ez*ez) / s; ex /= s1; ey /= s1; ey /= s1; } if (key == GLUT_KEY_F1) bCull = !bCull; if (key == GLUT_KEY_F2)bDepth = !bDepth; if (key == GLUT_KEY_F3)bOutline = !bOutline; if (key == GLUT_KEY_F4) { bShade = !bShade; if (bShade) { glShadeModel(GL_FLAT); } else { glShadeModel(GL_SMOOTH); } } if (key == GLUT_KEY_F5)//Rotate camera around origin in Oyz plane { dy = -ez; dz = ey; GLfloat s = sqrtf(ex*ex + ey*ey + ez*ez); ey -= delta*dy; ez -= delta*dz; GLfloat s1 = sqrtf(ex*ex + ey*ey + ez*ez) / s; ex /= s1; ey /= s1; ey /= s1; } if (key == GLUT_KEY_F6)//Rotate camera around origin in Oyz plane { dy = -ez; dz = ey; GLfloat s = sqrtf(ex*ex + ey*ey + ez*ez); ey += delta*dy; ez += delta*dz; GLfloat s1 = sqrtf(ex*ex + ey*ey + ez*ez) / s; ex /= s1; ey /= s1; ey /= s1; } ////////// if (key == GLUT_KEY_F7)//Move light toward the center of ground { dx = cx - foco[0]; dy = cy - foco[1]; dz = cz - foco[2]; dx *= (1.0 - deltatrans); dy *= (1.0 - deltatrans); dz *= (1.0 - deltatrans); foco[0] = cx - dx; foco[1] = cy - dy; foco[2] = cz - dz; // Calculate new projection matrix to draw shadow on the ground } if (key == GLUT_KEY_F8)//Move light outward the center of ground { dx = cx - foco[0]; dy = cy - foco[1]; dz = cz - foco[2]; dx /= (1.0 - deltatrans); dy /= (1.0 - deltatrans); dz /= (1.0 - deltatrans); foco[0] = cx - dx; foco[1] = cy - dy; foco[2] = cz - dz; } if (key == GLUT_KEY_F9)//Rotate (+) light around ... in the vertical plane { dy0 = cz - foco[2]; dz0 = foco[1] - cy; dy = cy - foco[1]; dz = cz - foco[2]; GLfloat s = sqrtf(dy*dy + dz*dz); dy += delta*dy0; dz += delta*dz0; GLfloat s1 = sqrtf(dy*dy + dz*dz) / s; dy /= s1; dz /= s1; foco[1] = cy - dy; foco[2] = cz - dz; } if (key == GLUT_KEY_F10)//Rotate (-) light around ... in the vertical plane { dy0 = cz - foco[2]; dz0 = foco[1] - cy; dy = cy - foco[1]; dz = cz - foco[2]; GLfloat s = sqrtf(dy*dy + dz*dz); dy -= delta*dy0; dz -= delta*dz0; GLfloat s1 = sqrtf(dy*dy + dz*dz) / s; dy /= s1; dz /= s1; foco[1] = cy - dy; foco[2] = cz - dz; } if (key == GLUT_KEY_F11)//Rote light around ... in the horizontal plane { dy = - foco[2]; dz = foco[0]; GLfloat s = sqrtf( foco[0] * foco[0] + foco[1] * foco[1] + foco[2] * foco[2]); foco[0] += delta*dy; foco[2] += delta*dz; GLfloat s1 = sqrtf( foco[0] * foco[0] + foco[1] * foco[1] + foco[2] * foco[2]) / s; foco[0] /= s1; foco[1] /= s1; foco[2] /= s1; } if (key == GLUT_KEY_F12)//Move light in horiz. plane { dy = foco[0]; dz = foco[2]; foco[0] += delta*dy; foco[2] += delta*dz; } // Refresh the Window glutPostRedisplay(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(/*GLUT_DOUBLE*/GLUT_SINGLE | GLUT_RGBA | GLUT_STENCIL | GLUT_DEPTH); glutInitWindowSize(200, 200); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); glutDisplayFunc(RenderScene); glutReshapeFunc(ChangeSize); glutSpecialFunc(SpecialKeys); SetupRC(); glutMainLoop(); return 0; }