OpenGL正面&背面剔除与深度测试

2020-07-21  本文已影响0人  Gumball_a45f

1.隐藏面消失

在绘制图形的时候,图形的背面是观察者不可见的,那么这部分就不应该被渲染出来,这种情况叫“隐藏面消除”

image.png

使用平面着色器来绘制时,会出现隐藏面消除吗?

隐藏面消除不会因为着色器的不同而消失,只不过因为平面着色器正反面的颜色相同,所以无法察觉。

为什么使用默认光源着色器?

因为默认光源着色器有阴面和阳面可以看的出来隐藏面消失的问题。

可以用开启正背面剔除的方法来处理隐藏面消失

 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.深度测试

  • 什么是深度?

深度其实就是该像素点在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)

总结

上一篇 下一篇

猜你喜欢

热点阅读