本文详细解析 JavaScript WebGL 中图片透明处理的两种核心机制:Alpha 通道存储方式与 Alpha 混合。重点介绍 Premultiplied Alpha(预乘 Alpha)与 Non-premultiplied Alpha 的区别,以及通过 pixelStorei 配置纹理。深入讲解启用混合功能后,如何利用 blendEquation 和 blendFunc 系列方法控制源颜色与目标颜色的混合计算,实现正确的图像叠加效果。
引子
在 JavaScript WebGL 开发中,常遇到图片叠加时透明区域无法透出的问题。本节将深入探讨 WebGL 中透明图像的正确处理方式。
- Origin
- My GitHub
关于透明
透明度由颜色编码中的 Alpha 通道决定,其存储方式主要分为两类:
- Premultiplied Alpha(预乘 Alpha):在存储颜色信息时,RGB 值会与 Alpha 透明度值相乘。例如,若 RGB 为 (1, 1, 1),Alpha 为 0.5,则实际存储值为 (0.5, 0.5, 0.5, 0.5)。
- Non-premultiplied Alpha(非预乘 Alpha):RGB 颜色值与 Alpha 透明度值分开存储,不进行相乘操作。例如,若 RGB 为 (1, 1, 1),Alpha 为 0.5,则存储值为 (1, 1, 1, 0.5)。
在 WebGL 中,可通过 方法指定纹理的透明处理方式。若需使用 Premultiplied Alpha 模式,应设置此参数为 true。
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);WebGL 实现透明效果的另一种主要方式是使用 α 混合(Alpha Blending)。
α 混合
α 混合是指利用 RGBA 中的 Alpha 值,将两个或多个物体的颜色进行混合的过程。当绘制多个存在重叠区域的纹理时,后绘制的纹理 D 被视为源颜色(source color),先绘制的纹理 C 被视为目标颜色(destination color)。
要启用此功能,首先需要执行以下代码:
gl.enable(gl.BLEND);随后,可以通过以下方法指定具体的混合规则:
- blendEquation
- blendEquationSeparate
- blendFunc
- blendFuncSeparate
blendEquation
void blendEquation(enum mode)mode 方法的取值包括:
- FUNC_ADD:源颜色分量与目标颜色分量直接相加。
- FUNC_SUBTRACT:源颜色分量减去目标颜色分量。
- FUNC_REVERSE_SUBTRACT:目标颜色分量减去源颜色分量。
仅指定混合方式不足以产生最终视觉效果,还需配合 blendFunc 或 blendFuncSeparate 方法使用。参考文末的伪代码逻辑可加深理解。
这是示例。
blendEquationSeparate
void blendEquationSeparate(enum modeRGB, enum modeAlpha)
该方法的两个参数取值与 blendEquation 方法相同,区别在于它将颜色分为 RGB 和 Alpha 两个独立部分分别处理。
blendFunc
void blendFunc(enum sfactor, enum dfactor);- sfactor:常量,表示源颜色在混合中的权重因子,比 dfactor 多一个可选值
SRC_ALPHA_SATURATE。 - dfactor:常量,表示目标颜色在混合中的权重因子。
混合颜色的计算公式为:
混合后颜色 = 源颜色 * sfactor + 目标颜色 * dfactor
上述计算针对每个颜色分量进行。设 S 为源颜色,D 为目标颜色,各分量用小写 rgba 表示,以下是权重因子常量的取值:
| 常量 | R 分量 | G 分量 | B 分量 | A 分量 |
|---|---|---|---|---|
| ZERO | 0 | 0 | 0 | 0 |
| ONE | 1 | 1 | 1 | 1 |
| SRC_COLOR | S.r | S.g | S.b | S.a |
| ONE_MINUS_SRC_COLOR | (1-S.r) | (1-S.g) | (1-S.b) | (1-S.a) |
| DST_COLOR | D.r | D.g | D.b | D.a |
| ONE_MINUS_DST_COLOR | (1-D.r) | (1-D.g) | (1-D.b) | (1-D.a) |
| SRC_ALPHA | S.a | S.a | S.a | S.a |
| ONE_MINUS_SRC_ALPHA | (1-S.a) | (1-S.a) | (1-S.a) | (1-S.a) |
| DST_ALPHA | D.a | D.a | D.a | D.a |
| ONE_MINUS_DST_ALPHA | (1-D.a) | (1-D.a) | (1-D.a) | (1-D.a) |
此外,还可配合 方法使用的常量取值如下:
| 常量 | R 分量 | G 分量 | B 分量 | A 分量 |
|---|---|---|---|---|
| CONSTANT_COLOR | red | green | blue | alpha |
| ONE_MINUS_CONSTANT_COLOR | (1-red) | (1-green) | (1-blue) | (1-alpha) |
| CONSTANT_ALPHA | alpha | alpha | alpha | alpha |
| ONE_MINUS_CONSTANT_ALPHA | (1-alpha) | (1-alpha) | (1-alpha) | (1-alpha) |
若不通过 blendColor 指定分量,也可直接使用这些常量,因为它们有默认值:
gl.getParameter(gl.BLEND_COLOR) // 默认对应分量都是 0关于第一个参数中多出的取值 SRC_ALPHA_SATURATE:
| 常量 | R 分量 | G 分量 | B 分量 | A 分量 |
|---|---|---|---|---|
| SRC_ALPHA_SATURATE | min(S.a, 1-D.a) | min(S.a, 1-D.a) | min(S.a, 1-D.a) | 1 |
下面这些是示例:
- 没有使用
blendColor方法的示例。 - 配合使用
blendColor方法的示例。
blendFuncSeparate
void blendFuncSeparate(enum srcRGB, enum dstRGB, enum srcAlpha, enum dstAlpha)该方法的参数取值与 blendFunc 方法相同,区别在于它将颜色分为 RGB 和 Alpha 两个独立部分分别处理。
Back to top
参考资料
WebGL绘制详解之七:Blend
Texture Maps
Texture Mapping Using Images
WebGL and Alpha
Transparency (and Alpha Blending)
WEBGL, BLENDING, AND WHY YOU'RE PROBABLY DOING IT WRONG
到此这篇关于JavaScript WebGL 图片透明处理的文章就介绍到这了,更多相关js图片透明处理内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!