[!error] Z-Fighting(深度冲突)是指两个深度非常接近物体,在渲染时争夺同一个屏幕像素的深度测试结果。比如两个几乎重叠的表面
发生 深度冲突 会有什么现象?
-
⚪️有以下现象,可能发生了深度冲突:
- 条纹、斑块、摩尔纹;
- 两个材质交替出现;
- 摄像机移动时图案变化;
- 画面闪烁或抖动;
- 局部区域像“穿插”在一起。
-
👁️ 深度冲突常见于:
- 两个重叠平面;
- 地面上贴了一层几乎共面的贴花;
- 两个模型表面重合;
- 阴影接收面和深度投影存在误差。
为什么会产生 深度冲突 ?
- 在渲染管线 的 光栅化阶段 里 会为每个片元计算深度,然后进行深度测试。如图⬇️
flowchart LR
subgraph A[光栅化阶段会做的事]
direction LR
A1[计算片元深度]
B[与深度缓冲比较]
C[决定片元是否绘制]
D[更新颜色和深度缓冲]
end
A1-->B-->C-->D
- 由于 深度缓冲不是无限精确 的,通常只有 16位 、24位、或32位精度。如果两个表面太近,他们就可能被量化成非常接近的深度值。
平面 A:0.500000
平面 B:0.500001
- 经过深度缓冲量化后,这上面两个值可能变成同一个值
- 在光栅化的时候,由于这个浮点误差、插值误差、和像素误算,有些片元被判断的近一些,有些远。表现出虽然是一个片面,但是屏幕片元判断不一样的情况
[!warning] 相机近裁平面 和远裁平面 对深度冲突 的影响
- 深度精度 在近裁面附近比较高:所以相机离的近,会减小误差,Z-Fighting 现象就会减弱。反之里相机越远,深度缓冲就干架干得厉害。
- 相机的近裁平面(near)和远裁平面(far)他们之间的范围相差越大越会发生深度冲突
深度冲突 怎么避免 ?
-
让几何体或平面 不要离的这么近!
- 实际距离取决于场景尺度、相机距离和深度缓冲精度。
-
相机的 远近剪裁范围不要相差太大
-
使用开启深度偏移
- 对于无法改变几何位置的情况,例如贴花、道路标线、UI 覆盖层、阴影等,可以使用以下参数:
- Constant Bias:可以解决基本的深度重合;
- Slope-Scaled Bias:解决倾斜表面上的深度变化;
- clamp:防止偏移太大导致悬浮或穿模。
- Polygon Offset;
- Depth Bias;
- Depth Bias Clamp。
开启深度偏移后最终深度会产生变化。
- 对于无法改变几何位置的情况,例如贴花、道路标线、UI 覆盖层、阴影等,可以使用以下参数:
最终深度 = 原始深度 + 固定偏移 + 斜率相关偏移
[!note] cocos 对应的深度偏移参数
- |参数|别名|作用|为什么需要它|
|—|—|—|—|
|depthBias|Constant Bias / Units Factor|施加一个固定的深度偏移量|解决平面平行于屏幕时的 Z-Fighting(此时斜率=0,只有常量项生效)|
|depthBiasSlope|Slope-Scaled Bias / Factor|根据多边形相对于视线的倾斜程度动态调整偏移|解决大角度斜面的 Z-Fighting。斜面在深度缓冲中的精度更差,需要更大的偏移;正面朝向相机的面精度高,偏移应小甚至为0|
|depthBiasClamp|Clamp|限制偏移量的最大值和最小值|防止极端斜率导致偏移过大,使物体"悬浮"或穿模到不该穿的地方|
[!tip] 各个渲染 api 底层机制参考
- |图形 API / 管线|常见机制|
|—|—|
|OpenGL|glPolygonOffset(factor, units)|
|Direct3D|DepthBias、SlopeScaledDepthBias、DepthBiasClamp|
|Vulkan|depthBiasConstantFactor、depthBiasSlopeFactor、depthBiasClamp|
|Cocos 等引擎|通常封装为 Depth Bias、Polygon Offset、Shadow Bias 或材质参数|
评论区