- 复习下基本流程
- 具体代码:
- 绘制甜甜圈的准备工作
- 初始化工作
- 窗口改变时
- 屏幕刷新时
- ">
![[demo5].不画甜甜圈的吃货不是好的程序猿 - 图1](/uploads/projects/nanziyaonulibenpao@uyzg7e/dab2d71fe17f3e0eafeef2e97bc1b708.png)
- Run一下,发现甜甜圈出现了,开心~
- 再Run一下,棒~想要的效果出来了!👏👏👏👏👏
- 再run一次,发现不再出现黑色了,👏👏👏👏👏
- 但是又来了,这次,黑色没有了,可旋转到某一个方向的时候,出现了透视的现象,这是为什么呢?
- ">
![[demo5].不画甜甜圈的吃货不是好的程序猿 - 图2](/uploads/projects/nanziyaonulibenpao@uyzg7e/aa0b557956a3cd4bdabeffdd3d7ef0e5.png)
- 在这次的甜甜圈的世界里,因为采用的是油画的画法,即先画底下涂层的,再画上面涂层,因此,图形的正面与背面是已经设定好了的,所以在旋转的时候,由于正面位于背面的涂层下面,但是正面是不会被背面所遮挡的,所以便出现了透视的效果
- OpenGL的深度测试把,深度测试可以帮我们定位很多问题!">该怎么做呢?先看一下下一篇OpenGL的深度测试把,深度测试可以帮我们定位很多问题!
复习下基本流程
初始化glut模块加载配置模块设置窗口大小给窗口取个名字注册一个方法监测窗口改变注册一个方法监测键盘输入注册一个方法监测屏幕刷新初始化glew模块并检测是否初始化成功设置默认值(环境)加载并启动MainLoop
实际上并不需要完全按照上面的步骤来做,像注册监测的那三个方法可以自由变换顺序。
具体代码:
//着色器管理类GLShaderManager shaderManager;//甜甜圈容器GLTriangleBatch donutBatch;//窗口改变void ChangeSize(int w, int h) { }//监测键盘输入信号void SpecialKeys(int key, int x, int y) { }//屏幕刷新void RenderScene() { }//初始化相关工作void SetupRC() { }int main( int argc, char *argv[]) {gltSetWorkingDirectory(argv[0]);//初始化glut模块glutInit(&argc, argv);//加载配置模块glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);//设置窗口大小glutInitWindowSize(400, 400);//给窗口取个名字glutCreateWindow("There is a donut here");//注册一个方法监测窗口改变glutReshapeFunc(ChangeSize);//注册一个方法监测键盘输入glutSpecialFunc(SpecialKeys);注册一个方法监测屏幕刷新glutDisplayFunc(RenderScene);//初始化glew模块并检测是否初始化成功GLenum err = glewInit();if (GLEW_OK != err) {fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));return 1;}//设置默认值(环境)SetupRC();//加载并启动MainLoopglutMainLoop();return 0;}
绘制甜甜圈的准备工作
1.因为这次是要画一个可以展览的甜甜圈(不然就没有灵魂了),所以我们需要有一个观察者,也就是摄影师(观察者坐标系),且观察者自身也有一个属性(物体坐标系)
GLMatrixStack cameraMatix;GLFrame cameraFrame;
2.而甜甜圈自身也是有大小的,所以我们需要描绘甜甜圈的属性(物体坐标系)
GLMatrixStack donutMatrix;
3.在将甜甜圈转化为世界坐标系的时候,需要设置甜甜圈的投影规则(称之为管线)
GLGeometryTransform donutTransform;
4.这次需要绘制的是立体的甜甜圈,所以为了有立体感,需要设置投影方式为透视投影,为此,我们需要设置一个全局变量用于记录当前透视状态
GLFrustum viewFrustum;
初始化工作
在SetupRC中需要设置背景颜色,初始化全局变量
glClearColor(240/255.0, 248/255.0, 255/255.0, 1.0f);shaderManager.InitializeStockShaders();//将相机向后移动7个单元:肉眼到物体之间的距离cameraFrame.MoveForward(7.0);//创建一个甜甜圈//void gltMakeTorus(GLTriangleBatch& torusBatch, GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor);//参数1:GLTriangleBatch 容器帮助类//参数2:外边缘半径//参数3:内边缘半径//参数4、5:主半径和从半径的细分单元数量gltMakeTorus(donutBatch, 1.0f, 0.3f, 52, 26);
窗口改变时
//1.防止h变为0if(h == 0)h = 1;//2.设置视口窗口尺寸glViewport(0, 0, w, h);//3.setPerspective函数的参数是一个从顶点方向看去的视场角度(用角度值表示)// 设置透视模式,初始化其透视矩阵viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 100.0f);//4.把透视矩阵加载到透视矩阵对阵中donutMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());//5.初始化渲染管线donutTransform.SetMatrixStacks(cameraMatix, donutMatrix);
屏幕刷新时
//1.清除窗口和深度缓冲区glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//2.把摄像机矩阵压入模型矩阵中cameraMatix.PushMatrix(cameraFrame);//3.设置绘图颜色GLfloat colorDonut[] = { 255/255.0, 215/255.0, 0/255.0, 1.0f };//4.//使用平面着色器//参数1:平面着色器//参数2:模型视图投影矩阵//参数3:颜色// shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vRed);//使用默认光源着色器//通过光源、阴影效果跟提现立体效果//参数1:GLT_SHADER_DEFAULT_LIGHT 默认光源着色器//参数2:模型视图矩阵//参数3:投影矩阵//参数4:基本颜色值shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT, donutTransform.GetModelViewMatrix(), donutTransform.GetProjectionMatrix(), colorDonut);//5.绘制donutBatch.Draw();//6.出栈 绘制完成恢复cameraMatix.PopMatrix();//7.交换缓存区glutSwapBuffers();
Run一下,发现甜甜圈出现了,开心~
但是,这是一个不会动的甜甜圈!!!
为了让他动起来,我们必须进行操作
在SpecialKey中
//监测键盘输入信号void SpecialKeys(int key, int x, int y) {//w 设置为后空翻吧,就是围绕x轴向后旋转if(key == 119)cameraFrame.RotateWorld(m3dDegToRad(-5.0), 1.0f, 0.0f, 0.0f);//s 设置为前空翻吧,就是围绕x轴向前旋转if(key == 115)cameraFrame.RotateWorld(m3dDegToRad(5.0), 1.0f, 0.0f, 0.0f);//a 设置为直立顺时针转圈,就是围绕y轴顺时针旋转if(key == 97)cameraFrame.RotateWorld(m3dDegToRad(-5.0), 0.0f, 1.0f, 0.0f);//d 设置为直立顺时针转圈,就是围绕y轴逆时针旋转if(key == 100)cameraFrame.RotateWorld(m3dDegToRad(5.0), 0.0f, 1.0f, 0.0f);//q 设置为正向中心顺时针转圈,就是围绕z轴逆时针旋转if(key == 113)cameraFrame.RotateWorld(m3dDegToRad(-5.0), 0.0f, 0.0f, 1.0f);//e 设置为正向中心逆时针转圈,就是围绕z轴逆时针旋转if(key == 101)cameraFrame.RotateWorld(m3dDegToRad(5.0), 0.0f, 0.0f, 1.0f);//3.重新刷新glutPostRedisplay();}
再Run一下,棒~想要的效果出来了!👏👏👏👏👏
又又又又又但是!在旋转的时候,出现了很多黑色的东西,色香味色先挂了,哪里还有食欲?想要解决它,首先得了解它是什么。![[demo5].不画甜甜圈的吃货不是好的程序猿 - 图4](/uploads/projects/nanziyaonulibenpao@uyzg7e/932bbb7a8e3942cd5843ac255f6fd6c6.png)
在现实世界中,一个甜甜圈还没开始吃的时候,应该只能看到它脆脆的皮,而不可能看到它松松的肉,但是在我们绘制的甜甜圈中,我们看到了它松松的肉,这是不正常的。
在OpenGL的世界中,所描绘的每一个物体都是有它的正面和背面的,正面不会被遮挡,而背面会被遮挡住,用这样的方式来模拟现实世界中不透明的物体的成像。
因此现在的这种情况,我们只需要打开OpenGL自身的背面剔除功能就好了,所以在RenderScene绘制的时候我们需要设置背面剔除.
glEnable(GL_CULL_FACE);
