角色和武器Shader特效开发
角色Shader的动效需求
角Shader的开发不知要实现最基础光照等功能, 可能还要在角色武器的Shader增加多种动效, 比如因武器品质区分的流光特效, 被技能击中时的冻结效果.
这类动效的实现方式有多种, 以下以Shader的方式实现下列三种:
- 流光
- 冰
- 溶解
开发思路
具体效果
-
流光
两层
Alpha控制范围 -
冰
matcap实现 -
溶解
支持溶解边缘亮边
step(fixed2(noise, noise+edge), _Dissolve)
对需要实现的效果进行排序
实现这些需求的过程上来说, 肯定是一层一层在基础效果只上叠加上去的,相互之间是有"覆盖"关系的, 于是我们将以上需求排列整理如下:
- 光照
- 流光
- 冰
- 溶解
2. Shader代码的实现
1. 封装
#ifndef MESH_FX_CORE_INCLUDED
#define MESH_FX_CORE_INCLUDED
#ifdef MESH_FX_ON
uniform float4 _EdgeColor;
uniform sampler2D _DissolveNoiseTex;
uniform float4 _DissolveNoiseTex_ST;
uniform float _DissolveWidth;
uniform float _Dissolve;
uniform sampler2D _MatcapTex ;
uniform float _MatcapIntensity;
uniform float4 _FlowColor;
uniform sampler2D _FlowTex ;
uniform float4 _FlowTexTiling ;
uniform float4 _Flow1Color;
uniform sampler2D _FlowTex1 ;
uniform float4 _FlowSpeed ;
uniform float _FlowIntensity ;
struct MeshFXData
{
float2 UV0;
float3 normalWorld;
fixed3 BaseColor;
};
fixed4 FX_Dissolve(MeshFXData fx)
{
float2 uv_DissolveNoiseTex = fx.UV0 * _DissolveNoiseTex_ST.xy + _DissolveNoiseTex_ST.zw;
float4 dissolveTexCol = tex2D(_DissolveNoiseTex, uv_DissolveNoiseTex);
float2 twoLayer = float2(dissolveTexCol.r, saturate(dissolveTexCol.r + _DissolveWidth));
float2 dissolveResult = step(twoLayer, _Dissolve.xx);
float4 finalCol = _EdgeColor * (dissolveResult.x - dissolveResult.y) * dissolveTexCol.r;
finalCol.a = saturate(dissolveResult.x);
return finalCol;
}
fixed4 FX_Frozen(MeshFXData fx)
{
float2 matCapUV = ((mul(UNITY_MATRIX_V, float4(fx.normalWorld, 0.0)).xyz * 0.5) + 0.5).xy;
float4 finalCol = tex2D(_MatcapTex, matCapUV);
finalCol.a = _MatcapIntensity;
return finalCol;
}
fixed4 FX_LightFlow(MeshFXData fx)
{
float2 uv0 = fx.UV0 * _FlowTexTiling.xy + (_Time.y * _FlowSpeed.xy);
fixed4 flowCol1 = tex2D(_FlowTex, uv0);
fixed mask1 = tex2D(_FlowTex, fx.UV0.xy).a; //
float2 uv1 = fx.UV0 * _FlowTexTiling.zw + (_Time.y * _FlowSpeed.zw);
fixed4 flowCol2 = tex2D(_FlowTex1, uv1);
fixed mask2 = tex2D(_FlowTex1, fx.UV0.xy).a;
fixed4 layer1 = flowCol1 * mask1 * _FlowColor;
fixed4 layer2 = flowCol2 * mask2 * _Flow1Color;
fixed4 col = (layer1 + layer2) * _FlowIntensity;
col.a = max(flowCol1.a, flowCol2.a);
return col;
}
fixed4 MeshFXInternal(MeshFXData fx)
{
fixed4 finalColor = fixed4(0, 0, 0, 0);
fixed4 Dissolve = FX_Dissolve(fx);
fixed4 Frozen = FX_Frozen(fx);
fixed4 LightFlow = FX_LightFlow(fx);
// lightflow -> frozen -> dissolve
//lightflow
finalColor.rgb = fx.BaseColor + LightFlow.rgb * fx.BaseColor * 2;
//matcap frozen
finalColor.rgb = lerp(finalColor.rgb, Frozen.rgb, Frozen.a);
//dissolve
finalColor.rgb = finalColor + Dissolve.rgb;
finalColor.a = Dissolve.a;
return finalColor;
}
#endif
#endif
2. 调用
#if defined(MESH_FX_ON)
MeshFXData fx = (MeshFXData)0;
fx.UV0 = i.tex.xy;
fx.normalWorld = s.normalWorld;
fx.BaseColor = Color.rgb;
Color = MeshFXInternal(fx);
#endif
3. ShaderGUI的实现
体力活
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">