OpenGL正面&背面剔除与深度测试
1.隐藏面消失
在绘制图形的时候,图形的背面是观察者不可见的,那么这部分就不应该被渲染出来,这种情况叫“隐藏面消除”

使用平面着色器来绘制时,会出现隐藏面消除吗?
隐藏面消除不会因为着色器的不同而消失,只不过因为平面着色器正反面的颜色相同,所以无法察觉。
为什么使用默认光源着色器?
因为默认光源着色器有阴面和阳面可以看的出来隐藏面消失的问题。
可以用开启正背面剔除的方法来处理隐藏面消失
glEnable(GL_CULL_FACE)
下面是正背面剔除的其他使用方法
开启表⾯面剔除(默认背⾯面剔除)
void glEnable(GL_CULL_FACE);
关闭表⾯面剔除(默认背⾯面剔除)
void glDisable(GL_CULL_FACE);
⽤用户选择剔除那个⾯面(正⾯面/背⾯面) void glCullFace(GLenum mode);
mode参数为: GL_CW,GL_CCW,默认值:GL_CCW 例例如,剔除正⾯面实现(1)
glCullFace(GL_BACK); glFrontFace(GL_CW);
•
mode参数为: GL_FRONT,GL_BACK,GL_FRONT_AND_BACK ,默认GL_BACK ⽤用户指定绕序那个为正⾯面
•
void glFrontFace(GLenum mode);
例例如,剔除正⾯面实现(2) glCullFace(GL_FRONT);
2.深度测试
- 深度测试
深度缓冲区(DepthBuffer)和颜⾊色缓存区(ColorBuffer)是对应的.颜色缓存区存储像素的颜⾊色信息,而深度缓冲区存储像素的深度信息. 在决定是否绘制一个物体表面时, 首先要将表面对应的像素的深度值与当前深度缓冲区中的值进⾏行比较. 如果大于深度缓冲区中的值,则丢弃这部分.否则使用这个像素对应的深度值和颜色值.分别更更新深度缓冲区和颜⾊色缓存区. 这个过程称为”深度测试”
什么是深度?
深度其实就是该像素点在3D世界中距离摄像机的距离,Z值()
什什么是深度缓冲区?
深度缓存区,存储在显存中,专⻔门存储着每个像素点(绘制在屏幕上的)深度值.深度值(Z值)越⼤大,则离摄像机就越远.
为什么需要深度缓冲区?
在不不使⽤用深度测试的时候,如果我们先绘制⼀一个距离⽐比较近的物理理,再绘制距离较远的物理理,则距离 远的位图因为后绘制,会把距离近的物体覆盖掉. 有了了深度缓冲区后,绘制物体的顺序就不不那么 要的. 实际上,只要存在深度缓冲区,OpenGL 都会把像素的深度值写⼊入到缓冲区中. 除⾮非调⽤用glDepthMask(GL_FALSE).来禁⽌止写⼊入.
开启深度测试也可以解决隐藏面消失的问题。
glEnable(GL_);
我们可以通过修改glDepthFunc(GLenum func)
来改变深度测试的规则

开启深度测试后可能会引起ZFighting闪烁问题
因为开启深度测试后,OpenGL 就不会再去绘制模型被遮挡的部分. 这样实现的显示更加真实。但是由于深度缓冲区精度的限制对于深度相差⾮非常⼩小的情况下。(例如在同一平面上进行2次绘制),OpenGL 就可能出现不能正确判断两者的深度值,会导致深度测试的结果不可预测.显示出来的现象时交错闪烁。![]()
针对该问题,OpenGL提供了一种多边形偏移(Polygon Offset)方案。
glDisable(GL_POLYGON_OFFSET_FILL)

使用多边形偏移,主要有以下三个步骤
//开启多边形偏移
glDisable(GL_POLYGON_OFFSET_FILL)
//指定偏移量 参数一般填 -1 和 -1
glPolygonOffset (GLfloat factor, GLfloat units);
//关闭多边形偏移
glDisable(GL_POLYGON_OFFSET_FILL)
预防ZFighting闪烁
- 避免两个物体靠的太近:在绘制时,插入一个小偏移
- 将近裁剪面(设置透视投影时设置)设置的离观察者远一些:提高裁剪范围内的精确度
- 使用更高位数的深度缓冲区:提高深度缓冲区的精确度
3.混合
当开启深度测试后,两个重叠的图层中,如果有一个图层是半透明的,另一个是非半透明,此时就不能通过深度值比较,来进行颜色值的覆盖,而是需要将两个颜色进行混合,然后存入颜色缓冲区。
使用
针对不同需求,颜色混合的使用方式有两种
- 用于单纯的将两个图层重叠时进行颜色混合,这种混合并不能解决颜色的混合。在固定着色器和可编程着色器都可以使用这种方式
//开启,
glEnable(GL_BlEND);
//关闭
glDisable(GL_BlEND);
-
用于处理类似滤镜效果的场景,简单描述就是将需要处理的图片颜色和图片上覆盖的半透明颜色进行混合 即 两股颜色混合,此时如果只是单纯的开关方式,已经不能满足我们的需求,需要借助混合方程式,来实现两股颜色的混合。一般是在可编程着色器中片元着色器中使用。
//开启,
glEnable(GL_BlEND);
//设置混合因子--默认值是 GL_SRC_ALPHA 和 GL_ONE_MINUS_SRC_ALPHA
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//关闭
glDisable(GL_BlEND);
在glBlendFunc方法中,是通过混合方程式来得到颜色的组合,默认情况下混合方程式如下所示
//Cf -- 最终组合的颜色值
//Cd:源颜色 -- 当前渲染命令传入的颜色值
//CS:目标颜色 -- 颜色缓冲区中已经存在的颜色值
//S:源混合因子
//D:目标混合因子
Cf = (Cs * S) + (Cd * D)
总结
- 在颜色缓冲区中,每个像素点只能存储一种颜色
- 颜色混合主要用于实现在不透明物体前绘制透明物体的效果
- 只有上面图层是透明时,才需要开启颜色混合,如果不是,则没有必要开启颜色混合