openGL深度冲突z-fighting

网友投稿 879 2022-11-20

openGL深度冲突z-fighting

openGL深度冲突z-fighting

openGL系列文章目录

文章目录

​​openGL系列文章目录​​​​前言​​​​一、为什么会产生z-fighting​​​​二、防止深度冲突​​

​​1.第一种方法​​​​2.第二种方法​​​​3.第三种方法​​

​​参考​​

前言

针对z-fighting从问题的描述,到为什么会产生z-fighting现象,在继而从投影矩阵的的角度来解释这个问题的发生以及解决,最后稍微介绍一下深度值的非线性与线性的转换所能应用的渲染场景。如有不妥欢迎留言,如果读者觉得我的文章对自己有益,还望推荐给自己的朋友,感激不尽。 开启深度测试后OpenGL就不会再去绘制模型被遮挡的部分,这样实现的显示画面更为真实,但是由于深度缓冲区精度的限制,对于深度相差非常小的情况(例如在同一平面上进行两次绘制),OpenGL就不能正确判定两者的深度值,会导致深度测试的结果不可预测,显示出来的现象时交错闪烁的前后两个画面,这种情况称为z-fighting。

下面我将从这几个方向进行阐述z-fighting的前世今生

1.z-fighting问题的描述 2.为什么会产生z-fighting现象? 3.从透视投影矩阵的角度解释以及如何避免 4.深度值的非线性与线性的转化

一、为什么会产生z-fighting

z-fighting问题的描述 首先来讲一下,我们在进行三维渲染物体的时候,一般都是采用透视投影矩阵这样会产生近大远小的效果,很符合现实中人眼观看世界的情况。但是渲染中经常会遇到场景中离视点较远的物体会有闪烁的现象,而场景中离视点比较近的地方反而很少会长生物体闪烁的现象。

这是为什么那?

而如果我们换用了正交投影矩阵后,闪烁的问题会极大的解决,这又是为什么那?

为什么会产生z-fighting现象? 第一点原因

场景中渲染多个三维物体的时候,几个三维物体的摆放位置有点接近,导致在深度缓冲测试的时候,会产生精度的误差,然后会导致几个物体之间的片段值有的时候a通过,有的时候b通过,导致交替显示这几个物体的颜色值,然后那就会产生闪烁的现象。

第二点原因

采用透视投影矩阵渲染的场景,其深度缓冲区存储的深度值,ndc空间中的深度值。而ndc空间的深度值是经由透视空间转换过来的,ndc空间的深度值与透视空间的深度值转换并非是线性的,而是非线性。大家都知到,透视空间转换到ndc空间会有一步透视除法,是处以z值。这样就会导致,离视点越近的物体的片段深度值是越精确的,离视点距离约远的物体的片段的深度值是约不精确的。这样就会导致z-fighting问题。

而采用正交透视矩阵渲染场景,其变换是线性的,为什么,因为其透视空间转换为ndc空间的时候采用的透视除法是处以1,所以其片段距离视点的深度值是线性的,这样除非你把两个物体设置的位置非常接近,否则是产生不了z-fighting这种现象的。

那么为什么透视投影矩阵渲染场景的时候,在透视空间转换到ndc空间时,透视除法会除以z值那?下面笔者从透视投影矩阵的数学推导层面来回到这个问题。

从透视投影矩阵计算的角度解释以及如何避免 三维空间的物体在经历的图元装配以后,会经历剪裁与淘汰这两步操作。其中在剪裁中经历坐标系的转换的。

坐标系的转换如下所示:

模型坐标系–>世界坐标系—>相机坐标系—>投影坐标系—>标准设备化空间–>视口变换—>光栅化阶段。

在其投影坐标系转换到标准设备化空间的时,需要将xyz坐标转换为-1到1之间,也可以说标准设备化空间(NDC)是一个立方体空间。那么该怎么达到这样的操作那?答案是借助于矩阵,矩阵的一个几何意义就是将一个物体从一个坐标系转换到另外一个坐标系。那么笔者下面将去介绍这个透视投影矩阵是长的什么样子。

注意到蓝色线框里面.有花屏现象

这张图片就没有深度冲突

二、防止深度冲突

1.第一种方法

第一个也是最重要的技巧是永远不要把多个物体摆得太靠近,以至于它们的一些三角形会重叠。通过在两个物体之间设置一个用户无法注意到的偏移值,你可以完全避免这两个物体之间的深度冲突。在箱子和地板的例子中,我们可以将箱子沿着正y轴稍微移动一点。箱子位置的这点微小改变将不太可能被注意到,但它能够完全减少深度冲突的发生。然而,这需要对每个物体都手动调整,并且需要进行彻底的测试来保证场景中没有物体会产生深度冲突。

2.第二种方法

第二个技巧是尽可能将近平面设置远一些。在前面我们提到了精度在靠近近平面时是非常高的,所以如果我们将近平面远离观察者,我们将会对整个平截头体有着更大的精度。然而,将近平面设置太远将会导致近处的物体被裁剪掉,所以这通常需要实验和微调来决定最适合你的场景的近平面距离。

3.第三种方法

另外一个很好的技巧是牺牲一些性能,使用更高精度的深度缓冲。大部分深度缓冲的精度都是24位的,但现在大部分的显卡都支持32位的深度缓冲,这将会极大地提高精度。所以,牺牲掉一些性能,你就能获得更高精度的深度测试,减少深度冲突。

我们上面讨论的三个技术是最普遍也是很容易实现的抗深度冲突技术了。还有一些更复杂的技术,但它们依然不能完全消除深度冲突。深度冲突是一个常见的问题,但如果你组合使用了上面列举出来的技术,你可能不会再需要处理深度冲突了。

参考

​​牧野​​​​SkySnow​​

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:聊聊Spring Cloud Gateway过滤器精确控制异常返回问题
下一篇:openGL API之glPolygonOffset函数
相关文章

 发表评论

暂时没有评论,来抢沙发吧~