渲染两个重叠的共面曲面时,一个常见的问题是“ z-fighting”,渲染器无法确定两个曲面中的哪个更靠近相机,从而在重叠的区域中产生视觉伪像。
对此的标准解决方案是在设计模型时使表面略微偏移。还有其他解决方案吗?

评论

您可以签出对数深度缓冲区。关于gamasutra有一篇文章

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

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

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

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

#1 楼

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

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

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

评论


$ \ begingroup $
通过相同的变换重新渲染相同的几何图形确实可以每次可靠地生成相同的深度值。 (也就是说,这不是意志,而是意志)。例如,这就是为什么多路前向照明有效的原因。
$ \ endgroup $
–内森·里德(Nathan Reed)
2015年8月8日在17:51



$ \ begingroup $
@NathanReed已更正。谢谢你的澄清
$ \ endgroup $
–RichieSams
15年8月9日在18:44

$ \ begingroup $
要获得该功能,您需要在glsl中使用不变限定符:opengl.org/wiki/Type_Qualifier_%28GLSL%29#Invariance_qualifiers
$ \ endgroup $
–ashleysmithgpu
15年8月10日在11:11

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

#2 楼

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


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

#3 楼

根据您的渲染器的不同,您可以使用类似噪声的算法在多采样深度中应用微小的偏移,使表面更“模糊”。对于接近深度的表面,这将导致某种混合效果。据我所知,在片段着色器中设置每个样本的深度在OpenGL中是很新的,然后仅作为扩展。虽然不适用于单个模型中的曲面,但例如在绘制覆盖在一块土地上的道路时可以很好地工作。