blending与composite的区别及Canvas图层叠加色值计算规则咨询
关于blending与composite的差异及Canvas叠加色值计算问题
我当前问题涉及blending和composite两个术语,暂不明确二者的具体差异。
现有两个Canvas元素D、C,各元素RGBA参数如下:
- D的RGBA值为:( 44 , 0 , 22 , 0.70 )
- C的RGBA值为:( 134 , 55 , 0 , 0.35 )
- 页面body的RGBA值为:( 122 , 200 , 0 , 1.00 )
绘制顺序为先绘制D,后绘制C,我需要明确二者相交区域的色值计算逻辑。
我目前推测计算逻辑近似如下函数:
gl.blendFuncSeparate(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA,gl.ONE,gl.ONE_MINUS_SRC_ALPHA);
// color(RGB) = (sourceColor * srcRGB) + (destinationColor * dstRGB)
// color(A) = (sourceAlpha * srcAlpha) + (destinationAlpha * dstAlpha)
但我实测发现D、C单独显示区域以及D覆盖C的区域的Alpha值始终为1,既然Alpha恒为1,为什么还需要使用blendFuncSeparate?
我已通过Gimp记录了D单独显示、C单独显示、D覆盖C三个区域的色值,对应截图如下:
问题复现代码如下:
CSS代码
#c { position:absolute; top:50px; left:150px; background-color: rgba(134,55,0,0.35); } #d { position:absolute; top:0px; left:0px; background-color: rgba(44,0,22,0.7); } #namec { position:absolute; top:100px; left:350px; font-size: xx-large; color:white; } #named { position:absolute; top:50px; left:50px; font-size: xx-large; color:white; } body,html { background-color: rgb(122,200,0); }
HTML代码
<canvas id="d"></canvas> <canvas id="c"></canvas> <div id='named'>D</div> <div id='namec'>C</div>
术语差异说明
- blending(混合) 特指在同一渲染目标上,将新绘制的源像素和已存在的目标像素,按照指定的权重公式计算得到最终像素的过程,核心是像素RGBA的数值运算规则。
- composite(合成) 是更宽泛的概念,指多个图层堆叠时的最终视觉效果计算,blending是合成流程中处理RGBA数值的核心步骤之一,合成还包含图层裁剪、蒙版、混合模式选择等额外逻辑。
相交区域色值计算逻辑
你推测的混合函数是正确的,Canvas默认的混合逻辑就是基于blendFuncSeparate的预乘Alpha混合,计算分两步:
- 两个Canvas图层的混合(D为底,C为源)
先计算叠加后的图层RGBA:- Alpha通道计算:
A = C_A * 1 + D_A * (1 - C_A) = 0.35 + 0.7 * 0.65 = 0.805 - RGB通道计算(预乘Alpha后计算):
R = 134*0.35 + 44*0.7*0.65 ≈ 46.9 + 20.02 = 66.92G = 55*0.35 + 0*0.7*0.65 = 19.25B = 0*0.35 + 22*0.7*0.65 ≈ 10.01
- Alpha通道计算:
- 混合后的图层再和不透明的body背景混合
因为最终要输出到不透明的屏幕,所以会用上面得到的叠加图层再和背景混合,此时Alpha通道最终会被压缩为1:
最终RGB:R = 66.92 + 122*(1-0.805) ≈ 66.92 + 23.79 = 90.71G = 19.25 + 200*(1-0.805) ≈ 19.25 + 39 = 58.25B = 10.01 + 0*(1-0.805) ≈ 10.01
取整后就和你GIMP里测得的交叠区域色值一致。
为什么Alpha恒为1还需要用blendFuncSeparate
你看到的最终输出Alpha为1,是因为最后和不透明的页面背景混合后,透明通道被覆盖了,这不代表中间图层混合的过程不需要计算Alpha:
- 中间图层叠加时必须通过Alpha通道计算权重,才能得到正确的RGB混合结果,没有Alpha的权重计算,两个半透明图层的颜色混合会出现偏色。
- 如果后续你需要把Canvas的绘制结果导出为带透明通道的图片,或者再作为半透明图层和其他元素叠加,中间计算得到的Alpha值就会直接生效,而
blendFuncSeparate可以保证RGB和Alpha通道的混合规则独立可控,避免混合后Alpha通道计算错误。
内容的提问来源于stack exchange,提问作者oceanGermanique
相关产品推荐
相关产品推荐

