【问题标题】:Rendering glitch with GL_DEPTH_TEST and transparent textures使用 GL_DEPTH_TEST 和透明纹理渲染故障
【发布时间】:2012-03-10 07:49:39
【问题描述】:

从一个角度看,我的灌木是这样的:

从另一个角度看,它们看起来像这样:

我的理论是,从第一个角度看灌木时,灌木后面的所有方块都已经画好了,所以在画灌木的时候,它只是把它们画在上面。

然而,从另一个角度来看,它基本上是先尝试绘制灌木,然后当​​它去绘制灌木后面的块时,它会检查深度缓冲区并发现已经有东西挡住了块的视野,所以它不会渲染它,导致海军蓝色方块(我的清晰颜色)。

我真的不知道如何解决这个问题。禁用深度测试会导致各种其他错误。有没有办法将顶点或多边形标记为具有透明度,以便它知道它仍然需要渲染后面的内容?


Found this。这是唯一的解决方案吗?分离我的透明和不透明块,然后几乎每一帧都在 CPU 上手动对它们进行排序,因为玩家可以四处移动?必须有一种方法可以将其委托给 GPU...

【问题讨论】:

  • Minecraft 克隆作品正在制作中?
  • 嘿,这些是 Mojang 的 256 像素! :P
  • @JesusRamos:类似的东西 :) 游戏玩法和重点会有所不同。
  • @Thomas:65536 像素,如果你想获得技术。

标签: opengl 3d rendering depth


【解决方案1】:

该链接(以及在 CPU 上排序)用于 alpha 混合。如果您只需要 Alpha 测试(而不是混合),那么您不需要对任何东西进行排序。只需启用 alpha 测试,保持启用深度测试,一切都会正常呈现。

请看这里:http://www.opengl.org/wiki/Transparency_Sorting 您需要需要 Alpha 测试的“Alpha 测试”,而不是需要排序的“标准半透明”。

【讨论】:

  • 启用 alpha 测试会导致它使用glAlphaFunc,对吗?那我应该使用什么功能?默认似乎不起作用。 “不等于”几乎可以工作,除非从侧面直接看:i.imgur.com/HMhSu.png
  • @Martins:Nvm。你的文章解释得很好。稍后我将不得不处理半透明问题,但我想我会过一会儿。
  • 哥们,你是我的救命恩人!!!我已经连续 48 小时与这个问题作斗争,最后只需要两行代码就可以解决它……谢谢,如果可以的话,我会给你钱,哈哈。谢谢。
【解决方案2】:

解决方案#1:

  1. 首先以任意顺序渲染所有非透明对象,启用深度缓冲区。这包括所有使用 alpha 测试没有 alpha 混合的对象。
  2. 对于glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 对象(烟雾/玻璃/草):将透明场景从最远的多边形 渲染到最近的多边形,并禁用深度缓冲区写入 (glDepthMask(GL_FALSE))。如果所有透明对象都是凸面且不相交,则可以对对象进行排序,而不是对多边形进行排序。
  3. 对于glBlendFunc(GL_SRC_ALPHA, GL_ONE)glBlend(GL_ONE, GL_ONE)(火焰、“魔法”粒子系统、发光):在禁用深度缓冲区写入 (glDepthMask(GL_FALSE)) 的情况下以任意顺序渲染透明场景。
  4. 在第 3 步之后不要渲染任何启用深度缓冲的对象。

解决方案 #2:
使用深度剥离(google it)。特别是如果透明对象相互交叉。不适用于需要解决方案 #1 的粒子系统和草。


然后几乎每一帧都在 CPU 上手动对它们进行排序

插入排序非常适合已排序或部分排序的数据。

必须有办法将此委托给 GPU...

我认为您可以使用具有通道(例如 alpha)的纹理在几何着色器中生成草多边形(以正确的顺序),该通道标记有草和没有草的区域。需要 OpenGL 4,您可能需要对多边形执行某种更高级别的排序,然后将其提供给着色器以生成草地补丁。

单个灌木可以在顶点着色器中旋转(+- 90/180/270 度)以保持正确的多边形排序,前提是它们在所有方向上都完全对称。

还有一种合并排序算法可以很好地并行化并且可以在 GPU 上执行,使用 GDGPU 方法或 OpenCL/CUDA。

但是,使用类似的东西来渲染 5 棵草丛大致相当于试图用榴弹发射器杀死一只蟑螂 - 这样做很有趣,但效率不高。

我建议在您真正遇到性能问题之前忘记“将其卸载到 GPU”。使用分析器并始终在优化之前进行测量,否则您将浪费大量开发时间进行不必要的优化。

【讨论】:

  • 哈!我记得学习排序算法并思考“我什么时候才能事先知道我的数据已经大部分排序?最后,一个用例。我将深入研究这个。谢谢一步一步的,非常有帮助。
  • 灌木并不是真正的问题,特别是因为我可以通过 alpha 测试渲染它们,但我担心的是大片水域。那些是半透明的,所以我必须对它们进行分类。幸运的是,我猜只是表面多边形需要排序。我会尝试一下,看看效果如何。通过“委托给 GPU”,我更多地考虑首先进行单次渲染,然后收集有关其距离的数据,类似于这个人所做的:rastergrid.com/blog/2010/02/…
  • @Mark:除非你有非常大的波浪,否则你不需要对水进行分类,因为它是平的,所以你可以一次渲染它。对于非平水,您通常仍然不需要对其进行排序,只需在所有不透明的内容之后将其渲染即可。当然,如果你用它做墙,那就有问题了,它需要分类。
  • 每次玩Minecraft?这正是人们对水所做的事情>.
  • @Mark:“每次都玩 Minecraft?”不,您可能想查看sauerbraten,不过(附带源代码)。
【解决方案3】:

如果您使用的是 WebGL 或 OpenGL ES 2.0 (iPhone/Android),则没有 alpha 测试。相反,您不需要绘制透明像素。这样它们就不会影响深度缓冲区,因为没有写入像素。为此,您需要丢弃片段着色器中透明的像素。你可以硬编码

...
void main() {
   vec4 color = texture2D(u_someSampler, v_someUVs);
   if (color.a == 0.0) {
     discard;
   }
   gl_FragColor = color;
}

或者您可以模拟旧式 alpha 测试,您可以在其中设置 alpha 值

...
uniform float u_alphaTest;
void main() {
   vec4 color = texture2D(u_someSampler, v_someUVs);
   if (color.a < u_alphaTest) {
     discard;
   }
   gl_FragColor = color;
}

【讨论】:

    猜你喜欢
    • 2010-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-16
    • 1970-01-01
    • 2016-02-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多