javascript - webgl 2d 将两个透明纹理相互叠加

标签 javascript textures webgl blending

我正在尝试将两个具有 Alpha channel 的纹理相互混合。

enter image description here

查遍网络后发现没有简单的方法可以解决这个问题。我在片段着色器中尝试了这个技巧:

if(gl_FragColor.a < 0.5){
    discard;
}

这适用于没有太多 Alpha 变化的简单纹理,例如背景中的人类 Sprite 。但我希望能够处理更复杂的图像,例如根本不起作用的渐变 Sprite 。

这是我的片段着色器:

precision mediump float;
varying vec3 fragColor;
varying highp vec2 vTextureCoord;
uniform sampler2D uSampler;
void main()
{
    vec4 tex = texture2D(uSampler, vTextureCoord);
    gl_FragColor = tex * vec4(fragColor, 1.0);
    if(gl_FragColor.a < 0.5){
    discard;
}
}'

这是我的顶点着色器:

precision mediump float;

attribute vec3 vertPosition;
attribute vec3 vertColor;
attribute vec2 aTextureCoord;
varying vec3 fragColor;
varying highp vec2 vTextureCoord;
uniform mat4 uPMatrix;
uniform mat4 uMVMatrix;

uniform vec2 uvOffset;
uniform vec2 uvScale;

void main()
{
  fragColor = vertColor;
  gl_Position = uPMatrix * uMVMatrix * vec4(vertPosition.x, vertPosition.y, vertPosition.z, 1.0);
  vTextureCoord = aTextureCoord * uvScale + uvOffset;
}

这是我使用的 gl 设置的一部分:

gl.enable(gl.DEPTH_TEST);
gl.enable(gl.BLEND);
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.SRC_ALPHA, gl.ON);

目前,所有 Sprite 都绘制在同一 z 轴 0 上。但是,我不知道这是否是问题的根源,因为我测试为每个对象提供了随机 z 值,但问题仍然存在。

编辑: 回应 Rabbid76 的评论。

这个效果非常好! alpha 已混合,但唯一的问题是 Sprite 看起来“被烧焦”:

enter image description here

我尝试将片段着色器更改为:

<strike>gl_FragColor = tex * vec4(tex.rgb, tex.a);</strike>

But it still looks burned.

Edit 2

I solved it it. gl_FragColor should b:

gl_FragColor = vec4(tex.rgb, tex.a);

而不是

gl_FragColor = vec4(fragColor* tex.rgb, tex.a);

否则会产生燃烧混合效果

最佳答案

Currently all sprites are being drawn on the same z axis, 0.

由于启用了部门测试( gl.enable(gl.DEPTH_TEST) ),并且默认深度函数( depthFunc )为 gl.LESS ,第二个绘制的 Sprite 将无法通过深度测试。
您必须禁用深度测试:

gl.disable(gl.DEPTH_TEST);


此外,我建议调整混合函数( blendFunc ):

gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

或者你使用Alpha premultiplication 。因此,您必须调整片段着色器:

gl_FragColor = tex * vec4(fragColor * tex.rgb, tex.a);

并且您必须使用以下混合函数( blendFunc ):

gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);

注意,您不需要 if(gl_FragColor.a < 0.5) discard;不再有。

关于javascript - webgl 2d 将两个透明纹理相互叠加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45732861/

相关文章:

cocoapods - SCNScene 加载来自 pod 的纹理

opengl - GL_SRGB8_ALPHA8 对纹理插值的影响?

javascript - Highcharts : How to graph from Radio Button

javascript - 为什么这个 JavaScript 不能运行?

javascript - ng-change 正在清除预选的下拉选项

javascript - 无法一直跳转到页面显示顶部

android - Ice Cream Sandwich 上的 OpenGL 黑色纹理

javascript - 在 webgl 中创建类似铅笔的主体

webgl - 如何修改此 WebGL 片段着色器以增加高光的亮度并减少

javascript - WebGL-渲染一个又一个形状时出现问题