OpenGL 回顾——简化版的窗体(包含鼠标控制,普通键位控制,以及镜面反射)
// OpenGLBook.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" //变量声明 static GLfloat spin =0.0; GLfloat zoom=-10.0f; GLfloat angel=20.0f; BOOL light; // 光源的开/关 BOOL lp; // L键按下了么? BOOL fp; // F键按下了么? GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0}; GLfloat mat_shininess[] = {50.0}; GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0}; GLfloat white_light[] = {1.0, 1.0, 1.0, 1.0}; GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 1.0}; //函数声明 void init(void); void display(void); void spinDisplay(void); void reshape(int w,int h); void mouse(int button,int state,int x,int y); void processNormalKeys(unsigned char key,int x,int y); void processKeyUpDowm(int key,int x,int y); /************************************************************************/ /* 函数实现 */ /************************************************************************/ //初始化 void init(void){ glClearColor(0.0f,0.0f,0.0f,0.0f); glShadeModel(GL_SMOOTH); glShadeModel(GL_SMOOTH); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light); glLightfv(GL_LIGHT0, GL_SPECULAR, white_light); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); //glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); /////////////////////// glShadeModel(GL_SMOOTH); // Enable Smooth Shading glClearColor(0.1f,0.1f, 0.1f, 0.9f); // Black Background glClearDepth(1.0f); // Depth Buffer Setup glEnable(GL_DEPTH_TEST); // Enables Depth Testing glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations } //图形绘画 void display(void){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕及深度缓存 // 重置模型观察矩阵 glPushMatrix(); //glLoadIdentity(); //等同于glPushMatrix();和glPopMatrix();配对重绘 glTranslatef(0.0f,0.0f,zoom); glRotatef(spin,0.0f,1.0f,0.0f); glutSolidSphere(1.0, 20, 16); glPopMatrix(); glutSwapBuffers(); //交换屏幕缓冲区与后台缓冲区 angel+=5.0f; glutPostRedisplay(); //重绘 // glPushMatrix(); } void reshape(int w,int h){ if (h==0) // Prevent A Divide By Zero By { h=1; // Making Height Equal One } glViewport(0,0,(GLsizei)w,(GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,(GLfloat)w/(GLfloat)h,0.1f,100.0f);//透视 //glOrtho(-50.0,50.0,-50.0,50.0,-1.0,100.0); //平行修剪空间(离观察者远时,不会缩小) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } //鼠标响应 void mouse(int button,int state,int x,int y) { switch(state){ case GLUT_DOWN: if (button==GLUT_LEFT_BUTTON) //左键 { break; } if (button==GLUT_RIGHT_BUTTON) //右键 { break; } case GLUT_UP: if (button==GLUT_WHEEL_UP) { zoom-=1.0f; glutPostRedisplay(); break; } else if (button==GLUT_WHEEL_DOWN) { zoom+=1.0f; glutPostRedisplay(); break; } default: break; } } //按键响应 void processNormalKeys(unsigned char key,int x,int y) { switch(key){ case 27: exit(0); break; case 'l': if (!lp) { lp=TRUE; // lp 设为 TRUE light=!light; // 切换光源的 TRUE/FALSE } else{ lp=FALSE; light=!light; } if (!light) // 如果没有光源 { glDisable(GL_LIGHTING); // 禁用光源 } else // 否则 { glEnable(GL_LIGHTING); // 启用光源 } break; case 'r': spin+=2.0f; if (spin>360.0f) { spin-=360.0f; } glutPostRedisplay(); break; } } void processKeyUpDowm(int key,int x,int y){ switch(key){ case GLUT_KEY_UP: lp=TRUE; break; case GLUT_KEY_DOWN: lp=false; break; default: break; } } //主函数 int _tmain(int argc, char**argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowSize(640,480); glutInitWindowPosition(350,150); glutCreateWindow("this is my window"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMouseFunc(mouse); glutKeyboardFunc(processNormalKeys); glutMainLoop(); return 0; }
ps:
镜面反射步骤:光源要设置镜面反射的属性、之后相应的物体要设置镜面反射的材质。还有自发光的属性emission,看起来就行物体在自己发光一样。
尽量用glPushMatrix()和 glPopMatrix()进行绘图,而glLoadIdentity()在初始化和重绘的时候用。
暂时还没发现回调函数中有捕获普通按键按下的函数,不过影响不是很大。长按相当于连续按多次。