Unity——Shader学习13——From庄懂(特效篇):AC、AB ...
第十三课(特效篇)<hr/>本课任务:
[*]特效大纲
[*]AC(AlphaCutout)
[*]AB(AlphaBlend)
[*]AD(Addtive)
[*]混合模式
[*]美术自定义混合面板
<hr/>一、特效大纲
1.特效·透
[*]AlphaCutOut(AC)
[*]AlphaBlend(AB)
[*]Additive(AD)
[*]其他混合效果
2.特效·动
[*]参数动画:面板上的参数做动画,(标量、位置、颜色、向量...)
[*]UV动画:
UV流动:一般拿UV的Offset做流动动画
UV扰动:UV做扰动+映射
序列帧动画:拿UV走序列,如1张图是3x3的九宫格,拿UV去走每一格
[*]顶点动画
顶点位置动画:下面视频中的食物动画就是用顶点位置动画实现的,不是骨骼实现的
顶点颜色动画:通常和粒子相关,粒子颜色、显示、消失等
https://www.zhihu.com/video/1433564662336389120
序列帧动画:
https://www.zhihu.com/video/1433564838043324416
序列帧动画案例:案例来源:v_xchen_v
3.特效·映射
[*]极坐标:可以制作圆形的法阵,做一些极坐标的动画
[*]屏幕坐标UV:(之前讲过)拿屏幕坐标UV采样贴图,配合UV扰动可以做出下面透明扭曲的效果
[*]透明扭曲
https://www.zhihu.com/video/1433565046320885760
<hr/>二、透明剪切·AlphaCutout(AC)(或者AlphaTest)
介绍:只有完全透明和不完全透明2种情况,无中间半透明情况,其本质是舍弃了某些片元
用途:
[*]常用于复杂轮廓,边缘明确的物体表现,如:镂空金属,裙摆边缘,特定风格的头发,树叶等。(像丝袜的网孔,写实的头发,其边缘就表达不能确了)
[*]卡通渲染表现,一般配上抗锯齿后处理+Bloom(辉光)
优点:
[*]无排序问题
缺点:
[*]边缘效果太实
[*]移动端性能较差
[*]有很强的锯齿
AC:右;AB:左
Shader代码
1.Properties声明:
_MainTex: 要带透明度的贴图
_Cutoff: 透明剪切阈值
2.SubShader Tags
Tags {
&#34;Queue&#34; = &#34;AlphaTest&#34; //渲染队列2450
&#34;IgnoreProjector&#34; = &#34;True&#34; //shader不会受到投影器(Projectors)的影响
&#34;ForceNoShadowCasting&#34; = &#34;True&#34; //关闭阴影投射
&#34;RenderType&#34; = &#34;TransparentCutout&#34;//把Shader归入到提前定义的组(这里是TransparentCutout组)
//以指明该Shader使用了透明度测试
//RenderType标签通常被用于着色器替换功能3.用clip函数对采样纹理进行透明度剪切
clip(var_MainTex.a - _Cutoff);//如果clip里面的值小于0,则剔除该片元这里我在Pass里面 使用了渲染设置 Cull Off ,关闭背面剔除
具体代码:
Shader &#34;AP1/L13/AlphaCutout&#34; {
Properties{
_MainTex (&#34;RGB:颜色 ; A:透贴&#34; , 2D) = &#34;white&#34;{}
_Cutoff(&#34;Cutoff&#34; , Range(0.0 , 1.0)) = 0.5
}
SubShader{
Tags {
&#34;Queue&#34; = &#34;AlphaTest&#34; //渲染队列2450
&#34;IgnoreProjector&#34; = &#34;True&#34; //shader不会受到投影器(Projectors)的影响
&#34;ForceNoShadowCasting&#34; = &#34;True&#34; //关闭阴影投射
&#34;RenderType&#34; = &#34;TransparentCutout&#34;//把Shader归入到提前定义的组(这里是TransparentCutout组)
//以指明该Shader使用了透明度测试
//RenderType标签通常被用于着色器替换功能
}
Pass {
Name &#34;FORWARD&#34;
Tags {
&#34;LightMode&#34; = &#34;ForwardBase&#34;
}
Cull Off //关闭背面剔除
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include &#34;UnityCG.cginc&#34;
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
uniform fixed _Cutoff;
struct VertexInput {
float4 vertex : POSITION;
float2 uv0 : TEXCOORD0;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
};
VertexOutput vert(VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv0 = v.uv0 * _MainTex_ST.xy + _MainTex_ST.zw;
return o;
}
fixed4 frag(VertexOutput i) : SV_TARGET {
fixed4 var_MainTex = tex2D(_MainTex , i.uv0);
clip(var_MainTex.a - _Cutoff); //如果clip里面的值小于0,则剔除该片元
return fixed4(var_MainTex.rgb ,1.0);
}
ENDCG
}
}
FallBack &#34;Diffuse&#34;
}<hr/>三、透明混合·AlphaBlend(AB)
介绍:有半透明效果,将源颜色(该片元颜色)和目标颜色(颜色缓冲区颜色)进行混合
用途:
[*]用于复杂轮廓,无明确边缘的物体表现
[*]半透明物体的表现
[*]一般的特效表现,打底用
优点:
[*]移动端性能较好
[*]边缘效果好,有过渡
缺点:
[*]有排序问题,需要关闭深度写入
AC:右;AB:左
Shader代码
Queue : 控制渲染队列,使Unity能够先渲染不透明物体,再渲染带透明度的物体
Blend : 混合方式,源颜色和目标颜色的混合算法的一部分
(这里是 Blend One OneMinusSrcAlpha,是因为所用贴图的rgb已经预乘过了alpha通道了,如果没有预乘过则应写成 Blend SrcAlpha OneMinusSrcAlpha)(具体解释看十五课)
注意:AB涉及到了透明度混合,因此想要渲染双面显示,不能直接简单地写 Cull Off ,应该用2个Pass来分别渲染前后面
具体代码:
Shader &#34;AP1/L13/AlphaBlend&#34; {
Properties{
_MainTex (&#34;RGB:颜色 ; A:透贴&#34; , 2D) = &#34;white&#34;{}
}
SubShader{
Tags {
&#34;Queue&#34; = &#34;Transparent&#34; //渲染队列3000
&#34;RenderType&#34; = &#34;Transparent&#34; //把Shader归入到提前定义的组(这里是Transparent组)
//以指明该Shader使用了透明度测试
//RenderType标签通常被用于着色器替换功能
&#34;IgnoreProjector&#34; = &#34;True&#34; //shader不会受到投影器(Projectors)的影响
&#34;ForceNoShadowCasting&#34; = &#34;True&#34; //关闭阴影投射
}
Pass {
Name &#34;FORWARD&#34;
Tags {
&#34;LightMode&#34; = &#34;ForwardBase&#34;
}
ZWrite Off //关闭深度写入
Blend One OneMinusSrcAlpha //修改混合方式
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include &#34;UnityCG.cginc&#34;
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
struct VertexInput {
float4 vertex : POSITION;
float2 uv0 : TEXCOORD0;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
};
VertexOutput vert(VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv0 = v.uv0 * _MainTex_ST.xy + _MainTex_ST.zw;
return o;
}
fixed4 frag(VertexOutput i) : SV_TARGET {
fixed4 var_MainTex = tex2D(_MainTex , i.uv0);
return fixed4(var_MainTex); //最终输出
}
ENDCG
}
}
FallBack &#34;Diffuse&#34;
}<hr/>四、透明度叠加·Additive(AD)
用途:
[*]常用于发光体,辉光
[*]一般用于特效提亮
问题:
[*]有排序问题,需要关闭深度写入
[*]叠加多层后 容易爆性能(OverDraw),一个像素会算多次叠加
[*]辉光效果,通常可以用后处理Bloom替代
Shader代码:
只是在AB的基础上修改混合模式为 Blend One One 即可,达到提亮的效果
(注意:这里前面的One 是用了预乘后的贴图,如果没有预乘,则要在Shader里面预乘)
为什么最后输出alpha通道可以设置为1.0:因为AD的混合因子为 One One ,与透明度无关,因此最终输出的RGB不会受到alpha值的影响,你将其设置为0.0也不会有任何改变
具体代码:
Shader &#34;AP1/L13/Addtive&#34; {
Properties{
_MainTex (&#34;RGB:颜色 ; A:透贴&#34; , 2D) = &#34;white&#34;{}
}
SubShader{
Tags {
&#34;Queue&#34; = &#34;Transparent&#34; //渲染队列3000
&#34;RenderType&#34; = &#34;Transparent&#34; //把Shader归入到提前定义的组(这里是Transparent组)
//以指明该Shader使用了透明度测试
//RenderType标签通常被用于着色器替换功能
&#34;IgnoreProjector&#34; = &#34;True&#34; //shader不会受到投影器(Projectors)的影响
&#34;ForceNoShadowCasting&#34; = &#34;True&#34; //关闭阴影投射
}
Pass {
Name &#34;FORWARD&#34;
Tags {
&#34;LightMode&#34; = &#34;ForwardBase&#34;
}
ZWrite Off //关闭深度写入
Blend One One //修改混合方式
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include &#34;UnityCG.cginc&#34;
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
struct VertexInput {
float4 vertex : POSITION;
float2 uv0 : TEXCOORD0;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
};
VertexOutput vert(VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv0 = v.uv0 * _MainTex_ST.xy + _MainTex_ST.zw;
return o;
}
fixed4 frag(VertexOutput i) : SV_TARGET {
fixed4 var_MainTex = tex2D(_MainTex , i.uv0);
return fixed4(var_MainTex.rgb , 1.0); //最终输出,因为Blend One One 最终输出RGB与透明度无关,所以alpha可以设置为常数
}
ENDCG
}
}
FallBack &#34;Diffuse&#34;
}
AC、AB、AD对比
五、混合模式
各种混合模式,就是一个个函数,参数是混合因子和运算符,变量是源颜色和目标颜色
(拿PS类比:PS的上图层——源颜色,下图层——目标颜色)
关于混合计算方式可以参考我的另一篇文章:TecrayC:《UnityShader入门精要》学习笔记——第八章——透明效果中的混合命令
<hr/>六、美术自定义混合面板
左边:一般给美术调试效果; 右边:进行相应封装(需要C#)
代码实现:
//[枚举Enum(枚举类型)]
_BlendSrc(&#34;混合源乘子&#34; , int) = 0 //_BlendSrc , int型Enum是枚举的意思,后面小括号内是枚举类型
BlendOp //可自定义混合算符
Blend //可自定义混合模式在定义变量时BlendOp(混合算符)和Blend(混合模式) 的参数填写 面板参数
具体代码:
Shader &#34;AP1/L13/BlendMode&#34; {
Properties{
_MainTex (&#34;RGB:颜色 ; A:透贴&#34; , 2D) = &#34;white&#34;{}
//[枚举Enum(枚举类型)]
_BlendSrc(&#34;混合源乘子&#34; , int) = 0 //_BlendSrc , int型
_BlendDst(&#34;混合目标乘子&#34; , int) = 0 //_BlendDst
_BlendOp(&#34;混合算符&#34; , int) = 0 //_BlendOp
}
SubShader{
Tags {
&#34;Queue&#34; = &#34;Transparent&#34; //渲染队列3000
&#34;RenderType&#34; = &#34;Transparent&#34; //把Shader归入到提前定义的组(这里是Transparent组)
//以指明该Shader使用了透明度测试
//RenderType标签通常被用于着色器替换功能
&#34;IgnoreProjector&#34; = &#34;True&#34; //shader不会受到投影器(Projectors)的影响
&#34;ForceNoShadowCasting&#34; = &#34;True&#34; //关闭阴影投射
}
Pass {
Name &#34;FORWARD&#34;
Tags {
&#34;LightMode&#34; = &#34;ForwardBase&#34;
}
ZWrite Off //关闭深度写入
BlendOp //可自定义混合算符
Blend //可自定义混合模式
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include &#34;UnityCG.cginc&#34;
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
struct VertexInput {
float4 vertex : POSITION;
float2 uv0 : TEXCOORD0;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
};
VertexOutput vert(VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv0 = v.uv0 * _MainTex_ST.xy + _MainTex_ST.zw;
return o;
}
fixed4 frag(VertexOutput i) : SV_TARGET {
fixed4 var_MainTex = tex2D(_MainTex , i.uv0);
return fixed4(var_MainTex);
}
ENDCG
}
}
FallBack &#34;Diffuse&#34;
}
https://www.zhihu.com/video/1433565970187497472
<hr/>第十三课总结:
[*]特效有透明,动画,映射等
[*]AC(AlphaCutout)是直接去掉透明度超过某一阈值的片元
[*]AB(AlphaBlend)和AD(Addtive)都是应用了透明度混合,用到了混合模式
[*]混合模式有很多种,其本质上是一种关于源颜色、目标颜色、源混合因子、目标混合因子的算法,可以自己设定面板参数进行枚举调节
参考资料:
页:
[1]