透明度实际上有点复杂
有
#1 画布本身需要什么
默认画布需要预乘 alpha。换句话说,它希望您提供 RGBA 值,其中 RGB 已乘以 A。
您可以设置画布,使其在创建 webgl 上下文时不需要预乘 alpha,方法是传入 premultipledAlpha: false,如下所示
const gl = someCanvas.getContext('webgl', {premultipliedAlpha: false});
注意:IIRC 这不适用于 iOS。
#2 加载图片的格式
在 WebGL 中加载图像的默认值是未预乘的 alpha。换句话说,如果图像的像素是
255, 128, 64, 128 RGBA
它将完全像那样加载(*)
您可以通过设置告诉 WebGL 在加载图像时为您预乘
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
在致电gl.texImage2D之前。
现在上面的同一个像素最终会变成
128, 64, 16, 128 RGBA
每个 RGB 都乘以 A(上面的 A 是 128,其中 128 代表 128/255 或 0.5019607843137255)
#3 你在着色器中写出的内容
如果您加载了未预乘的数据,您可能会选择在着色器中进行预乘
gl_FragColor = vec4(someColor.rgb * someColor.a, someColor.a);
#4 你如何混合
如果要将正在绘制的内容混合到已经绘制的内容中,则需要打开混合
gl.enable(gl.BLEND);
但您还需要设置混合的方式。有多种功能会影响混合。最常用的是gl.blendFunc,它设置src 像素(由着色器生成的像素)和dst 像素(在画布顶部绘制的像素)在组合之前受到的影响。两种最常见的设置是
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); // unpremultiplied alpha
和
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); // premultiplied alpha
第一个参数是如何乘以 src 像素。上面我们要么乘以 src 的 alpha (SRC_ALPHA),要么乘以 1 (ONE)。第二个参数是如何乘以 dst 像素。 ONE_MINUS_SRC_ALPHA 正是它所说的(1 - alpha)
如何将所有这些放在一起取决于您。
This article 和 This one 在某种程度上涵盖了这些问题
(*) 图片可能有color conversion applied。