ShaderLab:Blend 的理解和应用
2022-05-06 本文已影响0人
子夜书案
概括:

看上图,会发现 Blending 发生在着色流程的最后。片段着色,
Alptha Test
完成后,如何和 ColorBuffer
中已有颜色混合,就是 Bland
指令需要做的事情。
应用:
Blend 指令可以在 Pass
内部,用来决定这一个 Pass
的渲染状态;也可以放在 SubShader
,用来决定其所有 Pass 的渲染状态。
Blending 方程式为:
finalValue = sourceFactor * sourceValue operation destinationFactor * destinationValue
方程式中各变量的含义:
-
finalValue
is the value that the GPU writes to the destination buffer.
GPU 写进目标缓存的值 -
sourceFactor
is defined in the Blend command.
由 Blend 指令定义 -
sourceValue
is the value output by the fragment shader.
片段着色器输出的值 -
operation
is the blending operation.
Blend 操作,可用的指令有:值 含义 Add buffer_value
+片段着色器输出值
Sub 片段着色器输出值
-buffer_value
RevSub buffer_value
-片段着色器输出值
Min Math.Min( 片段着色器输出值
,buffer_value
)Max Math.Max( 片段着色器输出值
,buffer_value
) -
destinationFactor
is defined in the Blend command.
由 Blend 指令定义 -
destinationValue
is the value already in the desination buffer.
目标缓存中已经存在的值
定义 | 样例 | 描述 |
---|---|---|
Blend <state> |
Blend Off |
关闭 Blend ,这是默认设置 |
Blend <render target> <state> |
Blend 1 Off |
同上,但是给定了渲染目标 |
Blend <source factor> <destination factor> |
Blend One Zero |
为默认渲染目标开启Blend |
Blend <render target> <source factor><destination factor> |
Blend 1 One Zero |
同上,但是指定了渲染目标 |
Blend <source factor RGB> <destination factor RGB>, <source factor alpha> <destination factor alpha> |
Blend One Zero,Zero One |
为默认渲染目标开启Blend,为 RGB 和 alpha 值设置单独的混合因子 |
Blend <render target> <source factor RGB> <destination factor RGB>, <source factor alpha> <destination factor alpha> |
Blend 1 One Zero,Zero One | 同上,但给定了渲染目标 |
参数可能的值:
名称 | 值 | 含义 |
---|---|---|
render target | int[0-7] | 渲染目标编号,从0到7 |
state | Off |
关闭 blending |
factor | One |
输入值1,相当于直接用源值或者目标值代入公式 |
Zero |
输入值0,相当于移除源值或者目标值 | |
SrcColor |
GPU 用此输入值乘源值 | |
DestColor |
GPU 将此输入的值乘以目标值(color buffer中的值) | |
OneMinusSrcColor |
GPU 将此输入值乘以(1 - 源值) | |
OneMinusSrcAlpha |
GPU 将此输入值乘以(1 - 源值的Alpha) | |
OneMinusDstColor |
GPU 将此输入值乘以(1 - 目标值) | |
OneMinusDstAlpha |
GPU 将此输入值乘以(1 - 目标的Alpha) |
注释
- 源值:片段着色器输出的值
- 目标值:color buffer 中的当前值
常见的混合类型:
-
Blend SrcAlpha OneMinusSrcAlpha
// 传统的透明度
传统的透明度
-
Blend One OneMinusSrcAlpha
// 预乘透明度
预乘透明度
-
Blend One One
// 叠加
叠加
-
Blend OneMinusDstColor One
// 柔性叠加
柔性叠加
-
Blend DstColor Zero
// 乘
Blend DstColor Zero
-
Blend DstColor SrcColor
// 加倍乘
Blend DstColor SrcColor
测试用的Shader
Shader "Unlit/TestBlendShader"
{
Properties
{
_Color ("Main Color", Color) = (1,1,1,1)
[Header(Blending)]
// https://docs.unity3d.com/ScriptReference/Rendering.BlendMode.html
[Enum(UnityEngine.Rendering.BlendMode)]_DecalSrcBlend("_DecalSrcBlend (default = SrcAlpha)", Int) = 5 // 5 = SrcAlpha
[Enum(UnityEngine.Rendering.BlendMode)]_DecalDstBlend("_DecalDstBlend (default = OneMinusSrcAlpha)", Int) = 10 // 10 = OneMinusSrcAlpha
}
SubShader
{
Tags { "RenderType"="Opaque" }
Blend[_DecalSrcBlend][_DecalDstBlend]
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 normal : NORMAL;
};
struct v2f
{
float2 wnormal : NORMAL;
float4 vertex : SV_POSITION;
};
fixed4 _Color;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.wnormal = UnityObjectToWorldNormal((v.normal,1));
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return _Color * (dot(normalize(_WorldSpaceLightPos0.xyz),i.wnormal) * 0.5 + 0.5);
}
ENDCG
}
}
}