JavaScript WebGL 图片透明处理详解:Alpha 通道与混合模式

作者:页面旅途

时间:2026-10-24

浏览:513

本文详细解析 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 分量
ZERO0000
ONE1111
SRC_COLORS.rS.gS.bS.a
ONE_MINUS_SRC_COLOR(1-S.r)(1-S.g)(1-S.b)(1-S.a)
DST_COLORD.rD.gD.bD.a
ONE_MINUS_DST_COLOR(1-D.r)(1-D.g)(1-D.b)(1-D.a)
SRC_ALPHAS.aS.aS.aS.a
ONE_MINUS_SRC_ALPHA(1-S.a)(1-S.a)(1-S.a)(1-S.a)
DST_ALPHAD.aD.aD.aD.a
ONE_MINUS_DST_ALPHA(1-D.a)(1-D.a)(1-D.a)(1-D.a)

此外,还可配合 方法使用的常量取值如下:

常量R 分量G 分量B 分量A 分量
CONSTANT_COLORredgreenbluealpha
ONE_MINUS_CONSTANT_COLOR(1-red)(1-green)(1-blue)(1-alpha)
CONSTANT_ALPHAalphaalphaalphaalpha
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_SATURATEmin(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图片透明处理内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章