Blend 混合模式

Blend 混合模式混合常见的混合类型ShaderLab的混合命令当片元着色器产生一个颜色时,可以选择与颜色缓冲中的颜色进行混合。混合与两个参数有关:源颜色(sourcecolor)和目标颜色(destinationcolor)。源颜色用S表示,指的是片元着色器生成的颜色值;目标颜色用D表示,指的是颜色缓冲中读取到的颜色值。将它们混合之后得到的输出颜色O会重新写入颜色缓冲区。混合是一个逐片元的操作,不可编程但是高度可配置。将源颜色S和目标颜色D通过混合等式(blendequation)进行混合后得到输出颜色

参考
韩世麟 把 PS 图层混合模式理解到这个程度,就算是入门了
Wiki Blend_modes
冯乐乐 《Unity Shader入门精要》
Ps混合模式的计算原理,宇宙最穷的进阶笔记

混合

在这里插入图片描述

图层混合模式规则

  1. 0 – 255要换算到0 – 1区间
  2. 逐像素,分通道

常见的混合类型

为叙述方便,定义原图或下层的颜色为底色A,画笔或上层颜色为绘图色B,混合之后的颜色为最终色C

各种模式

正常透明度混合(Normal)

默认状态,最终色与绘图色相同。当上层有透明度时混合方式如下:

C = A ∗ ( 1 − B . a l p h a ) + B ∗ B . a l p h a C = A *(1 – B.alpha) + B * B.alpha C=A(1B.alpha)+BB.alpha

溶解(Dissolve)

从两个图层中随机取得像素,上层图像的不透明度越高所占权重越高
在这里插入图片描述

变暗系

变暗(Darken)

选取两个颜色中较暗的颜色作为最终色

C = m i n ( A , B ) C = min(A, B) C=min(A,B)

正片叠底(Multiply)

将两种颜色相乘

C = A B C = A B C=AB

  • 去白留黑
  • 满足交换律,上下不影响结果
  • 可使用黑白线稿与原图相乘来获得描边
  • 模拟暗房中两张正片(所见即所得的底片)重叠的效果

颜色加深(Color Burn)

将底层反相后除以顶层,再反相

C = A − ( 1 − A ) ( 1 − B ) / B = 1 − ( 1 − A ) / B C = A – (1 – A) (1 – B) / B=1-(1-A)/B C=A(1A)(1B)/B=1(1A)/B

  • 将纯黑图层至于上方时,图像不会变成全黑,会出现失真现象(分母不能出现0,ps中的输入值最大为251,因此底图的过曝部分不会受到影响)
    在这里插入图片描述

线性加深

将两个图层相加后减去1,等价于两个图层取反相加再取反(线性减淡各项取反)

C = A + B − 1 = 1 − ( ( 1 − A ) + ( 1 − B ) ) C = A + B – 1=1-((1-A)+(1-B)) C=A+B1=1((1A)+(1B))

变亮系

变亮(Lighten)

选取两个颜色中较亮的作为最终色

C = m a x ( A , B ) C = max(A, B) C=max(A,B)

滤色(Screen)

将两种颜色取反之后相乘,再取反
C = 1 − ( 1 − A ) ( 1 − B ) C = 1 – (1 – A) (1 – B) C=1(1A)(1B)

  • 去黑留白

  • 滤色之后的图像会提亮且绝对不会过曝(结果必小于1),能够保留更多细节

  • A的反相与B的反相相乘等于C的反相,可看作是正片叠底的逆运算(各项均取反) ( 1 − C ) = ( 1 − A ) ( 1 − B ) (1-C)=(1-A)(1-B) (1C)=(1A)(1B)

  • 两张相同的图片进行滤色约等于将中间亮度提高到75%的曲线
    在这里插入图片描述

  • 模拟在暗房中将两张负片重叠后进行曝光的效果

颜色减淡(Color Dodge)

底层除以反相后的顶层

C = A + ( A ∗ B ) / ( 1 − B ) = A / ( 1 − B ) C = A + (A * B) / (1 – B)=A/(1-B) C=A+(AB)/(1B)=A/(1B)

  • 将纯白图层至于顶层后不会变成全白,会出现失真
    在这里插入图片描述

线性减淡(Linear Dodge / Additive)

两图层相加

C = A + B C = A + B C=A+B

饱和度系

叠加(overlay)

根据底色是否大于50%中灰来决定使用正片叠底滤色,使暗的变暗、亮的变亮,提高对比度

{ C = 2 A B , i f A < 0.5 C = 1 − 2 ( 1 − A ) ( 1 − B ) , o t h e r w i s e \begin{cases} C=2AB, & ifA<0.5\\ C=1-2(1-A)(1-B),&otherwise\\ \end{cases} {
C=2AB,C=12(1A)(1B),ifA<0.5otherwise

  • 抠中灰,留黑白
  • 对应函数曲线如下图,可以看出当图片叠加它自己时等效于如下图的曲线,亮部变亮、暗部变暗以提高对比度
    在这里插入图片描述

强光(Hard Light)

公式与叠加模式相同,但是叠加是根据底色来判断,强光则是根据绘图色与50%中灰的关系来判断使用正片叠底还是滤色

{ C = 2 A B , i f B < 0.5 C = 1 − 2 ( 1 − A ) ( 1 − B ) , o t h e r w i s e \begin{cases} C=2AB, & ifB<0.5\\ C=1-2(1-A)(1-B),&otherwise\\ \end{cases} {
C=2AB,C=12(1A)(1B),ifB<0.5otherwise

柔光(Soft Light)

根据绘图色的明暗来决定提亮还是变暗,原理与强光相同,曲线相比于强光更加柔和

{ C = 2 A B + A 2 ( 1 − 2 B ) , i f B < 0.5 C = 2 A ( 1 − B ) + A ( 2 B − 1 ) , o t h e r w i s e \begin{cases} C=2AB+A^2(1-2B), & ifB<0.5\\ C=2A(1-B)+\sqrt{A}(2B-1),&otherwise\\ \end{cases} {
C=2AB+A2(12B),C=2A(1B)+A
(2B1),
ifB<0.5otherwise

  • 柔光与叠加的曲线对比
    在这里插入图片描述

叠加的上下图层*

ps中对混合模式常用的操作是在原图上方增加一个图层作为控制图层,从直觉上来判断是对上方图层的操作影响了下方图层。

在这种方式下,使用黑色笔刷在控制图层上进行涂抹时,混合之后的图像并不会变成纯黑色,与公式中两倍的正片叠底/两倍的滤色不匹配。
在这里插入图片描述
分析公式可以得知,叠加的控制层应该在下方,即下方颜色与中灰的关系决定最终图像是变亮还是变暗。

将控制图层至于下方时,可以看到最终效果符合公式定义。
在这里插入图片描述
因此许多人对图层混合的理解其实是错误的。使用传统的操作方法可能会出现灰度突变的问题。

下图中使用上方图层作为控制层,用黑色笔刷进行加深之后,能看到中间有一道明显的分界线。因为实际上的控制层在下方,因此下图中接近中灰的位置会进行判断,左侧使用的正片叠底而右侧使用了滤色。
而上方的图层是被改变的图层,左侧的纯黑经过正片叠底运算之后依旧是纯黑,并不会受影响。但是右边的纯黑会受到滤色的影响而迅速变亮。这就形成了中灰位置的分界线。
在这里插入图片描述但是反过来,这种特性也能够起到保留边界的作用。

下图中左侧的墙壁亮度小于50%,右侧亮度大于50%,因此中间的分界线得到了非常清晰的保留。
在这里插入图片描述
将调整图层至于上方的传统做法虽然与实际原理不符,但是不代表一定是错误的用法。毕竟根据只要它看起来是对的那么它就是对的的原则,能够得到想要的效果的方法就是最好的方法。实际应用中应当根据实际的需求来决定,切忌教条化。

Unity中的颜色混合

混合操作发生于光栅化阶段最后的逐片元操作中,透明度测试之后
在这里插入图片描述

渲染顺序

在开启深度写入的情况下,物体背后的其他物体会在深度测试中被剔除,导致无法通过半透明表面看到后边的物体,因此半透明物体的渲染需要关闭深度写入。
因为半透明物体的渲染需要关闭深度写入,所以半透明物体的渲染顺序非常重要。

渲染引擎一般都会先对物体进行排序,再渲染。常用的方法为:

  1. 先渲染所有不透明物体,并开启它们的深度测试与深度写入。
  2. 把半透明物体按它们距离摄像机的远近进行排序,然后按照从后往前的顺序渲染这些半透明物体,并开启它们的深度测试,关闭深度写入。

但是以上面的方法进行渲染还是会出现一些问题。由于深度缓冲区中的值是像素级别的,排序时却是对物体进行排序,这就会导致有些物体之间出现穿插产生了循环重叠的现象时无法得到正确的渲染结果。
在这里插入图片描述

上图中三个循环重叠的物体无法得到正确的渲染结果。这种情况需要通过分割网格的方法来解决。

Unity中解决渲染顺序问题提供的方案是渲染队列(render queue)。使用SubShader的Queue标签来决定模型归属于哪个队列。Unity内部使用一系列整数索引来表示每个渲染队列,且索引号越小表示越早被渲染。

名称 队列索引号 描述
Background 1000 这个渲染队列会在任何其他队列之前被渲染,通常使用该队列来渲染那些需要绘制在背景上的物体
Geometry 2000 默认的渲染队列,大多数物体包括不透明物体使用这个队列。
AlphaTest 2450 需要透明度测试的物体使用这个队列。在Unity 5中它从Geometry队列中被单独分离出来,这是因为在所有不透明物体渲染之后再渲染它们会更加高效
Transparent 3000 这个队列中的物体会在所有 Geometry 和 AlphaTest 物体渲染后再按从后往前的顺序进行渲染。任何使用了透明度混合的物体都应该使用该队列
Overlay 4000 该队列用于实现一些叠加效果。任何需要在最后渲染的物体都应使用该队列

ShaderLab的混合命令

当片元着色器产生一个颜色时,可以选择与颜色缓冲中的颜色进行混合。混合与两个参数有关:源颜色(source color)目标颜色(destination color)。源颜色用S表示,指的是片元着色器生成的颜色值;目标颜色用D表示,指的是颜色缓冲中读取到的颜色值。将它们混合之后得到的输出颜色O会重新写入颜色缓冲区。

混合是一个逐片元的操作,不可编程但是高度可配置。将源颜色S和目标颜色D通过混合等式(blend equation) 进行混合后得到输出颜色O。进行混合时需要使用两个混合等式:一个用于混合RGB通道,一个用于混合A通道。

设置混合状态状态实际上设置的是混合等式中的操作因子。默认状态下的操作为加操作,因此通常需要设置的是混合因子。设置2个因子,RGB和A将以相同的方式进行混合;设置4种因子,RGB和A将以各自的方式进行混合。

命令 描述
Blend SrcFactor DstFactor 开启混合,设置混合因子,源颜色乘以SrcFactor,目标颜色乘以DstFactor,之后将两者相加再存入颜色缓冲中
Blend SrcFactor DstFactor,
SrcFactorA DstFactorA
除使用不同的因子来混合透明通道外其余与上边相同

混合公式:

O r g b = S r c F a c t o r × S r g b + D s t F a c t o r × D r g b O a = S r c F a c t o r A × S a + D s t F a c t o r A × D a O_{rgb}=SrcFactor\times S_{rgb}+DstFactor\times D_{rgb} \\ O_{a}=SrcFactorA\times S_{a}+DstFactorA\times D_{a} Orgb=SrcFactor×Srgb+DstFactor×DrgbOa=SrcFactorA×Sa+DstFactorA×Da

ShaderLab 中的混合因子

参数 描述
One 因子为1
Zero 因子为0
SrcColor 因子为源颜色值。当用于混合RGB的混合等式时,使用SrcColor的RGB分量作为混合因子;当用于混合A的混合等式时,使用SrcColor的A分量作为混合因子
SrcAlpha 因子为源颜色的透明度值(A通道)
DstColor 因子为目标颜色值。当用于混合RGB的混合等式时,使用DstColor的RGB分量作为混合因子;当用于混合A的混合等式时,使用DstColor的A分量作为混合因子
DstAlpha 因子为目标颜色的透明度值(A通道)
OneMinusSrcColor 因子为(1-源颜色)。当用于混合RGB的混合等式时,使用结果的RGB分量作为混合因子;当用于混合A的混合等式时,使用结果的A分量作为混合因子
OneMinusSrcAlpha 因子为(1-源颜色的透明度值)
OneMinusDstColor 因子为(1-目标颜色)。当用于混合RGB的混合等式时,使用结果的RGB分量作为混合因子;当用于混合A的混合等式时,使用结果的A分量作为混合因子
OneMinusDstAlpha 因子为(1-目标颜色的透明度值)

使用上边的指令进行设置时,RGB通道的混合因子和A通道的混合因子都是一样的。有时我们希望可以使用不同的参数混合A通道,这时就可以利用Blend SrcFactor DstFactor,SrcFactorA DstFactorA 指令。例如,如果我们想要在混合后输出颜色的透明度就是源颜色的透明度,可以使用下面的命令:

Blend SrcAlpha OneMinusSrcAlpha, One Zero

混合操作

上面涉及的混合等式都是将源颜色和目标颜色与对应的混合因子相乘后的结果相加作为输出颜色。使用ShaderLab的BlendOp BlendOperation命令可以设置其他的混合操作。

操作 描述
Add 将混合后的源颜色与目标颜色相加。默认的混合操作。等式为:
O r g b = S r c F a c t o r × S r g b + D s t F a c t o r × D r g b O_{rgb}=SrcFactor\times S_{rgb}+DstFactor\times D_{rgb} Orgb=SrcFactor×Srgb+DstFactor×Drgb
O a = S r c F a c t o r A × S a + D s t F a c t o r A × D a O_{a}=SrcFactorA\times S_{a}+DstFactorA\times D_{a} Oa=SrcFactorA×Sa+DstFactorA×Da
Sub 用混合后的源颜色减去混合后的目标颜色。等式为:
O r g b = S r c F a c t o r × S r g b − D s t F a c t o r × D r g b O_{rgb}=SrcFactor\times S_{rgb}-DstFactor\times D_{rgb} Orgb=SrcFactor×SrgbDstFactor×Drgb
O a = S r c F a c t o r A × S a − D s t F a c t o r A × D a O_{a}=SrcFactorA\times S_{a}-DstFactorA\times D_{a} Oa=SrcFactorA×SaDstFactorA×Da
RevSub 用混合后的目标颜色减去混合后的源颜色。等式为:
O r g b = D s t F a c t o r × S r g b − S r c F a c t o r × D r g b O_{rgb}=DstFactor\times S_{rgb}-SrcFactor\times D_{rgb} Orgb=DstFactor×SrgbSrcFactor×Drgb
O a = D s t F a c t o r A × S a − S r c F a c t o r A × D a O_{a}=DstFactorA\times S_{a}-SrcFactorA\times D_{a} Oa=DstFactorA×SaSrcFactorA×Da
Min 使用源颜色和目标颜色中较小的值作为最终结果,逐分量比较。等式为:
O r g b a = ( m i n ( S r , D r ) , m i n ( S g , D g ) , m i n ( S b , D b ) , m i n ( S a , D a ) ) O_{rgba}=(min(S_r, D_r),min(S_g, D_g),min(S_b, D_b),min(S_a, D_a)) Orgba=(min(Sr,Dr),min(Sg,Dg),min(Sb,Db),min(Sa,Da))
Max 使用源颜色和目标颜色中较大的值作为最终结果,逐分量比较。等式为:
O r g b a = ( m a x ( S r , D r ) , m a x ( S g , D g ) , m a x ( S b , D b ) , m a x ( S a , D a ) ) O_{rgba}=(max(S_r, D_r),max(S_g, D_g),max(S_b, D_b),max(S_a, D_a)) Orgba=(max(Sr,Dr),max(Sg,Dg),max(Sb,Db),max(Sa,Da))
其他逻辑操作 仅支持D3D11.1,详见官方文档

常见的混合类型

通过混合操作和混合类型的组合,可以得到一些类似Photoshop混合模式中的混合效果

//正常(Normal),即透明度混合
Blend SrcAlpha OneMinusSrcAlpha

//柔和相加(Soft Additive)
Blend OneMinusDstColor One

//正片叠底(Multiply)
Blend DstColor Zero

//变暗(Darken)
BlendOp Min
Blend One One

//变亮(Lighten)
BlendOp Max
Blend One One

//滤色(Screen) C = 1-(1-A)(1-B) = A+B-AB = A+B(1-A) = A(1-B)+B
Blend OneMinusDstColor One
//等同于
Blend One OneMinusSrcColor 

//线性减淡
Blend One One

在这里插入图片描述

今天的文章Blend 混合模式分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:http://bianchenghao.cn/7333.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注