openGL+VS2010的例程--空间摄影机+灯光渲染成型(三维)
2015-01-16 10:02
423 查看
![](http://images.cnitblog.com/blog/444792/201501/160958126362030.jpg)
效果图如上:
步骤:略
实现代码如下:
1、main.cpp
/********************************************************************** Lighting and depth testing June, 11th, 2000 This tutorial was written by Philipp Crocoll Contact: philipp.crocoll@web.de www.codecolony.de Every comment would be appreciated. If you want to use parts of any code of mine: let me know and use it! *********************************************************************** ESC : Exit CAMERA movement: w : forwards s : backwards a : turn left d : turn right x : turn up y : turn down v : strafe right c : strafe left r : move up f : move down **********************************************************************/ #include <GL\glut.h> //includes gl.h and glu.h #include <windows.h> #include "camera.h" CCamera Camera; bool LightEnabled = true; float TorusRotated = 0.0; static GLfloat MatSpec[] = {1.0,1.0,1.0,1.0}; static GLfloat MatShininess[] = {50.0}; // 设置材料反射指数 //其中,LightPosition也是一个四维数组,四维数组的前3项依次为光源位置的X,Y,Z分量,第四个值很特殊,一般为1或-1。当 //LightPosition[4]=-1的时候,表示光源位于距离场景无限远的地方,无论前面设置的X,Y,Z是什么值。当LightPosition[4]=1 //时,光源的位置就是前三项所指定的位置。 static GLfloat LightPos[] = {-2.0,2.0,3.0,0.0}; void Display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Don't forget the depth buffer! glLoadIdentity(); //Load a new modelview matrix -> we can apply new transformations Camera.Render(); // 移动新视点的矩阵 glLightfv(GL_LIGHT0, GL_POSITION, LightPos); // 设置光源在场景中的位置 glutSolidSphere(1.0,40,40); // 设置球体1 glTranslatef(2.0,0.0,0.0); glutSolidSphere(0.8,40,40); // 设置球体2 glPushMatrix(); // 压栈1 glTranslatef(0.0,2.0,0.0); glutSolidSphere(1.2,40,40); // 设置球体3 glPopMatrix(); // 出栈1 glTranslatef(0.0,0.0,2.0); glutSolidSphere(0.5,40,40); // 设置球体4 glTranslatef(-4.0,0.0,0.0); glRotatef(TorusRotated, 0.0,1.0,0.0); glutSolidTorus(0.3,1.0,16,32); // glutWireTorus 绘制线框圆环 glutSolidTorus 绘制实心圆环 glFlush(); //Finish rendering glutSwapBuffers(); //Swap the buffers ->make the result of rendering visible } void Reshape(int x, int y) { if (y == 0 || x == 0) return; //Nothing is visible then, so return //Set a new projection matrix glMatrixMode(GL_PROJECTION); glLoadIdentity(); //Angle of view:40 degrees //Near clipping plane distance: 0.5 //Far clipping plane distance: 20.0 gluPerspective(40.0,(GLdouble)x/(GLdouble)y,0.5,20.0); glMatrixMode(GL_MODELVIEW); glViewport(0,0,x,y); //Use the whole window for rendering //Adjust point size to window size glPointSize(GLfloat(x)/200.0); } void KeyDown(unsigned char key, int x, int y) //Note: because there is an Idle-func, we don't have to call Display here { switch(key) { case 27: //ESC exit(0); break; case 97: //a Camera.RotateY(5.0); break; case 100: //d Camera.RotateY(-5.0); break; case 119: //w Camera.MoveForwards( -0.1 ) ; break; case 115: //s Camera.MoveForwards( 0.1 ) ; break; case 120: //x Camera.RotateX(5.0); break; case 121: //y Camera.RotateX(-5.0); break; case 99: //c Camera.StrafeRight(-0.1); break; case 118: //v Camera.StrafeRight(0.1); break; case 'l': LightEnabled = !LightEnabled; if (LightEnabled) glEnable(GL_LIGHTING); else glDisable(GL_LIGHTING); break; } } static long long times = 0; void Idle(void) { times++; // 延迟 if(times>500000) times =0; if(times% 500000== 0) { TorusRotated += 2.0; Display(); } } int main(int argc, char **argv) { //Initialize GLUT glutInit(&argc, argv); //Lets use doublebuffering, RGB(A)-mode and a depth buffer glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // 新增“深度缓冲” glutInitWindowSize(600,600); //Create a window with rendering context and everything else we need glutCreateWindow("Lighting and depth testing"); //Assign the event-handling routines glutDisplayFunc(Display); glutReshapeFunc(Reshape); glutKeyboardFunc(KeyDown); glutIdleFunc(Idle); // 新增“空闲任务” Camera.Move(F3dVector(0.0,0.0,15.0)); // 摄影机的位置 //Lighting stuff: glShadeModel(GL_SMOOTH); //GL_FLAT would look much worse GL_SMOOTH // 平滑过渡颜色 glEnable(GL_DEPTH_TEST); // 开启深度测试,比较在z轴上的点是否最靠前。 // GL_DIFFUSE 漫射光 GL_SPECULAR 镜面光 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MatSpec); // 镜面光的颜色 -- 缺省值 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, MatShininess); // 称为 镜面指数 ,取值范围是0到128。 glEnable(GL_LIGHTING); // 打开光照效果 glEnable(GL_LIGHT0); // 使用默认的0号灯 //Let GLUT get the msgs and tell us the ones we need glutMainLoop(); return 0; }
2、camera.cpp
#include "camera.h" #include "math.h" #include <iostream> #include "windows.h" SF3dVector F3dVector ( GLfloat x, GLfloat y, GLfloat z ) { SF3dVector tmp; tmp.x = x; tmp.y = y; tmp.z = z; return tmp; } SF3dVector AddF3dVectors (SF3dVector* u, SF3dVector* v) { SF3dVector result; result.x = u->x + v->x; result.y = u->y + v->y; result.z = u->z + v->z; return result; } void AddF3dVectorToVector ( SF3dVector * Dst, SF3dVector * V2) { Dst->x += V2->x; Dst->y += V2->y; Dst->z += V2->z; } /***************************************************************************************/ CCamera::CCamera() { //Init with standard OGL values: Position = F3dVector ( 0.0, 0.0, 0.0); ViewDir = F3dVector( 0.0, 0.0, -1.0); ViewDirChanged = false; //Only to be sure: RotatedX = RotatedY = RotatedZ = 0.0; } void CCamera::GetViewDir( void ) { SF3dVector Step1, Step2; //Rotate around Y-axis: Step1.x = cos( (RotatedY + 90.0) * PIdiv180); Step1.z = -sin( (RotatedY + 90.0) * PIdiv180); //Rotate around X-axis: double cosX = cos (RotatedX * PIdiv180); Step2.x = Step1.x * cosX; Step2.z = Step1.z * cosX; Step2.y = sin(RotatedX * PIdiv180); //Rotation around Z-axis not yet implemented, so: ViewDir = Step2; } void CCamera::Move (SF3dVector Direction) { AddF3dVectorToVector(&Position, &Direction ); } void CCamera::RotateY (GLfloat Angle) { RotatedY += Angle; ViewDirChanged = true; } void CCamera::RotateX (GLfloat Angle) { RotatedX += Angle; ViewDirChanged = true; } void CCamera::Render( void ) { glRotatef(-RotatedX , 1.0, 0.0, 0.0); glRotatef(-RotatedY , 0.0, 1.0, 0.0); glRotatef(-RotatedZ , 0.0, 0.0, 1.0); glTranslatef( -Position.x, -Position.y, -Position.z ); } void CCamera::MoveForwards( GLfloat Distance ) { if (ViewDirChanged) GetViewDir(); SF3dVector MoveVector; MoveVector.x = ViewDir.x * -Distance; MoveVector.y = ViewDir.y * -Distance; MoveVector.z = ViewDir.z * -Distance; AddF3dVectorToVector(&Position, &MoveVector ); } void CCamera::StrafeRight ( GLfloat Distance ) { if (ViewDirChanged) GetViewDir(); SF3dVector MoveVector; MoveVector.z = -ViewDir.x * -Distance; MoveVector.y = 0.0; MoveVector.x = ViewDir.z * -Distance; AddF3dVectorToVector(&Position, &MoveVector ); }
3、camera.h
#include <gl\glut.h> // Need to include it here because the GL* types are required #define PI 3.1415265359 #define PIdiv180 3.1415265359/180.0 ///////////////////////////////// //Note: All angles in degrees // ///////////////////////////////// struct SF3dVector //Float 3d-vect, normally used { GLfloat x,y,z; }; struct SF2dVector { GLfloat x,y; }; class CCamera { private: SF3dVector Position; SF3dVector ViewDir; /*Not used for rendering the camera, but for "moveforwards" So it is not necessary to "actualize" it always. It is only actualized when ViewDirChanged is true and moveforwards is called*/ bool ViewDirChanged; GLfloat RotatedX, RotatedY, RotatedZ; void GetViewDir ( void ); public: CCamera(); //inits the values (Position: (0|0|0) Target: (0|0|-1) ) void Render ( void ); //executes some glRotates and a glTranslate command //Note: You should call glLoadIdentity before using Render void Move ( SF3dVector Direction ); void RotateX ( GLfloat Angle ); void RotateY ( GLfloat Angle ); void RotateZ ( GLfloat Angle ); void RotateXYZ ( SF3dVector Angles ); void MoveForwards ( GLfloat Distance ); void StrafeRight ( GLfloat Distance ); }; SF3dVector F3dVector ( GLfloat x, GLfloat y, GLfloat z ); SF3dVector AddF3dVectors ( SF3dVector * u, SF3dVector * v); void AddF3dVectorToVector ( SF3dVector * Dst, SF3dVector * V2);
代码来源地址:http://www.codecolony.de/
相关文章推荐
- openGL+VS2010的例程--空间摄影机(三维)
- openGL+VS2010的例程--空间摄影机注释版(三维)
- openGL+VS2010的例程--城堡模型注释版(三维)
- openGL+VS2010的例程--太阳地球月球运动模型(三维)
- openGL+VS2010的例程--旋转贴图灯笼(三维)
- openGL+VS2010的例程--太阳地球月球运动模型增强版(三维)
- openGL+VS2010的例程--旋转变色立方体(三维)
- openGL+VS2010的例程--旋转彩球(三维)
- VS2010-MFC:用OpenGL在对话框中的PictureControl(图片控件)中绘制三维模型,可旋转、平移、缩放,可用于三维模型的预览
- OpenGL入门学习之五——三维的空间变换
- VC+OpenGL实现空间三维Delaunay三角剖分
- openGL三维网格坐标,旋转,缩放,灯光设置,纹理读取,模型读取(MFC单文档)
- VC+OpenGL实现空间三维Delaunay三角剖分
- OpenGL 三维的空间变换
- Captain Dialog 2009-09-18 VC+OpenGL实现空间三维Delaunay三角剖分
- openGL三维网格坐标,旋转,缩放,灯光设置,纹理读取,模型读取(MFC单文档)
- OpenGL学习--08--基本渲染(灯光)
- VC+OpenGL实现空间三维Delaunay三角剖分
- openGL+VS2010的例程--静态平滑变色三角形(二维)
- OpenGL入门学习——第五课 三维的空间变换