鸟语天空
ShaderLab的混合命令
post by:追风剑情 2016-10-25 20:02

      我们首先来看一下混合是如何实现的。当片元着色器产生一个颜色的时候,可以选择与颜色缓存中的颜色进行混合。这样一来,混合就和两个操作数有关:源颜色(source color)目标颜色(destination color)。源颜色,我们用S表示,指的是由片元着色器产生的颜色值;目标颜色,我们用D表示,指的是从颜色缓冲中读取到的颜色值。对它们进行混合后得到的输出颜色,我们用O表示,它会重新写入颜色缓冲中。需要注意的是,当我们谈及混合中的源颜色、目标颜色和输出颜色时,它们都包含了RGBA四个通道的值,而并非仅仅是RGB通道。

      想要使用混合,我们必须先开启它。在Unity中,当我们使用Blend(Blend Off命令除外)命令时,除了设置混合状态外也开启了混合。但是,在其他图形API中我们是需要手动开启的。例如在OpenGL中,我们需要使用glEnable(GL_BLEND)来开启混合。但在Unity中,它已经在背后为我们做了这些工作。

混合等式和参数

      混合是一个逐片元的操作,而且它不是可编程的,但却是高度可配置的。也就是说,我们可以设置混合时使用的运算操作、混合因子等来影响混合。那么,这些配置又是如何实现的呢?

现在,我们已知两个操作数:源颜色S和目标颜色D,想要得到输出颜色O就必须使用一个等式来计算。我们把这个等式称为混合等式(blend equation)。当进行混合时,我们需要使用两个混合等式:一个用于混合RGB通道,一个用于混合A通道。当设置混合状态时,我们实际上设置的就是混合等式中的操作因子。在默认情况下,混合等式使用的操作都是加操作(我们也可以使用其他操作),我们只需要再设置一下混合因子即可。由于需要两个等式(分别用于混合RGB通道和A通道),每个等式有两个因子(一个用于和源颜色相乘,一个用于和目标颜色相乘),因此一共需要4个因子。

ShaderLab中设置混合因子的命令
命令 描述
Blend SrcFactor DstFactor 开启混合,并设置混合因子。源颜色(该片元产生的颜色)会乘以SrcFactor,而目标颜色(已经存在于颜色缓存的颜色)会乘以DstFactor,然后把两者相加后再存入颜色缓冲中
Blend SrcFactor DstFactor, SrcFactorA DstFactorA
和上面几乎一样,只是使用不同的因子来混合透明通道

可以发现,第一个命令只提供了两个因子,这意味着将使用同样的混合因子来混合RGB通道和A通道,即此时SrcFactorA将等于SrcFactor,DstFactorA将等于DstFactor。下面就是使用这些因子进行加法混合时使用的混合公式
Orgb=SrcFactor×Srgb+DstFactor×Drgb
Oa=SrcFactorA×Sa+DstFactorA×Da
那么,这些混合因子可以有哪些值呢?下表给出了ShaderLab支持的几种混合因子。

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命令,即混合操作。下表给出了ShaderLab中支持的混合操作。

ShaderLab中的混合操作
操作 描述
Add 将混合后的源颜色和目标颜色相加。默认的混合操作。使用的混合等式是
Orgb=SrcFactor×Srgb+DstFactor×Drgb 
Oa=SrcFactorA×Sa+DstFactorA×Da
Sub 用混合后的源颜色减去混合后的目标颜色。使用的混合等式是
Orgb=SrcFactor×Srgb - DstFactor×Drgb 
Oa=SrcFactorA×Sa - DstFactorA×Da
RevSub 用混合后的目标颜色减去混合后的源颜色。使用的混合等式是
Orgb=DstFactor×Drgb - SrcFactor×Srgb 
Oa=DstFactorA×Da - SrcFactorA×Sa
Min 使用源颜色和目标颜色中较小的值,是逐分量比较。使用的混合等式是:
Orgba=(min(Sr, Dr), min(Sg, Dg), min(Sb, Db), min(Sa, Da))
Max 使用源颜色和目标颜色中较大的值,是逐分量比较的。使用的混合等式是
Orgba=(max(Sr, Dr), max(Sg, Dg), max(Sb, Db), max(Sa, Da))
其他逻辑操作 仅在DirectX11.1中支持

混合操作命令通常是与混合因子命令一起工作的。但需要注意的是,当使用Min或Max混合操作时,混合因子实际上是不起任何作用的,它们仅会判断原始的源颜色和目标颜色之间的比较结果

常见的混合类型

通过混合操作和混合因子命令的组合,我们可以得到一些类似Photoshop混合模式中的混合效果:
// 正常(Normal),即透明度混合
Blend SrcAlpha OneMinusSrcAlpha
// 柔和相加(Soft Additive)
Blend OneMinusDstColor One
// 正片叠底(Multiply),即相乘
Blend DstColor Zero
// 两倍相乘(2x Multiply)
Blend DstColor SrcColor
// 变暗(Darken)
BlendOp Min
Blend One One
// 变亮(Lighten)
BlendOp Max
Blend One One
// 滤色(Screen)
Blend OneMinusDstColor One
// 等同于
Blend One OneMinusSrcColor
// 线性减淡(Linear Dodge)
Blend One One

      需要注意的是,虽然上面使用Min和Max混合操作时仍然设置了混合因子,但实际上它们并不会对结果有任何影响,因为Min和Max混合操作会忽略混合因子。另一点是,虽然上面有些混合模式并没有设置混合操作的种类,但是它们默认就是使用加法操作,相当于设置了BlendOp Add。
评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容