原生WebGL粒子系统不透明度问题

时间:2014-04-24 23:55:03

标签: javascript graphics opengl-es 3d webgl

我正在尝试渲染纹理粒子,我遇到了问题。 纹理透明像素做一个奇怪的事与回报。 看起来像是最接近(相机)粒子的粒子根本不会渲染。 但并非总是如此,其中一些是渲染和期待。 我试图使用深度和混合选项,但没有结果。

也许可以通过修改此部件代码找到解决方案。

gl.enable(gl.DEPTH_TEST);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

下面的变体修复了我的问题,但没有给我需要的结果。颗粒变得透明并相互重叠。

// gl.enable(gl.DEPTH_TEST);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);

所以我的问题是jsfiddle

1 个答案:

答案 0 :(得分:1)

问题是z缓冲和深度测试。

您有效地以随机深度顺序绘制四边形。因此,首先绘制一个近似粒子,它会在快乐面的角上绘制透明像素,并为这些像素设置zbuffer。后来一些粒子被吸引但是zbuffer说不要画它们。

一些解决方案,每个都有自己的问题

  1. 对您正在绘制的所有透明内容进行排序,然后绘制最远到最近的内容。

    另外:它有效

    减:它真的很慢,特别是对于成千上万的粒子。

  2. 使用添加剂或其他混合模式。

    Plus:适用于某些情况,如火灾和可能冒烟

    减号:仅适用于火灾和烟雾等特定情况

  3. 丢弃透明像素

    更改着色器以丢弃像这样的透明像素

    void main() {
      float alphaThreshold = 0.1;
      vec4 color = texture2D(u_sampler, gl_PointCoord);
      if (color.a <= alphaThreshold) {
        discard;
      }
      gl_FragColor = color;
    }
    

    Plus:适用于100%透明像素的不透明纹理

    减:对于少于100%透明像素的抗锯齿,它是否真的有效。

  4. 如果您try #3 on your sample you'll see it mostly works但是当粒子非常大时,您仍然可以在仍然通过alphaThreshold测试的半透明像素上看到问题。您可以将alphaThreshold更改为更高的数字以丢弃更多像素,它可能看起来更好或更差。

    同样仅供参考:请注意,GL对POINTS的大小有依赖于实现的限制,因此您的示例将无法在许多实现中按预期工作。您可能需要考虑切换到quad based particles