#include <cassert> #include <iostream> #include <GL/glew.h> #include <GL/glut.h> using namespace std; static GLfloat mirror_x = 0; static GLfloat mirror_y = 0; static GLfloat mirror_z = 2; void init() { glClearColor(0,0,0,0); glClearDepth(1.0f); glClearStencil(0); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); const GLfloat light0_pos[] = { 5.0f, 5.0f, 0.0f, 1.0f }; const GLfloat light0_ambient[] = { 1.0f, 1.0f, 1.0f,1.0f }; glLightfv(GL_LIGHT0, GL_POSITION, light0_pos); glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient); glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); } void drawSphere() { GLUquadric* quadric = gluNewQuadric(); assert(quadric); glColor3f(0, 0, 0.5); gluSphere(quadric, 0.5f, 256, 10); gluDeleteQuadric(quadric); } void render() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); //设置当前的矩阵为投影矩阵 glMatrixMode(GL_MODELVIEW); glStencilFunc(GL_ALWAYS, 0x0, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glPushMatrix(); // 移动到位置(0,0,3) glTranslatef(mirror_x, mirror_y, mirror_z); drawSphere(); glPopMatrix(); //绘制镜面,绘制完成之后,将镜面的模板值全部设置为1 //由于镜面的Z值小于原始球体的Z值故直接调用zfail的操作 glStencilFunc(GL_ALWAYS, 0x1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); //绘制镜面,在z=0的位置绘制镜面 //在这里我给写错成glDisable(GL_DEPTH_TEST)写成这样就不能进行深度测试 //直接就覆盖了上一个图形,应该是锁住,修改其模板值 glDepthMask(GL_FALSE); //将深度缓冲区锁住 glColor3f(0.1, 0.1, 0.1); glRectf(-3, 3, 3, -3); glDepthMask(GL_TRUE); //将深度缓冲区解锁 //绘制镜像球体,为了保证镜像始终在镜面内部,只对模板 //值等于1的情况进行绘制 glStencilFunc(GL_EQUAL, 0x1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glPushMatrix(); glTranslatef(-mirror_x, -mirror_y, -mirror_z); drawSphere(); glPopMatrix(); glutSwapBuffers(); } void reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60, w*1.0f/h, 0.1, 100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(1, 0, 5, 0, 0, 0, 0, 1, 0); } void keyborad(unsigned char key, int x, int y) { std::cout<<"key="<<key<<std::endl; std::cout<<"x="<<x<<std::endl; std::cout<<"y="<<y<<std::endl; switch (key) { case '1': { ++mirror_x; break; } case '2': { --mirror_x; break; } case '4': { ++mirror_y; break; } case '5': { --mirror_y; break; } case '7': { ++mirror_z; break; } case '8': { --mirror_z; break; } default: break; } glutPostRedisplay(); } int main(int argc, char **argv[]) { glutInitDisplayMode(GLUT_RGBA | GLUT_STENCIL | GLUT_DEPTH | GLUT_DOUBLE); glutCreateWindow("Mirror Model"); glutInitWindowPosition(300, 300); glutInitWindowSize(600, 600); assert(glewInit() == GLEW_NO_ERROR); init(); glutDisplayFunc(render); glutReshapeFunc(reshape); glutKeyboardFunc(keyborad); glutMainLoop(); return 0; }