void CMirror::drawMirrorImage(void (*drawScene)(), const CLighting& lighting) { glClear(GL_STENCIL_BUFFER_BIT); if (showMirror) { // Don't update color or depth. glDisable(GL_DEPTH_TEST); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Draw 1 into the stencil buffer. glEnable(GL_STENCIL_TEST); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glStencilFunc(GL_ALWAYS, 1, 0xffffffff); // Now render mirror; mirror pixels just get their stencil set to 1. glEnable(GL_CULL_FACE); drawMirror(MIRROR_FRONT); glDisable(GL_CULL_FACE); // Re-enable update of color and depth. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glEnable(GL_DEPTH_TEST); // Now, only render where stencil is set to 1. glStencilFunc(GL_EQUAL, 1, 0xffffffff); // draw if ==1 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glPushMatrix(); applyReflectionMatrix(); lighting.init(); // mirror light sources drawScene(); // render the reflected scene glPopMatrix(); glDisable(GL_STENCIL_TEST); lighting.init(); // back to the original light sources // Back face culling will get used to only draw either the front side or the // back side of the mirror. This let's us get a mirror with two distinct // appearances. The front surface is reflective and kind of grayish. // The back surface is not reflective and blue. // Draw "back" of mirror in blue. glColor4f(0.1f, 0.1f, 0.5f, 1.0f); glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); drawMirror(MIRROR_BACK); glCullFace(GL_BACK); glDisable(GL_CULL_FACE); // Draw the mirror with stencil value 3. glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 3, 0xffffffff); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // Draw reflective side of mirror. Use blending to blend in reflection. glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(0.9, 0.9, 0.9, 0.3); glCullFace(GL_BACK); drawMirror(MIRROR_FRONT); glDisable(GL_BLEND); drawMirror(MIRROR_BOUNDARY); } }
void drawScene() { int i; ground.draw(); for(i=0;i<numTrees;i++) trees[i].draw(); glShadeModel(GL_SMOOTH); lighting.enable(); for(i=0;i<numFlowers;i++) flowers[i].draw(); monument.draw(); ball1.draw(); ball2.draw(); lighting.disable(); }
void init(void) { // select clearing color (for glClear) glClearColor (1.0, 1.0, 1.0, 0.0); // RGB-value for white // initialize view (simple perspective projection) glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(6.0, (GLfloat) windowWidth/(GLfloat) windowHeight, 5.0, 55.0); gluLookAt(0,0,45, -0.8,0.2,0, 0,1,0); trackball.tbInit(GLUT_LEFT_BUTTON); lighting.init(); // Initialise balls ball1.setPosition(CVec3df(-2,0,-1)); ball1.setVelocity(CVec3df(25,0,0)); ball2.setPosition(CVec3df(2,0.20,-1)); ball2.setVelocity(CVec3df(-33,30,0)); ball1.setMass(2.25); ball2.setMass(1); // Distribute trees randomly over the front half of the ground plane such // that the minimum distance between any two trees is at least minDistanceTrees GLfloat x,z,xx,zz; // (x,z) positions of trees bool validPosition; int i; for(i=0;i<numTrees;i++) { do { validPosition=true; x=(GLfloat) randomDouble(-1.95,1.95); z=(GLfloat) randomDouble(0,1.95); for(int j=0;j<i;j++) { // position is valid if the distance between the trunks of each tree is at least minDistanceTrees trees[j].getPosition(xx,zz); if (sqrt((xx-x)*(xx-x)+(zz-z)*(zz-z))<minDistanceTrees) { validPosition=false; break;} } } while (validPosition==false); trees[i].setPosition(x,z); } // Distribute flowers randomly over the back half of the ground plane such // that the minimum distance between any two flowers is at least minDistanceFlowers // x,z,xx,zz; // (x,z) positions of trees for(i=0;i<numFlowers;i++) { do { validPosition=true; x=(GLfloat) randomDouble(-1.95,1.95); z=(GLfloat) randomDouble(-1.8,-1.1); for(int j=0;j<i;j++) { // position is valid if the distance between the stems of each tree is at least minDistanceFlowers flowers[j].getPosition(xx,zz); if (sqrt((xx-x)*(xx-x)+(zz-z)*(zz-z))<minDistanceFlowers) { validPosition=false; break;} } } while (validPosition==false); flowers[i].setPosition(x,z); } // initialise three texture names glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(3, texName); ground.setTexture(texName[0]); monument.setTexture(texName[1]); trees[0].setTexture(texName[2]); }