OpenGL 3.3中的Z-fighting正交2D视图

huangapple go评论89阅读模式
英文:

opengl 3.3 z-fighting ortho 2d view

问题

我在使用OpenGL绘制简单的2D纹理四边形时遇到了一些Z fighting的问题。症状是两个物体以相同的速度移动,并且一个物体在另一个物体的上方,但是周期性地可以看到它们互相透视,就像是在"闪烁"。我认为这确实是Z fighting。

我已经关闭了深度测试,并且设置了以下参数:

gl.Disable(gl.DEPTH_TEST)
gl.DepthFunc(gl.LESS)
gl.Enable(gl.BLEND)
gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

我的视图矩阵和正交投影矩阵如下:

Projection := mathgl.Ortho(0.0, float32(width), float32(height), 0.0, -5.0, 5.0)
View := mathgl.LookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)

唯一与我的OpenGL流程不同的是,我将所有顶点、UV坐标(精灵图集)、平移、旋转等打包到一个大的数据包中,并发送到顶点着色器中,而不是为每个单独的对象调用drawelements函数。

有人对2D Z fighting有解决方法吗?

编辑:

我添加了一些图片来进一步描述情况:

OpenGL 3.3中的Z-fighting正交2D视图

OpenGL 3.3中的Z-fighting正交2D视图

这些图片是在几秒钟内拍摄的。它们只是从左到右移动的纹理。当它们移动时,你可以从图片中看到,一个精灵会重叠在另一个精灵上,反之亦然,来回闪烁。

还要注意,我的图片(精灵)是带有透明背景的PNG图片。

英文:

I'm having some issues with z fighting while drawing simple 2d textured quads using opengl. The symptoms are both objects moving at the same speed and one on top of another but periodically one can see through the other and vice versa - sort of like a "flickering". I assume this is indeed z fighting.

I have turned off Depth Testing and have the following as well:

gl.Disable(gl.DEPTH_TEST)
gl.DepthFunc(gl.LESS)
gl.Enable(gl.BLEND)
gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

My view and ortho matrices are as follows:

I have tried to set the near and far distances much greater ( like range of 50000 but still no help)

Projection := mathgl.Ortho(0.0, float32(width), float32(height), 0.0, -5.0, 5.0)




View := mathgl.LookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)

The only difference with my opengl process is that instead of a drawelements call for each individual object, I package all vertices, uvs(sprite atlas), translation, rotation, etc in one big package sent to vertex shader.

Does anyone have remedies for 2d z fighting?

edit:

i'm adding some pictures to further describe the scenario:

OpenGL 3.3中的Z-fighting正交2D视图

OpenGL 3.3中的Z-fighting正交2D视图

These images are taken a few seconds apart from each other. They are simply texture moving from left to right. As they move; you see from the image, that one sprite over-lapse the other and vice versa back and forth etc very fast.

Also note that my images (sprites) are pngs that have a transparent background to them..

答案1

得分: 2

如果你在代码片段中禁用了深度测试,那么它肯定不会导致深度冲突。

“我将所有顶点、UV(精灵图集)、平移、旋转等打包到一个大的数据包中,发送到顶点着色器。” - 你需要检查你添加精灵的顺序。也许由于某种原因,它们的添加是不一致的。

英文:

It definitely isn't depth fighting if you have depth testing disabled as shown in the code snippet.

"I package all vertices, uvs(sprite atlas), translation, rotation, etc in one big package sent to vertex shader." - You need to look into the order that you add your sprites. Perhaps it's inconsistent for some reason.

答案2

得分: 1

  1. 这可能是Z fighting(深度冲突)的问题。

通常的原因有:

  • 片段在相同的Z坐标或比Z坐标的精度更近的位置
  • 片段距离透视相机太远,使用透视投影时,距离Z近平面越远,精度越低

修复这个问题的一些方法有:

  • 稍微改变重叠表面的大小/位置
  • 使用更多的位数来存储Z缓冲(深度)
  • 使用线性或对数Z缓冲
  • 增加Z近平面或减小Z远平面,或者两者都调整。对于透视投影,你可以组合多个视锥体来获得高清的Z范围
  • 有时使用glDepthFunc(GL_LEQUAL)可以有所帮助
  1. 这可能是混合(Blending)的问题。

当你使用混合时,需要以稍微不同的方式进行渲染。为了正确渲染透明度,你必须对场景进行Z排序,否则可能会出现伪影。如果你有太多密集的透明物体或者靠近它们的物体(许多多边形边缘靠近),此外,深度冲突与混合结合会产生更高级别的伪影。

修复这个问题的一些方法有:

  1. Z排序可以通过多次渲染+深度测试+切换正面进行部分完成

    首先渲染所有的实体物体,然后以不面向相机的一侧设置正面,渲染Z排序的透明物体。然后以面向相机的一侧设置正面,再次渲染相同的物体。你需要使用深度测试来实现这一点!这样你就不需要对整个场景的所有多边形进行排序,只需要对透明物体进行排序。结果对于复杂的透明几何体来说可能不是100%正确,但通常结果已经足够好(尤其是对于动态场景)。下面是这种方法的输出示例:

    OpenGL 3.3中的Z-fighting正交2D视图

    这是一个玻璃杯,由于选择了适用于此情况的混合函数,视觉上有点混乱,因为较暗的像素表示有两层玻璃,这是故意的,并非错误。因此,开口看起来像是正反面被交换了。

  2. 对透明物体使用较少密集的几何体

  3. 消除Z fighting问题

英文:
  1. This could be Z fighting

the usual causes are:

  • fragments are at the same Z-coordinate or closer then accuracy of Z-coordinate
  • fragments are too far from perspective camera with perspective projection the more far you are from Z near the less accuracy

some ways to fix this:

  • change size/position of overlapped surfaces slightly
  • use more bits for Z-Buffer (Depth)
  • use linear or logarithmic Z-buffer
  • increase Z-near or decrease Z-far or both for perspective projection you can combine more frustrums to get high definition Z range
  • sometimes helps to use glDepthFunc(GL_LEQUAL)
  1. This could be an issue with Blending.

as you use Blending you need to render a bit differently. To render transparency correctly you must Z-sort the scene otherwise artifacts can occur. If you got too much dense geometry of transparent objects or objects near them (many polygon edges near). In addition Z-fighting creates a magnitude higher artifacts with blending.

some ways to fix this:

  1. Z sorting can be partially done by multi pass rendering + Depth test + switching front face

    so first render all solids and then render Z-sorted transparent objects with front face set to the side not facing camera. Then render the same objects with front face set for side facing camera. You need to use depth test for this!!!. This way you do not need to sort all polygons of scene just the transparent objects. Results are not 100% correct for complex transparent geometries but the results are usually good enough (especially for dynamic scenes). This is how the output from this looks like
    
    ![example][1]
    
    it is a glass cup a bit messed up visually by selected blending function for this case because darker pixels means 2 layers of glass on purpose it is not a bug. Therefore the opening looks like the front/back faces are swapped
    
  2. use less dense geometry for transparent objects

  3. get rid of Z-fighting issues

huangapple
  • 本文由 发表于 2015年8月17日 10:18:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/32041914.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定