OpenGL正背面剔除和深度测试
我们画一个甜甜圈来解决正背面剔除和深度测试
OpenGL 基本图形的绘制,大致步骤都一样,本次重复代码就不在复述了,如果有疑问请看demo
SetupRC关键代码
//3.将相机向后移动7个单元:肉眼到物体之间的距离
viewFrame.MoveForward(7.0);
//4.创建一个甜甜圈
//void gltMakeTorus(GLTriangleBatch& torusBatch, GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor);
//参数1:GLTriangleBatch 容器帮助类
//参数2:外边缘半径
//参数3:内边缘半径
//参数4、5:主半径和从半径的细分单元数量
gltMakeTorus(torusBatch, 1.0f, 0.3f, 52, 26);
之前我们的顶点数据都是自己创建的,在甜甜圈中有提供gltMakeTorus,为我们自动构造数据模型。
SpecialKeys函数关键代码
//1.判断方向
if(key == GLUT_KEY_UP)
//2.根据方向调整观察者位置
viewFrame.RotateWorld(m3dDegToRad(-5.0), 1.0f, 0.0f, 0.0f);
if(key == GLUT_KEY_DOWN)
viewFrame.RotateWorld(m3dDegToRad(5.0), 1.0f, 0.0f, 0.0f);
if(key == GLUT_KEY_LEFT)
viewFrame.RotateWorld(m3dDegToRad(-5.0), 0.0f, 1.0f, 0.0f);
if(key == GLUT_KEY_RIGHT)
viewFrame.RotateWorld(m3dDegToRad(5.0), 0.0f, 1.0f, 0.0f);
这次画甜甜圈,我们调整观察者的位置,实现甜甜圈的旋转。
RenderScene关键代码
//使用默认光源着色器
//通过光源、阴影效果跟提现立体效果
//参数1:GLT_SHADER_DEFAULT_LIGHT 默认光源着色器
//参数2:模型视图矩阵
//参数3:投影矩阵
//参数4:基本颜色值
shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vRed);
显示效果

出现这个问题的原因是隐藏面消除
隐藏面消除
在绘制3D场景的时候,我们需要决定哪些部分是对观察者可见的,或者哪些部分是对观察者不可见的。对于不可见的部分,应该及早丢弃。例如:在一个不透明的墙壁后,就不不应该渲染。这种情况叫做“隐藏面消除“(Hidden surface elimination)。
解决方案:油画算法
油画算法
1.先绘制场景中的离观察者较远的物体,再绘制较近的物体。
2.例如下面的我们先画红色,再画黄色部分,最后画灰色部分,这样就可以解决隐藏面消除。

但是交叉的图层就无法处理

使用油画算法只是将场景按照物理距离观察者的距离远近排序,由远及近的绘制即可,对于上图的叠加情况,无法处理
正面或者背面剔除
所有平面都有两个面,正面和背面,我们在一个时刻只能看到其中一个面。而看不到的面,我们是不是可以不绘制观察者看到的面。来提高我们的渲染性能那。OpenGL 可以做到检查所有正面朝向观察者的面,并渲染它们.从而丢弃背面朝向的⾯. 这样可以 节约片元着⾊器的性能
正面/背面区分
正面:按照逆时针顶点连接顺序的三角形面
背面:按照顺时针顶点连接顺序的三角形面

立体图形的正背面

左侧三⻆角形顶点顺序为: 1—> 2—> 3 ; 右侧三⻆角形的顶点顺序为: 1—> 2—> 3 .
当观察者在右侧时,则右边的三⻆角形⽅方向为逆时针⽅方向则为正面,而左侧的三角形为顺时针则为背面。
当观察者在左侧时,则左边的三角形为逆时针方向判定为正面,而右侧的三角形为顺时针判定为背面
正面和背面不是绝对的,它是有观察者和三角形的顶点定义顺序共同决定的,当观察者的角度方向改变,正面和背面也会跟着改变。
开启正背面消除
glEnable(GL_CULL_FACE); //没有设置背面和正面,会默认背面
关闭正面背面消除
glDisable(GL_CULL_FACE);
设置消除面是哪面
glCullFace(GLenum mode);
GL_FRONT 指消除正面,GL_BACK指消除背面,GL_FRONT_AND_BACK指正面和背面都消除。
项目中设置glEnable(GL_CULL_FACE);

开启正背面消除后还是有问题,这是因为没有开启深度测试导致的
深度测试
1.深度是指在像素点在3D世界里距离观察者(相机的)距离,如果观察者在Z轴正方向,值越大越靠近观察者,同理,观察者在Z轴负方向值越小,越靠近观察者。
2.深度缓存区:就是一块内存区域,专门存储每个像素点的深度值,值越大,距离越远。
3.为什么需要深度缓存
在不使用深度测试的时候,如果我们先绘制一个距离比较近的物体,再绘制距离较远的物体,则距离 远的位图因为后绘制,会把距离近的物体覆盖掉. 有了深度缓冲区后,绘制物体的顺序就不那么重 要的. 实际上,只要存在深度缓冲区,OpenGL 都会把像素的深度值写入到缓冲区中. 除非调用 glDepthMask(GL_FALSE)来禁⽌写入.
开启深度测试
glEnable(GL_DEPTH_TEST);
