3

从一个角度看,我的灌木看起来像这样:

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

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

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

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


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

4

3 回答 3

9

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

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

于 2012-02-19T21:32:35.033 回答
3

解决方案#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”。使用分析器并始终在优化之前进行测量,否则您将浪费大量开发时间进行不必要的优化。

于 2012-02-19T21:58:18.450 回答
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;
}
于 2013-12-22T19:07:23.907 回答