效果图如上:
步骤:略
实现代码如下:
1、main.cpp
1 /********************************************************************** 2 3 Lighting and depth testing 4 5 June, 11th, 2000 6 7 This tutorial was written by Philipp Crocoll 8 Contact: 9 philipp.crocoll@web.de 10 www.codecolony.de 11 12 Every comment would be appreciated. 13 14 If you want to use parts of any code of mine: 15 let me know and 16 use it! 17 18 *********************************************************************** 19 20 ESC : Exit 21 22 CAMERA movement: 23 w : forwards 24 s : backwards 25 a : turn left 26 d : turn right 27 x : turn up 28 y : turn down 29 v : strafe right 30 c : strafe left 31 r : move up 32 f : move down 33 34 35 **********************************************************************/ 36 37 #include <GL\glut.h> //includes gl.h and glu.h 38 #include <windows.h> 39 #include "camera.h" 40 41 CCamera Camera; 42 bool LightEnabled = true; 43 float TorusRotated = 0.0; 44 45 static GLfloat MatSpec[] = {1.0,1.0,1.0,1.0}; 46 static GLfloat MatShininess[] = {50.0}; // 设置材料反射指数 47 //其中,LightPosition也是一个四维数组,四维数组的前3项依次为光源位置的X,Y,Z分量,第四个值很特殊,一般为1或-1。当 48 //LightPosition[4]=-1的时候,表示光源位于距离场景无限远的地方,无论前面设置的X,Y,Z是什么值。当LightPosition[4]=1 49 //时,光源的位置就是前三项所指定的位置。 50 static GLfloat LightPos[] = {-2.0,2.0,3.0,0.0}; 51 52 void Display(void) 53 { 54 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Don't forget the depth buffer! 55 glLoadIdentity(); //Load a new modelview matrix -> we can apply new transformations 56 Camera.Render(); // 移动新视点的矩阵 57 glLightfv(GL_LIGHT0, GL_POSITION, LightPos); // 设置光源在场景中的位置 58 glutSolidSphere(1.0,40,40); // 设置球体1 59 60 glTranslatef(2.0,0.0,0.0); 61 glutSolidSphere(0.8,40,40); // 设置球体2 62 63 glPushMatrix(); // 压栈1 64 glTranslatef(0.0,2.0,0.0); 65 glutSolidSphere(1.2,40,40); // 设置球体3 66 glPopMatrix(); // 出栈1 67 68 glTranslatef(0.0,0.0,2.0); 69 glutSolidSphere(0.5,40,40); // 设置球体4 70 71 glTranslatef(-4.0,0.0,0.0); 72 glRotatef(TorusRotated, 0.0,1.0,0.0); 73 glutSolidTorus(0.3,1.0,16,32); // glutWireTorus 绘制线框圆环 glutSolidTorus 绘制实心圆环 74 75 glFlush(); //Finish rendering 76 glutSwapBuffers(); //Swap the buffers ->make the result of rendering visible 77 } 78 79 void Reshape(int x, int y) 80 { 81 if (y == 0 || x == 0) return; //Nothing is visible then, so return 82 //Set a new projection matrix 83 glMatrixMode(GL_PROJECTION); 84 glLoadIdentity(); 85 //Angle of view:40 degrees 86 //Near clipping plane distance: 0.5 87 //Far clipping plane distance: 20.0 88 gluPerspective(40.0,(GLdouble)x/(GLdouble)y,0.5,20.0); 89 glMatrixMode(GL_MODELVIEW); 90 glViewport(0,0,x,y); //Use the whole window for rendering 91 //Adjust point size to window size 92 glPointSize(GLfloat(x)/200.0); 93 } 94 void KeyDown(unsigned char key, int x, int y) 95 //Note: because there is an Idle-func, we don't have to call Display here 96 { 97 switch(key) 98 { 99 case 27: //ESC 100 exit(0); 101 break; 102 case 97: //a 103 Camera.RotateY(5.0); 104 break; 105 case 100: //d 106 Camera.RotateY(-5.0); 107 break; 108 case 119: //w 109 Camera.MoveForwards( -0.1 ) ; 110 break; 111 case 115: //s 112 Camera.MoveForwards( 0.1 ) ; 113 break; 114 case 120: //x 115 Camera.RotateX(5.0); 116 break; 117 case 121: //y 118 Camera.RotateX(-5.0); 119 break; 120 case 99: //c 121 Camera.StrafeRight(-0.1); 122 break; 123 case 118: //v 124 Camera.StrafeRight(0.1); 125 break; 126 case 'l': 127 LightEnabled = !LightEnabled; 128 if (LightEnabled) glEnable(GL_LIGHTING); 129 else glDisable(GL_LIGHTING); 130 break; 131 } 132 } 133 static long long times = 0; 134 void Idle(void) 135 { 136 times++; // 延迟 137 if(times>500000) 138 times =0; 139 if(times% 500000== 0) 140 { 141 TorusRotated += 2.0; 142 Display(); 143 } 144 } 145 146 int main(int argc, char **argv) 147 { 148 //Initialize GLUT 149 glutInit(&argc, argv); 150 //Lets use doublebuffering, RGB(A)-mode and a depth buffer 151 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // 新增“深度缓冲” 152 glutInitWindowSize(600,600); 153 //Create a window with rendering context and everything else we need 154 glutCreateWindow("Lighting and depth testing"); 155 //Assign the event-handling routines 156 glutDisplayFunc(Display); 157 glutReshapeFunc(Reshape); 158 glutKeyboardFunc(KeyDown); 159 glutIdleFunc(Idle); // 新增“空闲任务” 160 Camera.Move(F3dVector(0.0,0.0,15.0)); // 摄影机的位置 161 //Lighting stuff: 162 glShadeModel(GL_SMOOTH); //GL_FLAT would look much worse GL_SMOOTH // 平滑过渡颜色 163 glEnable(GL_DEPTH_TEST); // 开启深度测试,比较在z轴上的点是否最靠前。 164 // GL_DIFFUSE 漫射光 GL_SPECULAR 镜面光 165 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MatSpec); // 镜面光的颜色 -- 缺省值 166 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, MatShininess); // 称为 镜面指数 ,取值范围是0到128。 167 168 glEnable(GL_LIGHTING); // 打开光照效果 169 glEnable(GL_LIGHT0); // 使用默认的0号灯 170 171 //Let GLUT get the msgs and tell us the ones we need 172 glutMainLoop(); 173 return 0; 174 }
2、camera.cpp
1 #include "camera.h" 2 #include "math.h" 3 #include <iostream> 4 #include "windows.h" 5 SF3dVector F3dVector ( GLfloat x, GLfloat y, GLfloat z ) 6 { 7 SF3dVector tmp; 8 tmp.x = x; 9 tmp.y = y; 10 tmp.z = z; 11 return tmp; 12 } 13 SF3dVector AddF3dVectors (SF3dVector* u, SF3dVector* v) 14 { 15 SF3dVector result; 16 result.x = u->x + v->x; 17 result.y = u->y + v->y; 18 result.z = u->z + v->z; 19 return result; 20 } 21 void AddF3dVectorToVector ( SF3dVector * Dst, SF3dVector * V2) 22 { 23 Dst->x += V2->x; 24 Dst->y += V2->y; 25 Dst->z += V2->z; 26 } 27 28 29 /***************************************************************************************/ 30 31 CCamera::CCamera() 32 { 33 //Init with standard OGL values: 34 Position = F3dVector ( 0.0, 35 0.0, 36 0.0); 37 ViewDir = F3dVector( 0.0, 38 0.0, 39 -1.0); 40 ViewDirChanged = false; 41 //Only to be sure: 42 RotatedX = RotatedY = RotatedZ = 0.0; 43 } 44 45 void CCamera::GetViewDir( void ) 46 { 47 SF3dVector Step1, Step2; 48 //Rotate around Y-axis: 49 Step1.x = cos( (RotatedY + 90.0) * PIdiv180); 50 Step1.z = -sin( (RotatedY + 90.0) * PIdiv180); 51 //Rotate around X-axis: 52 double cosX = cos (RotatedX * PIdiv180); 53 Step2.x = Step1.x * cosX; 54 Step2.z = Step1.z * cosX; 55 Step2.y = sin(RotatedX * PIdiv180); 56 //Rotation around Z-axis not yet implemented, so: 57 ViewDir = Step2; 58 } 59 void CCamera::Move (SF3dVector Direction) 60 { 61 AddF3dVectorToVector(&Position, &Direction ); 62 } 63 64 void CCamera::RotateY (GLfloat Angle) 65 { 66 RotatedY += Angle; 67 ViewDirChanged = true; 68 } 69 70 void CCamera::RotateX (GLfloat Angle) 71 { 72 RotatedX += Angle; 73 ViewDirChanged = true; 74 } 75 76 void CCamera::Render( void ) 77 { 78 glRotatef(-RotatedX , 1.0, 0.0, 0.0); 79 glRotatef(-RotatedY , 0.0, 1.0, 0.0); 80 glRotatef(-RotatedZ , 0.0, 0.0, 1.0); 81 glTranslatef( -Position.x, -Position.y, -Position.z ); 82 } 83 84 void CCamera::MoveForwards( GLfloat Distance ) 85 { 86 if (ViewDirChanged) GetViewDir(); 87 SF3dVector MoveVector; 88 MoveVector.x = ViewDir.x * -Distance; 89 MoveVector.y = ViewDir.y * -Distance; 90 MoveVector.z = ViewDir.z * -Distance; 91 AddF3dVectorToVector(&Position, &MoveVector ); 92 } 93 94 void CCamera::StrafeRight ( GLfloat Distance ) 95 { 96 if (ViewDirChanged) GetViewDir(); 97 SF3dVector MoveVector; 98 MoveVector.z = -ViewDir.x * -Distance; 99 MoveVector.y = 0.0; 100 MoveVector.x = ViewDir.z * -Distance; 101 AddF3dVectorToVector(&Position, &MoveVector ); 102 }
3、camera.h
1 #include <gl\glut.h> // Need to include it here because the GL* types are required 2 #define PI 3.1415265359 3 #define PIdiv180 3.1415265359/180.0 4 5 / 6 //Note: All angles in degrees // 7 / 8 9 struct SF3dVector //Float 3d-vect, normally used 10 { 11 GLfloat x,y,z; 12 }; 13 struct SF2dVector 14 { 15 GLfloat x,y; 16 }; 17 18 class CCamera 19 { 20 private: 21 SF3dVector Position; 22 SF3dVector ViewDir; /*Not used for rendering the camera, but for "moveforwards" 23 So it is not necessary to "actualize" it always. It is only 24 actualized when ViewDirChanged is true and moveforwards is called*/ 25 bool ViewDirChanged; 26 GLfloat RotatedX, RotatedY, RotatedZ; 27 void GetViewDir ( void ); 28 public: 29 CCamera(); //inits the values (Position: (0|0|0) Target: (0|0|-1) ) 30 void Render ( void ); //executes some glRotates and a glTranslate command 31 //Note: You should call glLoadIdentity before using Render 32 void Move ( SF3dVector Direction ); 33 void RotateX ( GLfloat Angle ); 34 void RotateY ( GLfloat Angle ); 35 void RotateZ ( GLfloat Angle ); 36 void RotateXYZ ( SF3dVector Angles ); 37 void MoveForwards ( GLfloat Distance ); 38 void StrafeRight ( GLfloat Distance ); 39 }; 40 41 42 SF3dVector F3dVector ( GLfloat x, GLfloat y, GLfloat z ); 43 SF3dVector AddF3dVectors ( SF3dVector * u, SF3dVector * v); 44 void AddF3dVectorToVector ( SF3dVector * Dst, SF3dVector * V2);
代码来源地址:http://www.codecolony.de/