原生 WebGL 粒子系统不透明度问题 [英] Native WebGL particle system opacity issue

查看:27
本文介绍了原生 WebGL 粒子系统不透明度问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试渲染纹理粒子,但我遇到了问题.纹理的透明像素对渲染做了一件奇怪的事情.看起来离(相机)最近的粒子根本没有渲染.但并非总是如此,其中一些正在渲染并且看起来很预期.我试图尝试使用深度和混合选项,但没有结果.

I am trying to render textured particles and i have the problem. Transparent pixels of texture doing a weird thing with render. Looks like particles that are behing nearest (to camera) particles are not rendering at all. But not always, some of them are rendering and look expected. I was tried to play around with depth and blend options but without result.

也许可以通过修改这部分代码找到解决方案.

Perhaps that a solution can be found by modifying this part code.

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

下面的变体解决了我的问题,但没有给我所需的结果.粒子变得透明并相互重叠.

Variant below are fixes my problem, but does not give me needed result. Particles becomes transparent and overlap each other.

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

所以这里是 jsfiddle 我的问题.

So here is jsfiddle with my problem.

推荐答案

问题在于 z-buffering 和深度测试.

The problem is z-buffering and the depth test.

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

You're drawing quads in effectively a random depth order. So, you draw a close particle first, it draws the transparent pixels on the corners of the happy face and sets the zbuffer for those pixels. Later some particles behind get drawn but the zbuffer says not to draw them.

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

A few solutions, each with their own issues

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

  1. Sort all the transparent stuff you're drawing then draw furthest to closest.

另外:它有效

减:它真的很慢,尤其是对于数千个粒子.

Minus: It's really slow, especially for thousands of particles.

使用加法或其他混合模式.

Use an additive or other blending mode.

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

Plus: works for certain cases like fire and possibly smoke

减号:仅适用于某些情况,例如火灾和烟雾

Minus: only works for certain cases like fire and smoke

丢弃透明像素

改变你的着色器来丢弃像这样的透明像素

Change your shader to discard transparent pixels like this

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

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

Plus: Works for opaque textures with 100% transparent pixels

缺点:对于小于 100% 透明像素的抗锯齿效果并不真正有效.

Minus: Doesn't truly work for anti-aliased less than 100% transparent pixels.

如果您在您的样本上尝试#3,您会发现它基本上有效但是当粒子非常大,您仍然可以在仍然通过 alphaThreshold 测试的半透明像素上看到问题.您可以将 alphaThreshold 更改为更高的数字以丢弃更多像素,它可能看起来更好或更糟.

If you try #3 on your sample you'll see it mostly works but when particles are really large you can still see the issue on the semi-transparent pixels that still pass the alphaThreshold test. You can change the alphaThreshold to a higher number to discard more pixels and it might look better or worse.

也仅供参考:请注意,GL 对 POINTS 的大小有依赖于实现的限制,因此您的示例在许多实现中无法按预期工作.您可能需要考虑切换到基于四边形的粒子.

Also just FYI: Be aware that GL has an implementation dependent limit on how large POINTS can be so your sample will not work as intended on many implementations. You might want to consider switching to quad based particles.

这篇关于原生 WebGL 粒子系统不透明度问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆