避免与重合表面发生Z角战斗


26

渲染两个重叠的共面曲面时,一个常见的问题是“ z-fighting”,即渲染器无法确定两个曲面中的哪个更靠近相机,从而在重叠区域产生视觉伪像。

标准的解决方案是在设计模型时使表面略有偏移。还有其他解决方案吗?


2
您可以签出对数深度缓冲区。关于gamasutra
Soapy

1
当您说“共平面”时,您是指“几乎”还是“完全”共平面,如果是后者,这些表面是否曾经是相同的表面/三角形?对于最后一种情况,渲染硬件应该是确定性的(假设您不是以随机顺序提交的),并且没有战斗力。如果是表面不相同但正好共面的情况,您是否可以更新模型以将表面拆分为重叠和不重叠的部分?
西蒙F

@SimonF,“共面”是指“完全共面”。Soapy的解决方案仅适用于“几乎共面”的情况。
标记

您能举个例子吗?我唯一想到的就是@SimonF提到的重复三角形。
RichieSams 2015年

@RichieSams我能想到的最常见的情况是贴花,在贴花中您不需要完全重复的三角形。
2013年

Answers:


10

如果表面完全平整,那么您的命运取决于FPU的神灵。您很有可能会进行Z战。如果三角形是相同的,你做确切同样的数学到每个,你最终获得两个相同的Z值。但是同样,只有当您的两个数学运算相同时,才会发生这种情况。(因为通常,FPU操作不是可交换的)

一种可能的解决方案是根本不使用Z缓冲区。而是可以使用Painter的算法。当然,这也伴随着painters算法的所有问题。但是,这将解决Z战。

在屏幕空间贴标(SSD)的示例中,常见的解决方案是使用偏移量,也就是简单的薄立方体。有关参考,请参阅Warhammer 40k 关于SSD 的演示。或Bart Wronski的帖子不仅解决了贴花纸的其他问题,而且还链接到有关SSD的其他一些演示文稿


5
使用相同的变换重新渲染相同的几何图形确实会每次可靠地生成相同的深度值。(也就是说,它不是一个强权,这是一个意志)。例如,这就是为什么多路前向照明有效的原因。
内森·里德

@NathanReed已更正。感谢您的澄清
RichieSams

1
要获得该功能,您需要在glsl中使用不变限定符:opengl.org/wiki/Type_Qualifier_%28GLSL%29#Invariance_qualifiers
ashleysmithgpu 2015年

请注意,在评估顶点位置时,相同的着色器表达式(显然是输入)可能不足以获得相同的结果,因为某些优化可能取决于着色器的其余部分。GLSL使用“ invariant”关键字来声明必须在不同着色器中进行相同评估的着色器输出。
Firadeoclus 2015年

2

这是我过去解决此问题的方法:

  1. 通过深度测试绘制第一个对象(应该出现在另一个对象后面的对象),但不进行深度写入
  2. 通过深度测试和深度书写绘制第二个对象。因为我们没有在步骤1中写任何深度,所以不会引起z冲突。
  3. 通过仅写入深度缓冲区而非颜色缓冲区来绘制第一个对象。这可以确保深度缓冲区对于对象1而不是对象2覆盖的任何像素都是最新的。

请注意,对象需要连续绘制才能起作用。


0

根据您的渲染器的不同,您可以使用类似噪声的算法在多采样深度中应用微小的偏移,使表面更“模糊”。对于接近深度的表面,这应该导致某种混合效果。对于我所知道的,在片段着色器中设置每个样本的深度在OpenGL中是最近的,然后仅作为扩展。

OpenGL具有PolygonOffset,但需要事先知道您将要渲染共面的东西。虽然对于单个模型中的曲面不可行,但可以很好地工作,例如当绘制覆盖在一块土地上的道路时。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.