在OpenGL中进行深度测试的Z-fighting解决方案 - 它们如何工作?

mic*_*rus 11 opengl graphics shader rendering glsl

描述

我在OpenGL中遇到了Z-Fighting的主要问题,我花了很长时间才找到解决这个问题的方法.我发现的一些,我理解并不喜欢:

  • 移动多边形彼此远离(如OpenGL中的glPolygonOffset)
  • 根据Z坐标划分场景,并使用单独的干净z缓冲区绘制场景的部分.

那些我不明白的:

我已经在我的程序中实现了第二个,只需将它放入球的顶点着色器(它与地面z-fight):

float C = 1.0; 
float far = 2000.0; 
   gl_Position = u_projView * a_position;      
gl_Position.z = 2.0*log(gl_Position.w*C + 1.0)/log(far*C + 1.0) - 1.0;
gl_Position.z *= gl_Position.w;
Run Code Online (Sandbox Code Playgroud)

它工作了!

实际问题

  1. 任何人都可以解释我是如何在顶点着色器中更改顶点的Z坐标解决了问题而没有将顶点明显地移动到我身上?(场景看起来与人眼相同).它是如何改变z深度值的分布的?我猜我错过了一些关于渲染管道的知识.
  2. 任何人都可以向我解释我们如何使用Projection Matrix来解决问题?它是如何工作的?
  3. 是否还有其他类似的有效方法来解决z-fighting问题?

谢谢!

小智 2

也许深度缓冲区精度有问题?当使用 16 位缓冲区时,很可能会发生 z-fighting。您可以使用以下方法检查它:

glGetIntegerv( GL_DEPTH_BITS, &depthBits);
Run Code Online (Sandbox Code Playgroud)