效果图如上:
步骤:略
实现代码如下:
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/