3-图层混合

当我们希望通过 Shader 给图片增加不一样的滤镜效果时,图层混合模式将非常适用。图层混合模式给设计师提供了丰富的图层混合效果,大大减少他们对颜色的操作,更自然地混合不同图层。

图层混合

图层

就是PS中的“图层”,例如有以下两个图层A,B:

其中,当前选中层(Active Layer)为A层,或称 “混合色(Blend Color)”。下层(Background Layer)为B层,或称“基色(Base Color)”。两者混合得到“结果色(Result Color)“。

混合模式基本原理

取混合色A层任意一个像素a[R1, G1, B1],与基色B层对应位置的像素b[R2, G2, B2]进行某种运算,得到混合色像素c[R3, G3, B3]。

例如在PS中,默认的图层混合模式是“正常”,在不透明度为100%时,有

R1 正常 R2 = R1
G1 正常 G2 = G1
B1 正常 B2 = B1

那么结果就是只有A层的图片能被看到,看不到B层。

混合模式分类

一般系

正常(Normal):编辑或绘制每个像素,使其成为结果色。这是默认模式。(在处理位图图像或索引颜色图像时,“正常”模式也称为阈值。)

溶解(Dissolve):编辑或绘制每个像素,使其成为结果色。但是,根据任何像素位置的不透明度,结果色由基色或混合色的像素随机替换。

变暗系

变暗(Darken):查看每个通道中的颜色信息,并选择基色或混合色中较暗的颜色作为结果色。将替换比混合色亮的像素,而比混合色暗的像素保持不变。

正片叠底(Multiply):查看每个通道中的颜色信息,并将基色与混合色进行正片叠底。结果色总是较暗的颜色。任何颜色与黑色正片叠底产生黑色。任何颜色与白色正片叠底保持不变。当您用黑色或白色以外的颜色绘画时,绘画工具绘制的连续描边产生逐渐变暗的颜色。这与使用多个标记笔在图像上绘图的效果相似。

颜色加深(Color Burn):查看每个通道中的颜色信息,并通过增加二者之间的对比度使基色变暗以反映出混合色。与白色混合后不产生变化。

线性加深(Linear Burn):查看每个通道中的颜色信息,并通过减小亮度使基色变暗以反映混合色。与白色混合后不产生变化。

深色(Darker Color):比较混合色和基色的所有通道值的总和并显示值较小的颜色。“深色”不会生成第三种颜色(可以通过“变暗”混合获得),因为它将从基色和混合色中选取最小的通道值来创建结果色。

变亮系

变亮(Lighten):查看每个通道中的颜色信息,并选择基色或混合色中较亮的颜色作为结果色。比混合色暗的像素被替换,比混合色亮的像素保持不变。

滤色(Screen):查看每个通道的颜色信息,并将混合色的互补色与基色进行正片叠底。结果色总是较亮的颜色。用黑色过滤时颜色保持不变。用白色过滤将产生白色。此效果类似于多个摄影幻灯片在彼此之上投影。

颜色减淡(Color Dodge):查看每个通道中的颜色信息,并通过减小二者之间的对比度使基色变亮以反映出混合色。与黑色混合则不发生变化。

线性减淡/添加(Linear Dodge):查看每个通道中的颜色信息,并通过增加亮度使基色变亮以反映混合色。与黑色混合则不发生变化。

浅色(Lighter Color):比较混合色和基色的所有通道值的总和并显示值较大的颜色。“浅色”不会生成第三种颜色(可以通过“变亮”混合获得),因为它将从基色和混合色中选取最大的通道值来创建结果色。

对比系

让亮的更亮,暗的更暗。

叠加(Overlay):对颜色进行正片叠底或过滤,具体取决于基色。图案或颜色在现有像素上叠加,同时保留基色的明暗对比。不替换基色,但基色与混合色相混以反映原色的亮度或暗度。

柔光(Soft Light):使颜色变暗或变亮,具体取决于混合色。此效果与发散的聚光灯照在图像上相似。如果混合色(光源)比 50% 灰色亮,则图像变亮,就像被减淡了一样。如果混合色(光源)比 50% 灰色暗,则图像变暗,就像被加深了一样。使用纯黑色或纯白色上色,可以产生明显变暗或变亮的区域,但不能生成纯黑色或纯白色。

强光(Hard Light):对颜色进行正片叠底或过滤,具体取决于混合色。此效果与耀眼的聚光灯照在图像上相似。如果混合色(光源)比 50% 灰色亮,则图像变亮,就像过滤后的效果。这对于向图像添加高光非常有用。如果混合色(光源)比 50% 灰色暗,则图像变暗,就像正片叠底后的效果。这对于向图像添加阴影非常有用。用纯黑色或纯白色上色会产生纯黑色或纯白色。

亮光(Vivid Light):通过增加或减小对比度来加深或减淡颜色,具体取决于混合色。如果混合色(光源)比 50% 灰色亮,则通过减小对比度使图像变亮。如果混合色比 50% 灰色暗,则通过增加对比度使图像变暗。

线性光(Linear Light):通过减小或增加亮度来加深或减淡颜色,具体取决于混合色。如果混合色(光源)比 50% 灰色亮,则通过增加亮度使图像变亮。如果混合色比 50% 灰色暗,则通过减小亮度使图像变暗。

点光(Pin Light):根据混合色替换颜色。如果混合色(光源)比 50% 灰色亮,则替换比混合色暗的像素,而不改变比混合色亮的像素。如果混合色比 50% 灰色暗,则替换比混合色亮的像素,而比混合色暗的像素保持不变。这对于向图像添加特殊效果非常有用。

实色混合(Hard Mix):将混合颜色的红色、绿色和蓝色通道值添加到基色的 RGB 值。如果通道的结果总和大于或等于 255,则值为 255;如果小于 255,则值为 0。因此,所有混合像素的红色、绿色和蓝色通道值要么是 0,要么是 255。此模式会将所有像素更改为主要的加色(红色、绿色或蓝色)、白色或黑色。

负片系

差值(Difference):查看每个通道中的颜色信息,并从基色中减去混合色,或从混合色中减去基色,具体取决于哪一个颜色的亮度值更大。与白色混合将反转基色值;与黑色混合则不产生变化。

排除(Exclusion):创建一种与“差值”模式相似但对比度更低的效果。与白色混合将反转基色值。与黑色混合则不发生变化。

相消系

减去(Subtract):查看每个通道中的颜色信息,并从基色中减去混合色。在 8 位和 16 位图像中,任何生成的负片值都会剪切为零。

划分(Divide):查看每个通道中的颜色信息,并从基色中划分混合色。

HSL系

色相(Hue):用基色的明亮度和饱和度以及混合色的色相创建结果色。

饱和度(Saturation):用基色的明亮度和色相以及混合色的饱和度创建结果色。在无 (0) 饱和度(灰度)区域上用此模式绘画不会产生任何变化。

颜色(Color):用基色的明亮度以及混合色的色相和饱和度创建结果色。这样可以保留图像中的灰阶,并且对于给单色图像上色和给彩色图像着色都会非常有用。

明度(Luminosity):用基色的色相和饱和度以及混合色的明亮度创建结果色。此模式创建与“颜色”模式相反的效果。

混合模式的实现

混合模式的相关计算公式如下:

接下来看看片段着色器怎么写,这是它的大致框架:

#version 330 core
out vec4 FragColor;

in vec2 TexCoord;

uniform sampler2D baseLayerImg;
uniform sampler2D blendLayerImg;
uniform vec3 blendLayerColor;
uniform bool useImageBlend;

uniform float opacity;
uniform int blendMode;

// 0 - Normal 正常
vec3 blendNormal(vec3 base, vec3 blend) {
	return blend;
}
// ...

vec3 blend(int mode, vec3 baseLayer, vec3 blendLayer) 
{
	switch (mode)
	{
		case 0: return blendNormal(baseLayer, blendLayer);
		// ......
	}
	return baseLayer;
}

void main()
{
	vec3 baseLayer = texture(baseLayerImg, TexCoord).rgb;
	vec3 blendLayer = useImageBlend ? texture(blendLayerImg, TexCoord).rgb : blendLayerColor;
	vec3 blendResult = blend(blendMode, baseLayer, blendLayer);

	// 透明度处理
	float alpha = useImageBlend ? texture(blendLayerImg, TexCoord).a : 1.0;
	blendResult = blendResult * (alpha * opacity) + baseLayer * (1.0 - opacity * alpha);

	FragColor = vec4(blendResult, 1.0);
}

根据混合模式的实现原理,分为baseLayerblendLayer两层。前者作为基本图层,接受一张图片作为输入;后者作为混合图层,接受纯色/图片作为输入。有了两个图层后就能进行混合操作了,可以按公式实现上面的各种混合操作,得到混合后的结果blendResult。在输出最终结果之前,需要对其进行透明度处理,通过对结果进行混合插值操作,让最终结果的透明度设置正确,从而显示出正确的结果。

参考资料

  • Shader 中的颜色混合模式 - 掘金 (juejin.cn)
  • jamieowen/glsl-blend: glsl photoshop blending modes. glslify formatted. (github.com)
  • 一篇文章彻底搞清PS混合模式的原理 - 知乎 (zhihu.com)