详见《Unity Shader入门精要》第八章
1. 混合
1.1. 定义
混合Blend 就是把两种颜色混在一起。具体就是把某一像素位置原来颜色和将要会上去的颜色,通过某种方式或者算法混在一起,从而实现新的效果。
例如:PS内的正片叠底,叠加都属于混合模式的一种。
虽然所有图形 API 和硬件都支持混合功能,但对某些混合操作的支持较为有限。
启用混合会禁用 GPU 上的一些优化(主要是删除隐藏的表面/Early-Z),这些优化会增加 GPU 帧时间。
混合Blend 就是把两种颜色混在一起。具体就是把某一像素位置原来颜色和将要会上去的颜色,通过某种方式或者算法混在一起,从而实现新的效果。
例如:PS内的正片叠底,叠加都属于混合模式的一种。
虽然所有图形 API 和硬件都支持混合功能,但对某些混合操作的支持较为有限。
启用混合会禁用 GPU 上的一些优化(主要是删除隐藏的表面/Early-Z),这些优化会增加 GPU 帧时间。
1.2. 类型
1.3. 混合等式
finalValue = sourceFactor * sourceValue operation destinationFactor * destinationValue
在这个等式中:
finalValue
是 GPU 写入目标缓冲区的值。sourceFactor
在 Blend 命令中定义。sourceValue
是片元着色器输出的值,也就是当前透明物体的颜色。operation
是混合操作。destinationFactor
在 Blend 命令中定义。destinationValue
是目标缓冲区中现有的值,也就是透明物体后的背景颜色。
混合模式控制的就是源因子SrcFactor和目标因子DstFactor,在脚本里会看到的就是 :
Blend SrcFactor DstFactor
1.4. BlendOp 混合模式的操作符Operation
常见的:
指定 Blend 命令使用的混合操作。要使该命令生效,在同一个 Pass 代码块(如果该命令在 Pass 代码块中)或 SubShader 代码块(如果该命令在 SubShader 代码块中)中还必须有一个 BlendOp命令。
Shader "Examples/CommandExample"
{
SubShader
{
// 。。。
Pass
{
// 为此通道启用减法混合
Blend SrcAlpha One
BlendOp Sub
// 。。。
}
}
}
1.5. Unity对于混合自带的枚举
混合模式和深度开关:
举例:
1.6. 小结
常用混合命令及效果:
1.7. 实现方式
代码
1.
Shader "Custom/BlendMode"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Main Texture", 2D) = "white" {}
[Enum(UnityEngine.Rendering.BlendOp)] _BlendOp("Blend Option",Float)=0
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Source Blend",Float)=0
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Destination Blend",Float)=0
[Enum(Off,0,On,1)] _ZWriteMode("ZWrite Mode",Float)=1
}
SubShader
{
Tags{"RenderType"="Transparent""Queue"="Transparent"}
ZWrite[_ZWriteMode]
Blend [_SrcBlend][_DstBlend]
BlendOp [_BlendOp]
Pass
{
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
float _BlendOp;
float _SrcBlend;
float _DstBlend;
float _ZWriteMode;
struct a2v
{
float4 vertex:POSITION;
float2 uv:TEXCOORD0;
};
struct v2f
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
};
v2f vert(a2v v)
{
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.uv=TRANSFORM_TEX(v.uv,_MainTex);
return o;
}
fixed4 frag(v2f i):SV_Target
{
return tex2D(_MainTex,i.uv)*_Color;
}
ENDCG
}
}
FallBack "Diffuse"
}
2.
Shader "Custom/PSBlendMode"
{
Properties
{
[IntRange] _ModeID("Mode ID",Range(0,26))=0
_SrcColor("Color",Color)=(1,1,1,1)
_DstColor("Color",Color)=(1,1,1,1)
_SrcTex ("Source Texture", 2D) = "white" {}
_DstTex ("Destination Texture", 2D) = "white" {}
[HideInInspector] _IDChoose("",float)=0
}
SubShader
{
Tags{"RenderType"="Opaque""Queue"="Geometry"}
ZWrite On
Blend Off
Pass
{
CGPROGRAM
#include "UnityCG.cginc"
#include "PhotoshopBlendMode.cginc"
#pragma vertex vert
#pragma fragment frag
fixed4 _SrcColor;
fixed4 _DstColor;
sampler2D _SrcTex;
sampler2D _DstTex;
float4 _SrcTex_ST;
float4 _DstTex_ST;
float _IDChoose;
float _ModeID;
struct a2v
{
float4 vertex:POSITION;
float2 uv:TEXCOORD0;
};
struct v2f
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
};
v2f vert(a2v v)
{
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.uv=TRANSFORM_TEX(v.uv,_DstTex);
return o;
}
fixed4 frag(v2f i):SV_Target
{
fixed4 Src=tex2D(_SrcTex,i.uv)*_SrcColor;
fixed4 Dst=tex2D(_DstTex,i.uv)*_DstColor;
return fixed4(OutPutMode(Src,Dst,_ModeID),1);
}
ENDCG
}
}
}
正常混合
变暗
正片叠底
滤色
2. 剔除
- 法线剔除:也被称为背面消隐,根据法线朝向判断哪个面被剔除掉。可以用来控制是否双面渲染。
语法:Cull Off/ Front / Back
- 面裁剪:clip函数会将参数小于0直接在片元着色器直接丢弃,常用于制作溶解,裁剪等效果。
语法:clip();默认会切掉0的部分。
Shader "Custom/ClipMode"
{
Properties
{
_CutOut("Cut Out",Range(0,1))=0.5
_MainTex ("Main Texture", 2D) = "white" {}
[Enum(UnityEngine.Rendering.CullMode)] _CullMode("Cull Mode",Float)=0
}
SubShader
{
Tags{"RenderType"="Transparent""Queue"="AlphaTest"}
Cull [_CullMode]
LOD 100
Pass
{
CGPROGRAM
#include "UnityCG.cginc"
#pragma multi_compile_fog
#pragma vertex vert
#pragma fragment frag
float _CutOut;
sampler2D _MainTex;
float4 _MainTex_ST;
float _CullMode;
struct a2v
{
float4 vertex:POSITION;
float2 uv:TEXCOORD0;
};
struct v2f
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
UNITY_FOG_COORDS(1)
};
v2f vert(a2v v)
{
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.uv=TRANSFORM_TEX(v.uv,_MainTex);
return o;
}
fixed4 frag(v2f i):SV_Target
{
fixed4 col=tex2D(_MainTex,i.uv);
UNITY_APPLY_FOG(i.fogCoord,col);
clip(col.a-_CutOut);
return col;
}
ENDCG
}
}
FallBack "Diffuse"
}
3. 作业
效果: