游戏开发中常常会有精美的2D立绘,这种2D立绘一般为一张静态贴图,图片精美,但看地来比较呆板,不够生动形象。基于此问题,我们可以开发自己的shader实现动态效果。
如下图:左图为静态原始效果,右图为特殊渲染后的动态效果。(当然可以用Spine等其它方式做成动图,但在本文讨论范围)。
gif图片数据丢失比较严重:细看可以看到,妹子衣服的摆动,水面的波纹,妹子眼珠的转动,前景树枝的摇曳,树枝后面光束的转动,扇子上面宝石的闪烁,等动态效果。
实现原理为:给RawImage设置为自定义的材质(image_3d.shader),然后设置材质中的各个参数来实现动画。(Image3D.cs的作用也后面再介绍)
image_3d.shader,实现了多种动化效果,并利用遮罩图片的rgb通道和配置参数来做为动画的参数输入。
遮罩图片1(下左图)R:扇子上的光;G:水面;B:前景树枝
遮罩图片2(下右图)R:妹子的衣服;G:妹子的头发;B:妹子的眼睛
如果一张遮罩够用的话,最好只用一张遮罩会比较省。
遮罩中的颜色的值比如: 遮罩2中的红色,会有比较明显的颜色浓度过度(其它也有),用于控制衣服摆动的幅度,比如衣服的边缘处摆动幅度大,红色就比较深。
因为遮罩图层可能会有重叠。PS中遮罩层的图层要设置为“变亮“(如下图)。这样0XFF0000FF和0X009900FF混合后的颜色值会为0XFF9900FF,在shader中可以取到正确的值。PS图层中默认的”正常“在不同图层有重叠时会有最终颜色0XFF0000FF会把0X009900FF盖住,达不到我们要的效果。
然后在片元着色器中做动画
因为咱们要在材质球中编辑各个参数,所以用的是shader_feature而没用multi_compile
下面代码为简单示例:
fixed4 frag(v2f IN) : SV_Target
{
float2 mTexcoord = IN.texcoord;//原图的纹理坐标
fixed3 mask = tex2D(_Mask, mTexcoord).rgb;//遮罩图
mTexcoord += Wave(mTexcoord, _SpeedR, mask.r, _ParametersR);//用遮罩图的红色(mask.r)和其它参数(_SpeedR,_ParametersR )作为Wave函数的输入
half4 color = (tex2D(_MainTex, mTexcoord) + _TextureSampleAdd);
return color;
}
动画函数举例:波动
//params.x: 1,y方向的振幅
//params.y: 1,y方向的频率
//params.z: 1,x方向的振幅
//params.w: 1,x方向的频率
half2 Wave(float2 uv, float speed, float concentration, float4 params)
{
half2 offset;
half2 phase = (uv + speed * half2(_Time.y, _Time.y))* PI * 2;
offset.y = params.x * sin(params.y * phase.x);
offset.x = params.z * sin(params.w * phase.y);
offset = offset * concentration * 0.01;
return offset;
}
因为image_3d.shader代码比较多,并且组合方式不一定是最适合您的,所以只建议参考。
相关的资源:点击这里可以下载。
以上动画中的实际代码如下:(可用代码)
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
Shader "mgo/image/image_3d"
{
Properties
{
[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
_Color("Tint", Color) = (1,1,1,1)
_StencilComp("Stencil Comparison", Float) = 8
_Stencil("Stencil ID", Float) = 0
_StencilOp("Stencil Operation", Float) = 0
_StencilWriteMask("Stencil Write Mask", Float) = 255
_StencilReadMask("Stencil Read Mask", Float) = 255
_ColorMask("Color Mask", Float) = 15
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", Float) = 0
[Space(100)]
[Header(The following is editable content for card)]
[Toggle(_ENABLE_ANI)] _EnableAni("EnableAni", Int) = 0
[NoScaleOffset]
_Mask("Mask", 2D) = "white" {}
//[KeywordEnum(Null, ThreeD, Wave, Flex, Move, Flash, Ripple, FlowLight, Spiral)] _Type_R("TypeR", Int) = 0
[KeywordEnum(Null, ThreeD, Wave, Flex, Move, Flash, FlowLight, Ripple)] _Type_R("TypeR", Int) = 0
_SpeedR("SpeedR", Range(-10,10)) = 1
_ParametersR("ParametersR", vector) = (1,1,1,1)
//[KeywordEnum(Null, Wave, Flex, Move, Flash, Ripple, FlowLight, Spiral)] _Type_G("TypeG", Int) = 0
[KeywordEnum(Null, Wave, Flex, Move, Flash, FlowLight, Ripple)] _Type_G("TypeG", Int) = 0
_SpeedG("SpeedG", Range(-10,10)) = 1
_ParametersG("ParametersG", vector) = (1,1,1,1)
//[KeywordEnum(Null, Wave, Flex, Move, Flash, Ripple, FlowLight, Spiral)] _Type_B("TypeB", Int) = 0
[KeywordEnum(Null, Wave, Flex, Move, Flash, FlowLight, Ripple)] _Type_B("TypeB", Int) = 0
_SpeedB("SpeedB", Range(-10,10)) = 1
_ParametersB("ParametersB", vector) = (1,1,1,1)
[NoScaleOffset]
_Mask2("Mask2", 2D) = "white" {}
//[KeywordEnum(Null, Wave, Flex, Move, Flash, Ripple, FlowLight, Spiral)] _Type2_R("Type2R", Int) = 0
[KeywordEnum(Null, Wave, Flex, Move, Flash, FlowLight, Ripple)] _Type2_R("Type2R", Int) = 0
_Speed2R("Speed2R", Range(-10,10)) = 1
_Parameters2R("Parameters2R", vector) = (1,1,1,1)
//[KeywordEnum(Null, Wave, Flex, Move, Flash, Ripple, FlowLight, Spiral)] _Type2_G("Type2G", Int) = 0
[KeywordEnum(Null, Wave, Flex, Move, Flash, FlowLight, Ripple)] _Type2_G("Type2G", Int) = 0
_Speed2G("Speed2G", Range(-10,10)) = 1
_Parameters2G("Parameters2G", vector) = (1,1,1,1)
//[KeywordEnum(Null, Wave, Flex, Move, Flash, Ripple, FlowLight, Spiral)] _Type2_B("Type2B", Int) = 0
[KeywordEnum(Null, Wave, Flex, Move, Flash, FlowLight, Ripple)] _Type2_B("Type2B", Int) = 0
_Speed2B("Speed2B", Range(-10,10)) = 1
_Parameters2B("Parameters2B", vector) = (1,1,1,1)
//--------------------------------------------
[Space(100)]
[Header(The following is editable content for effect)]
[Header(Please do not check the effect options you do not use such as EnableFx1 EnableFx2 EnableFx3 EnableFx4)]
[Toggle(_ENABLE_FX1)] _ENABLE_FX1("EnableFx1", Int) = 0
[Toggle(_ENABLE_FX2)] _ENABLE_FX2("EnableFx2", Int) = 0
[Toggle(_ENABLE_FX3)] _ENABLE_FX3("EnableFx3", Int) = 0
[Toggle(_ENABLE_FX4)] _ENABLE_FX4("EnableFx4", Int) = 0
[Header(effect 1 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz)]
_Fx1Tex("Fx1 Texture", 2D) = "white" {}
[KeywordEnum(NULL, MASK_R, MASK_G, MASK_B, MASK2_R, MASK2_G, MASK2_B)] _Fx1("Fx1 Mask Color", Int) = 0
[Toggle] _Fx1IsOneMinus("Fx1IsOneMinus", Int) = 0
_Fx1SpeedMove("Fx1SpeedMove", Range(-10,10)) = 0
_Fx1ParametersMove("Fx1ParametersMove", vector) = (1,1,1,1)
_Fx1SpeedWave("Fx1SpeedWave", Range(-10,10)) = 0
_Fx1ParametersWave("Fx1ParametersWave", vector) = (1,1,1,1)
_Fx1SpeedFlex("Fx1SpeedFlex", Range(-10,10)) = 0
_Fx1ParametersFlex("Fx1ParametersFlex", vector) = (1,1,1,1)
_Fx1SpeedSpiral("Fx1SpeedSpiral", Range(-10,10)) = 0
_Fx1ParametersSpiral("Fx1ParametersSpiral", vector) = (1,1,1,1)
_Fx1SpeedFrameAni("Fx1SpeedFrameAni", Range(-10,10)) = 0
_Fx1ParametersFrameAni("Fx1ParametersFrameAni", vector) = (1,1,1,1)
_Fx1SpeedFlash("Fx1SpeedFlash", Range(-10,10)) = 0
_Fx1ParametersFlash("Fx1ParametersFlash", vector) = (1,1,1,1)
[Space(50)]
[Header(effect 2 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz)]
_Fx2Tex("Fx2 Texture", 2D) = "white" {}
[KeywordEnum(NULL, MASK_R, MASK_G, MASK_B, MASK2_R, MASK2_G, MASK2_B)] _Fx2("Fx2 Mask Color", Int) = 0
[Toggle] _Fx2IsOneMinus("Fx2IsOneMinus", Int) = 0
_Fx2SpeedMove("Fx2SpeedMove", Range(-10,10)) = 0
_Fx2ParametersMove("Fx2ParametersMove", vector) = (1,1,1,1)
_Fx2SpeedWave("Fx2SpeedWave", Range(-10,10)) = 0
_Fx2ParametersWave("Fx2ParametersWave", vector) = (1,1,1,1)
_Fx2SpeedFlex("Fx2SpeedFlex", Range(-10,10)) = 0
_Fx2ParametersFlex("Fx2ParametersFlex", vector) = (1,1,1,1)
_Fx2SpeedSpiral("Fx2SpeedSpiral", Range(-10,10)) = 0
_Fx2ParametersSpiral("Fx2ParametersSpiral", vector) = (1,1,1,1)
_Fx2SpeedFrameAni("Fx2SpeedFrameAni", Range(-10,10)) = 0
_Fx2ParametersFrameAni("Fx2ParametersFrameAni", vector) = (1,1,1,1)
_Fx2SpeedFlash("Fx2SpeedFlash", Range(-10,10)) = 0
_Fx2ParametersFlash("Fx2ParametersFlash", vector) = (1,1,1,1)
[Space(50)]
[Header(effect 3 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz)]
_Fx3Tex("Fx3 Texture", 2D) = "white" {}
[KeywordEnum(NULL, MASK_R, MASK_G, MASK_B, MASK2_R, MASK2_G, MASK2_B)] _Fx3("Fx3 Mask Color", Int) = 0
[Toggle] _Fx3IsOneMinus("Fx3IsOneMinus", Int) = 0
_Fx3SpeedMove("Fx3SpeedMove", Range(-10,10)) = 0
_Fx3ParametersMove("Fx3ParametersMove", vector) = (1,1,1,1)
_Fx3SpeedWave("Fx3SpeedWave", Range(-10,10)) = 0
_Fx3ParametersWave("Fx3ParametersWave", vector) = (1,1,1,1)
_Fx3SpeedFlex("Fx3SpeedFlex", Range(-10,10)) = 0
_Fx3ParametersFlex("Fx3ParametersFlex", vector) = (1,1,1,1)
_Fx3SpeedSpiral("Fx3SpeedSpiral", Range(-10, 10)) = 0
_Fx3ParametersSpiral("Fx3ParametersSpiral", vector) = (1, 1, 1, 1)
_Fx3SpeedFrameAni("Fx3SpeedFrameAni", Range(-10, 10)) = 0
_Fx3ParametersFrameAni("Fx3ParametersFrameAni", vector) = (1, 1, 1, 1)
_Fx3SpeedFlash("Fx3SpeedFlash", Range(-10,10)) = 0
_Fx3ParametersFlash("Fx3ParametersFlash", vector) = (1,1,1,1)
[Space(50)]
[Header(effect 4 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz)]
_Fx4Tex("Fx4 Texture", 2D) = "white" {}
[KeywordEnum(NULL, MASK_R, MASK_G, MASK_B, MASK2_R, MASK2_G, MASK2_B)] _Fx3("Fx4 Mask Color", Int) = 0
[Toggle] _Fx4IsOneMinus("Fx4IsOneMinus", Int) = 0
_Fx4SpeedMove("Fx4SpeedMove", Range(-10,10)) = 0
_Fx4ParametersMove("Fx4ParametersMove", vector) = (1,1,1,1)
_Fx4SpeedWave("Fx4SpeedWave", Range(-10,10)) = 0
_Fx4ParametersWave("Fx4ParametersWave", vector) = (1,1,1,1)
_Fx4SpeedFlex("Fx4SpeedFlex", Range(-10,10)) = 0
_Fx4ParametersFlex("Fx4ParametersFlex", vector) = (1,1,1,1)
_Fx4SpeedSpiral("Fx4SpeedSpiral", Range(-10, 10)) = 0
_Fx4ParametersSpiral("Fx4ParametersSpiral", vector) = (1, 1, 1, 1)
_Fx4SpeedFrameAni("Fx4SpeedFrameAni", Range(-10, 10)) = 0
_Fx4ParametersFrameAni("Fx4ParametersFrameAni", vector) = (1, 1, 1, 1)
_Fx4SpeedFlash("Fx4SpeedFlash", Range(-10,10)) = 0
_Fx4ParametersFlash("Fx4ParametersFlash", vector) = (1,1,1,1)
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
"PreviewType" = "Plane"
"CanUseSpriteAtlas" = "True"
}
Stencil
{
Ref[_Stencil]
Comp[_StencilComp]
Pass[_StencilOp]
ReadMask[_StencilReadMask]
WriteMask[_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest[unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask[_ColorMask]
Pass
{
Name "Default"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "UnityCG.cginc"
#include "UnityUI.cginc"
#pragma multi_compile __ UNITY_UI_CLIP_RECT
#pragma multi_compile __ UNITY_UI_ALPHACLIP
#pragma shader_feature _ENABLE_ANI
//#pragma shader_feature _TYPE_R_NULL _TYPE_R_THREED _TYPE_R_WAVE _TYPE_R_FLEX _TYPE_R_MOVE _TYPE_R_FLASH _TYPE_R_RIPPLE _TYPE_R_FLOWLIGHT _TYPE_R_SPIRAL
//#pragma shader_feature _TYPE_G_NULL _TYPE_G_WAVE _TYPE_G_FLEX _TYPE_G_MOVE _TYPE_G_FLASH _TYPE_G_RIPPLE _TYPE_G_FLOWLIGHT _TYPE_G_SPIRAL
//#pragma shader_feature _TYPE_B_NULL _TYPE_B_WAVE _TYPE_B_FLEX _TYPE_B_MOVE _TYPE_B_FLASH _TYPE_B_RIPPLE _TYPE_B_FLOWLIGHT _TYPE_B_SPIRAL
//#pragma shader_feature _TYPE2_R_NULL _TYPE2_R_WAVE _TYPE2_R_FLEX _TYPE2_R_MOVE _TYPE2_R_FLASH _TYPE2_R_RIPPLE _TYPE2_R_FLOWLIGHT _TYPE2_R_SPIRAL
//#pragma shader_feature _TYPE2_G_NULL _TYPE2_G_WAVE _TYPE2_G_FLEX _TYPE2_G_MOVE _TYPE2_G_FLASH _TYPE2_G_RIPPLE _TYPE2_G_FLOWLIGHT _TYPE2_G_SPIRAL
//#pragma shader_feature _TYPE2_B_NULL _TYPE2_B_WAVE _TYPE2_B_FLEX _TYPE2_B_MOVE _TYPE2_B_FLASH _TYPE2_B_RIPPLE _TYPE2_B_FLOWLIGHT _TYPE2_B_SPIRAL
#pragma shader_feature _TYPE_R_NULL _TYPE_R_WAVE _TYPE_R_FLEX _TYPE_R_MOVE _TYPE_R_FLASH _TYPE_R_FLOWLIGHT _TYPE_R_RIPPLE _TYPE_R_THREED
#pragma shader_feature _TYPE_G_NULL _TYPE_G_WAVE _TYPE_G_FLEX _TYPE_G_MOVE _TYPE_G_FLASH _TYPE_G_FLOWLIGHT _TYPE_G_RIPPLE
#pragma shader_feature _TYPE_B_NULL _TYPE_B_WAVE _TYPE_B_FLEX _TYPE_B_MOVE _TYPE_B_FLASH _TYPE_B_FLOWLIGHT _TYPE_B_RIPPLE
#pragma shader_feature _TYPE2_R_NULL _TYPE2_R_WAVE _TYPE2_R_FLEX _TYPE2_R_MOVE _TYPE2_R_FLASH _TYPE2_R_FLOWLIGHT _TYPE2_R_RIPPLE
#pragma shader_feature _TYPE2_G_NULL _TYPE2_G_WAVE _TYPE2_G_FLEX _TYPE2_G_MOVE _TYPE2_G_FLASH _TYPE2_G_FLOWLIGHT _TYPE2_G_RIPPLE
#pragma shader_feature _TYPE2_B_NULL _TYPE2_B_WAVE _TYPE2_B_FLEX _TYPE2_B_MOVE _TYPE2_B_FLASH _TYPE2_B_FLOWLIGHT _TYPE2_B_RIPPLE
#pragma shader_feature _ENABLE_FX1
#pragma shader_feature _FX1_MASK_NULL _FX1_MASK_R _FX1_MASK_G _FX1_MASK_B _FX1_MASK2_R _FX1_MASK2_G _FX1_MASK2_B
#pragma shader_feature _ENABLE_FX2
#pragma shader_feature _FX2_MASK_NULL _FX2_MASK_R _FX2_MASK_G _FX2_MASK_B _FX2_MASK2_R _FX2_MASK2_G _FX2_MASK2_B
#pragma shader_feature _ENABLE_FX3
#pragma shader_feature _FX3_MASK_NULL _FX3_MASK_R _FX3_MASK_G _FX3_MASK_B _FX3_MASK2_R _FX3_MASK2_G _FX3_MASK2_B
#pragma shader_feature _ENABLE_FX4
#pragma shader_feature _FX4_MASK_NULL _FX4_MASK_R _FX4_MASK_G _FX4_MASK_B _FX4_MASK2_R _FX4_MASK2_G _FX4_MASK2_B
#define PI 3.1415926
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
#if _ENABLE_FX1
float2 fx1Texcoord : TEXCOORD2;
#endif
#if _ENABLE_FX2
float2 fx2Texcoord : TEXCOORD3;
#endif
#if _ENABLE_FX3
float2 fx3Texcoord : TEXCOORD4;
#endif
#if _ENABLE_FX4
float2 fx4Texcoord : TEXCOORD5;
#endif
UNITY_VERTEX_OUTPUT_STEREO
};
sampler2D _MainTex;
fixed4 _Color;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
float4 _MainTex_ST;
uniform sampler2D _Mask;
uniform float4 _Mask_ST;
uniform float _SpeedR;
uniform float4 _ParametersR;
uniform float _SpeedG;
uniform float4 _ParametersG;
uniform float _SpeedB;
uniform float4 _ParametersB;
uniform sampler2D _Mask2;
uniform float4 _Mask2_ST;
uniform float _Speed2R;
uniform float4 _Parameters2R;
uniform float _Speed2G;
uniform float4 _Parameters2G;
uniform float _Speed2B;
uniform float4 _Parameters2B;
uniform sampler2D _Fx1Tex;
uniform float4 _Fx1Tex_ST;
uniform bool _Fx1IsOneMinus;
uniform float _Fx1SpeedMove;
uniform float4 _Fx1ParametersMove;
uniform float _Fx1SpeedWave;
uniform float4 _Fx1ParametersWave;
uniform float _Fx1SpeedFlex;
uniform float4 _Fx1ParametersFlex;
uniform float _Fx1SpeedSpiral;
uniform float4 _Fx1ParametersSpiral;
uniform float _Fx1SpeedFrameAni;
uniform float4 _Fx1ParametersFrameAni;
uniform float _Fx1SpeedFlash;
uniform float4 _Fx1ParametersFlash;
uniform sampler2D _Fx2Tex;
uniform float4 _Fx2Tex_ST;
uniform bool _Fx2IsOneMinus;
uniform float _Fx2SpeedMove;
uniform float4 _Fx2ParametersMove;
uniform float _Fx2SpeedWave;
uniform float4 _Fx2ParametersWave;
uniform float _Fx2SpeedFlex;
uniform float4 _Fx2ParametersFlex;
uniform float _Fx2SpeedSpiral;
uniform float4 _Fx2ParametersSpiral;
uniform float _Fx2SpeedFrameAni;
uniform float4 _Fx2ParametersFrameAni;
uniform float _Fx2SpeedFlash;
uniform float4 _Fx2ParametersFlash;
uniform sampler2D _Fx3Tex;
uniform float4 _Fx3Tex_ST;
uniform bool _Fx3IsOneMinus;
uniform float _Fx3SpeedMove;
uniform float4 _Fx3ParametersMove;
uniform float _Fx3SpeedWave;
uniform float4 _Fx3ParametersWave;
uniform float _Fx3SpeedFlex;
uniform float4 _Fx3ParametersFlex;
uniform float _Fx3SpeedSpiral;
uniform float4 _Fx3ParametersSpiral;
uniform float _Fx3SpeedFrameAni;
uniform float4 _Fx3ParametersFrameAni;
uniform float _Fx3SpeedFlash;
uniform float4 _Fx3ParametersFlash;
uniform sampler2D _Fx4Tex;
uniform float4 _Fx4Tex_ST;
uniform bool _Fx4IsOneMinus;
uniform float _Fx4SpeedMove;
uniform float4 _Fx4ParametersMove;
uniform float _Fx4SpeedWave;
uniform float4 _Fx4ParametersWave;
uniform float _Fx4SpeedFlex;
uniform float4 _Fx4ParametersFlex;
uniform float _Fx4SpeedSpiral;
uniform float4 _Fx4ParametersSpiral;
uniform float _Fx4SpeedFrameAni;
uniform float4 _Fx4ParametersFrameAni;
uniform float _Fx4SpeedFlash;
uniform float4 _Fx4ParametersFlash;
//函数定义区
//params.x: 自动情况下x方向移动的振幅
//params.y: 大于0表示开启自动3d运动 小于等于0用于手动拖动操作。
//params.z: 手动拖动操作时x方向的振幅
//params.w: 手动拖动操作时y方向的振幅
half2 ThreeD(float2 uv, float speed, float concentration, float4 params)
{
half2 offset;
if (params.y > 0)
{
half2 phase = (speed * _Time.y) * PI * 2;
offset.x = params.x * sin(phase);
offset.y = 0;
}
else
{
offset.x = params.z;
offset.y = params.w;
}
offset = offset * concentration * 0.01;
return offset;
}
//params.x: 1,y方向的振幅
//params.y: 1,y方向的频率
//params.z: 1,x方向的振幅
//params.w: 1,x方向的频率
half2 Wave(float2 uv, float speed, float concentration, float4 params)
{
half2 offset;
half2 phase = (uv + speed * half2(_Time.y, _Time.y))* PI * 2;
offset.y = params.x * sin(params.y * phase.x);
offset.x = params.z * sin(params.w * phase.y);
offset = offset * concentration * 0.01;
return offset;
}
//params.x: 1,x方向的振幅
//params.y: 1,x方向的频率
//params.z: 1,y方向的振幅
//params.w: 1,y方向的频率
half2 Flex(float2 uv, float speed, float concentration, float4 params)
{
half2 offset;
half2 phase = (uv + speed * half2(_Time.y, _Time.y))* PI * 2;
offset.x = params.x * sin(params.y * phase.x);
offset.y = params.z * sin(params.w * phase.y);
offset = offset * concentration * 0.01;
return offset;
}
//params.x: 1,x方向的速度
//params.y: 1,x方向的速度
//params.z: 0,useless
//params.w: 0,useless
half2 Move(float2 uv, float speed, float concentration, float4 params)
{
half2 offset;
half2 phase = speed * _Time.y;
offset.x = phase * params.x % 1;
offset.y = phase * params.y % 1;
return offset;
}
//params.x: 1,red
//params.y: 1,green
//params.z: 1,blue
//params.w: 0.2,最暗值
half3 Flash(float2 uv, float speed, float concentration, float4 params)
{
half3 color;
if (concentration > 0.01)
{
half2 phase = (speed * _Time.y) * PI * 2;
half light = saturate(lerp(params.w, 1, (sin(phase) + 1) * 0.5)) * concentration;
color = light * half3(params.x, params.y, params.z);
}
else
{
color = 0;
}
return color;
}
//params.x: 3,振幅
//params.y: 9,频率
//params.z: 0.5, 中心x
//params.w: 0.5, 中心y
half2 Ripple(float2 uv, float speed, float concentration, float4 params)
{
half dis = distance(float2(uv.x, uv.y * 1), params.zw);
half2 offset = saturate(1 - dis) * params.x * sin((dis * params.y + _Time.y * speed) * 2 * PI);
offset = offset * concentration * 0.01;
return offset;
}
//params.x: 0,光柱旋转角度
//params.y: 2,光柱频率(注意是否刷到目标位置)
//params.z: 0.2,光柱宽度(0~1)表示百分比
//params.w: 999900,光柱颜色(0~999999) red:990000 green:009900 blue:000099 yellow:999900 white:999999
half3 Flowlight(float2 uv, float speed, float concentration, float4 params)
{
//sampler2D fxTex,
/*half2 offset;
offset.y = 0;
offset.x = (speed * _Time.y % 1 - 0.5) * params.x;
half3 color = tex2D(fxTex, uv + offset);
color = color * params.y * concentration;
return color;*/
half width = params.z;
half rotation = params.x * PI / 180;
half offset = (speed * _Time.y % 1 - 0.5) * params.y;
float s, c;
sincos(rotation, s, c);
float2x2 rotMatrix = float2x2(c, -s, s, c);
half2 fxUV = mul(uv, rotMatrix);
half3 color = 0;
if (fxUV.x > offset && fxUV.x < offset + width)
{
color = half3(params.w / 10000 % 100, params.w / 100 % 100, params.w % 100) * concentration * 0.05;
fixed dis = abs(offset + width * 0.5 - fxUV.x);
fixed featherWidth = 0.2;
if (dis > width * (0.5 - featherWidth))
{
color *= lerp(1, 0, (dis - width * (0.5 - featherWidth)) / (width * featherWidth));
}
}
return color;
}
//params.x: 0.5, 扭曲程度
//params.y: 1, 中心扭曲加速度
//params.z: 0.5, 中心x
//params.w: 0.5, 中心y
half2 Spiral(float2 uv, float speed, float concentration, float4 params)
{
half dis = distance(uv.xy, params.zw);
float rotation = params.x * pow(dis, -params.y);
rotation += speed * _Time.y * 2 * PI;
float s, c;
sincos(rotation, s, c);
float2x2 rotMatrix = float2x2(c, -s, s, c);
half2 offset = mul(uv - params.zw, rotMatrix) + params.zw;
return offset;
}
//params.x: 4, 水平x方向有几个元素
//params.y: 4, 垂直y方向有几个元素
//params.z: 0, useless
//params.w: 0, useless
half2 FrameAni(float2 uv, float speed, float concentration, float4 params)
{
half2 offset = uv / params.xy;
fixed frame = floor(_Time.w * speed % (params.x * params.y));
fixed2 step = 1 / params.xy;
offset.x += (frame % params.x) * step.x;
offset.y += (1 - floor(frame / params.x) * step.y - step.y);
return offset;
}
v2f vert(appdata_t v)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.worldPosition = v.vertex;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
#if _ENABLE_ANI
#if _ENABLE_FX1
OUT.fx1Texcoord = TRANSFORM_TEX(v.texcoord, _Fx1Tex);
#endif
#if _ENABLE_FX2
OUT.fx2Texcoord = TRANSFORM_TEX(v.texcoord, _Fx2Tex);
#endif
#if _ENABLE_FX3
OUT.fx3Texcoord = TRANSFORM_TEX(v.texcoord, _Fx3Tex);
#endif
#if _ENABLE_FX4
OUT.fx4Texcoord = TRANSFORM_TEX(v.texcoord, _Fx4Tex);
#endif
#endif
OUT.color = v.color * _Color;
return OUT;
}
fixed4 frag(v2f IN) : SV_Target
{
#if _ENABLE_ANI
fixed3 depth = tex2D(_Mask2, IN.texcoord).rgb;
float2 mTexcoord = IN.texcoord;
fixed4 mColor = IN.color;
fixed3 mask = tex2D(_Mask, mTexcoord).rgb;
fixed3 mask2 = tex2D(_Mask2, mTexcoord).rgb;
//threeD------------------------------------------------------------------------------------------------------------------------------
#if _TYPE_R_THREED
mTexcoord += ThreeD(mTexcoord, _SpeedR, mask.r, _ParametersR);
mask2 = tex2D(_Mask2, mTexcoord).rgb;
#endif
//wave------------------------------------------------------------------------------------------------------------------------------
#if _TYPE_R_WAVE
mTexcoord += Wave(mTexcoord, _SpeedR, mask.r, _ParametersR);
mask2 = tex2D(_Mask2, mTexcoord).rgb;
#endif
#if _TYPE_G_WAVE
mTexcoord += Wave(mTexcoord, _SpeedG, mask.g, _ParametersG);
mask2 = tex2D(_Mask2, mTexcoord).rgb;
#endif
#if _TYPE_B_WAVE
mTexcoord += Wave(mTexcoord, _SpeedB, mask.b, _ParametersB);
mask2 = tex2D(_Mask2, mTexcoord).rgb;
#endif
#if _TYPE2_R_WAVE
mTexcoord += Wave(mTexcoord, _Speed2R, mask2.r, _Parameters2R);
#endif
#if _TYPE2_G_WAVE
mTexcoord += Wave(mTexcoord, _Speed2G, mask2.g, _Parameters2G);
#endif
#if _TYPE2_B_WAVE
mTexcoord += Wave(mTexcoord, _Speed2B, mask2.b, _Parameters2B);
#endif
//flex------------------------------------------------------------------------------------------------------------------------------
#if _TYPE_R_FLEX
mTexcoord += Flex(mTexcoord, _SpeedR, mask.r, _ParametersR);
mask2 = tex2D(_Mask2, mTexcoord).rgb;
#endif
#if _TYPE_G_FLEX
mTexcoord += Flex(mTexcoord, _SpeedG, mask.g, _ParametersG);
mask2 = tex2D(_Mask2, mTexcoord).rgb;
#endif
#if _TYPE_B_FLEX
mTexcoord += Flex(mTexcoord, _SpeedB, mask.b, _ParametersB);
mask2 = tex2D(_Mask2, mTexcoord).rgb;
#endif
#if _TYPE2_R_FLEX
mTexcoord += Flex(mTexcoord, _Speed2R, mask2.r, _Parameters2R);
#endif
#if _TYPE2_G_FLEX
mTexcoord += Flex(mTexcoord, _Speed2G, mask2.g, _Parameters2G);
#endif
#if _TYPE2_B_FLEX
mTexcoord += Flex(mTexcoord, _Speed2B, mask2.b, _Parameters2B);
#endif
//move-----------------------------------------------------------------------------------------------------------------------------
#if _TYPE_R_MOVE
mTexcoord += Move(mTexcoord, _SpeedR, mask.r, _ParametersR);
mask2 = tex2D(_Mask2, mTexcoord).rgb;
#endif
#if _TYPE_G_MOVE
mTexcoord += Move(mTexcoord, _SpeedG, mask.g, _ParametersG);
mask2 = tex2D(_Mask2, mTexcoord).rgb;
#endif
#if _TYPE_B_MOVE
mTexcoord += Move(mTexcoord, _SpeedB, mask.b, _ParametersB);
mask2 = tex2D(_Mask2, mTexcoord).rgb;
#endif
#if _TYPE2_R_MOVE
mTexcoord += Move(mTexcoord, _Speed2R, mask2.r, _Parameters2R);
#endif
#if _TYPE2_G_MOVE
mTexcoord += Move(mTexcoord, _Speed2G, mask2.g, _Parameters2G);
#endif
#if _TYPE2_B_MOVE
mTexcoord += Move(mTexcoord, _Speed2B, mask2.b, _Parameters2B);
#endif
//flash-----------------------------------------------------------------------------------------------------------------------------
#if _TYPE_R_FLASH
mColor.rgb += Flash(mTexcoord, _SpeedR, mask.r, _ParametersR);
#endif
#if _TYPE_G_FLASH
mColor.rgb += Flash(mTexcoord, _SpeedG, mask.g, _ParametersG);
#endif
#if _TYPE_B_FLASH
mColor.rgb += Flash(mTexcoord, _SpeedB, mask.b, _ParametersB);
#endif
#if _TYPE2_R_FLASH
mColor.rgb += Flash(mTexcoord, _Speed2R, mask2.r, _Parameters2R);
#endif
#if _TYPE2_G_FLASH
mColor.rgb += Flash(mTexcoord, _Speed2G, mask2.g, _Parameters2G);
#endif
#if _TYPE2_B_FLASH
mColor.rgb += Flash(mTexcoord, _Speed2B, mask2.b, _Parameters2B);
#endif
//ripple------------------------------------------------------------------------------------------------------------------------------
#if _TYPE_R_RIPPLE
mTexcoord += Ripple(mTexcoord, _SpeedR, mask.r, _ParametersR);
mask2 = tex2D(_Mask2, mTexcoord).rgb;
#endif
#if _TYPE_G_RIPPLE
mTexcoord += Ripple(mTexcoord, _SpeedG, mask.g, _ParametersG);
mask2 = tex2D(_Mask2, mTexcoord).rgb;
#endif
#if _TYPE_B_RIPPLE
mTexcoord += Ripple(mTexcoord, _SpeedB, mask.b, _ParametersB);
mask2 = tex2D(_Mask2, mTexcoord).rgb;
#endif
#if _TYPE2_R_RIPPLE
mTexcoord += Ripple(mTexcoord, _Speed2R, mask2.r, _Parameters2R);
#endif
#if _TYPE2_G_RIPPLE
mTexcoord += Ripple(mTexcoord, _Speed2G, mask2.g, _Parameters2G);
#endif
#if _TYPE2_B_RIPPLE
mTexcoord += Ripple(mTexcoord, _Speed2B, mask2.b, _Parameters2B);
#endif
//flowlight------------------------------------------------------------------------------------------------------------------------------
#if _TYPE_R_FLOWLIGHT
mColor.rgb += Flowlight(mTexcoord, _SpeedR, mask.r, _ParametersR);
#endif
#if _TYPE_G_FLOWLIGHT
mColor.rgb += Flowlight(mTexcoord, _SpeedG, mask.g, _ParametersG);
#endif
#if _TYPE_B_FLOWLIGHT
mColor.rgb += Flowlight(mTexcoord, _SpeedB, mask.b, _ParametersB);
#endif
#if _TYPE2_R_FLOWLIGHT
mColor.rgb += Flowlight(mTexcoord, _Speed2R, mask2.r, _Parameters2R);
#endif
#if _TYPE2_G_FLOWLIGHT
mColor.rgb += Flowlight(mTexcoord, _Speed2G, mask2.g, _Parameters2G);
#endif
#if _TYPE2_B_FLOWLIGHT
mColor.rgb += Flowlight(mTexcoord, _Speed2B, mask2.b, _Parameters2B);
#endif
//
spiral------------------------------------------------------------------------------------------------------------------------------
//#if _TYPE_R_SPIRAL
// mTexcoord += Spiral(mTexcoord, _SpeedR, mask.r, _ParametersR);
//#endif
//#if _TYPE_G_SPIRAL
// mTexcoord += Spiral(mTexcoord, _SpeedG, mask.g, _ParametersG);
//#endif
//#if _TYPE_B_SPIRAL
// mTexcoord += Spiral(mTexcoord, _SpeedB, mask.b, _ParametersB);
//#endif
//#if _TYPE2_R_SPIRAL
// mTexcoord += Spiral(mTexcoord, _Speed2R, mask2.r, _Parameters2R);
//#endif
//#if _TYPE2_G_SPIRAL
// mTexcoord += Spiral(mTexcoord, _Speed2G, mask2.g, _Parameters2G);
//#endif
//#if _TYPE2_B_SPIRAL
// mTexcoord += Spiral(mTexcoord, _Speed2B, mask2.b, _Parameters2B);
//#endif
#if _ENABLE_FX1 || _ENABLE_FX2 || _ENABLE_FX3 || _ENABLE_FX4
float2 fxUV;
fixed3 fxColor;
float concentration;
#endif
#if _ENABLE_FX1_ENABLE_FX1 START
#if _FX1_MASK_R
concentration = mask.r;
#elif _FX1_MASK_G
concentration = mask.g;
#elif _FX1_MASK_B
concentration = mask.b;
#elif _FX1_MASK2_R
concentration = mask2.r;
#elif _FX1_MASK2_G
concentration = mask2.g;
#elif _FX1_MASK2_B
concentration = mask2.b;
#elif _FX1_MASK_NULL
concentration = 1;
#endif
if (_Fx1IsOneMinus)
{
concentration = 1 - concentration;
}
fxUV = IN.fx1Texcoord;
if (_Fx1SpeedMove != 0.0)
{
fxUV += Move(fxUV, _Fx1SpeedMove, 1, _Fx1ParametersMove);
}
if (_Fx1SpeedWave != 0.0)
{
fxUV += Wave(fxUV, _Fx1SpeedWave, 1, _Fx1ParametersWave);
}
if (_Fx1SpeedFlex != 0.0)
{
fxUV += Flex(fxUV, _Fx1SpeedFlex, 1, _Fx1ParametersFlex);
}
if (_Fx1SpeedSpiral != 0.0)
{
fxUV = Spiral(fxUV, _Fx1SpeedSpiral, 1, _Fx1ParametersSpiral);
}
if (_Fx1SpeedFrameAni != 0.0)
{
fxUV = FrameAni(fxUV, _Fx1SpeedFrameAni, 1, _Fx1ParametersFrameAni);
}
fxColor = tex2D(_Fx1Tex, fxUV).rgb * concentration;
if (_Fx1SpeedFlash != 0.0)
{
if (fxColor.r > 0.001 || fxColor.g > 0.001 || fxColor.b > 0.001)
{
fxColor.rgb *= Flash(fxUV, _Fx1SpeedFlash, 1, _Fx1ParametersFlash);
}
}
mColor.rgb += fxColor;
#endif_ENABLE_FX1 END
#if _ENABLE_FX2_ENABLE_FX2 START
#if _FX2_MASK_R
concentration = mask.r;
#elif _FX2_MASK_G
concentration = mask.g;
#elif _FX2_MASK_B
concentration = mask.b;
#elif _FX2_MASK2_R
concentration = mask2.r;
#elif _FX2_MASK2_G
concentration = mask2.g;
#elif _FX2_MASK2_B
concentration = mask2.b;
#elif _FX2_MASK_NULL
concentration = 1;
#endif
if (_Fx2IsOneMinus)
{
concentration = 1 - concentration;
}
fxUV = IN.fx2Texcoord;
if (_Fx2SpeedMove != 0.0)
{
fxUV += Move(fxUV, _Fx2SpeedMove, 1, _Fx2ParametersMove);
}
if (_Fx2SpeedWave != 0.0)
{
fxUV += Wave(fxUV, _Fx2SpeedWave, 1, _Fx2ParametersWave);
}
if (_Fx2SpeedFlex != 0.0)
{
fxUV += Flex(fxUV, _Fx2SpeedFlex, 1, _Fx2ParametersFlex);
}
if (_Fx2SpeedSpiral != 0.0)
{
fxUV = Spiral(fxUV, _Fx2SpeedSpiral, 1, _Fx2ParametersSpiral);
}
if (_Fx2SpeedFrameAni != 0.0)
{
fxUV = FrameAni(fxUV, _Fx2SpeedFrameAni, 1, _Fx2ParametersFrameAni);
}
fxColor = tex2D(_Fx2Tex, fxUV).rgb * concentration;
if (_Fx2SpeedFlash != 0.0)
{
if (fxColor.r > 0.001 || fxColor.g > 0.001 || fxColor.b > 0.001)
{
fxColor.rgb *= Flash(fxUV, _Fx2SpeedFlash, 1, _Fx2ParametersFlash);
}
}
mColor.rgb += fxColor;
#endif_ENABLE_FX2 END
#if _ENABLE_FX3_ENABLE_FX3 START
#if _FX3_MASK_R
concentration = mask.r;
#elif _FX3_MASK_G
concentration = mask.g;
#elif _FX3_MASK_B
concentration = mask.b;
#elif _FX3_MASK2_R
concentration = mask2.r;
#elif _FX3_MASK2_G
concentration = mask2.g;
#elif _FX3_MASK2_B
concentration = mask2.b;
#elif _FX3_MASK_NULL
concentration = 1;
#endif
if (_Fx3IsOneMinus)
{
concentration = 1 - concentration;
}
fxUV = IN.fx3Texcoord;
if (_Fx3SpeedMove != 0.0)
{
fxUV += Move(fxUV, _Fx3SpeedMove, 1, _Fx3ParametersMove);
}
if (_Fx3SpeedWave != 0.0)
{
fxUV += Wave(fxUV, _Fx3SpeedWave, 1, _Fx3ParametersWave);
}
if (_Fx3SpeedFlex != 0.0)
{
fxUV += Flex(fxUV, _Fx3SpeedFlex, 1, _Fx3ParametersFlex);
}
if (_Fx3SpeedSpiral != 0.0)
{
fxUV = Spiral(fxUV, _Fx3SpeedSpiral, 1, _Fx3ParametersSpiral);
}
if (_Fx3SpeedFrameAni != 0.0)
{
fxUV = FrameAni(fxUV, _Fx3SpeedFrameAni, 1, _Fx3ParametersFrameAni);
}
fxColor = tex2D(_Fx3Tex, fxUV).rgb * concentration;
if (_Fx3SpeedFlash != 0.0)
{
if (fxColor.r > 0.001 || fxColor.g > 0.001 || fxColor.b > 0.001)
{
fxColor.rgb *= Flash(fxUV, _Fx3SpeedFlash, 1, _Fx3ParametersFlash);
}
}
mColor.rgb += fxColor;
#endif_ENABLE_FX3 END
#if _ENABLE_FX4_ENABLE_FX4 START
#if _FX4_MASK_R
concentration = mask.r;
#elif _FX4_MASK_G
concentration = mask.g;
#elif _FX4_MASK_B
concentration = mask.b;
#elif _FX4_MASK2_R
concentration = mask2.r;
#elif _FX4_MASK2_G
concentration = mask2.g;
#elif _FX4_MASK2_B
concentration = mask2.b;
#elif _FX4_MASK_NULL
concentration = 1;
#endif
if (_Fx4IsOneMinus)
{
concentration = 1 - concentration;
}
fxUV = IN.fx4Texcoord;
if (_Fx4SpeedMove != 0.0)
{
fxUV += Move(fxUV, _Fx4SpeedMove, 1, _Fx4ParametersMove);
}
if (_Fx4SpeedWave != 0.0)
{
fxUV += Wave(fxUV, _Fx4SpeedWave, 1, _Fx4ParametersWave);
}
if (_Fx4SpeedFlex != 0.0)
{
fxUV += Flex(fxUV, _Fx4SpeedFlex, 1, _Fx4ParametersFlex);
}
if (_Fx4SpeedSpiral != 0.0)
{
fxUV = Spiral(fxUV, _Fx4SpeedSpiral, 1, _Fx4ParametersSpiral);
}
if (_Fx3SpeedFrameAni != 0.0)
{
fxUV = FrameAni(fxUV, _Fx4SpeedFrameAni, 1, _Fx4ParametersFrameAni);
}
fxColor = tex2D(_Fx4Tex, fxUV).rgb * concentration;
if (_Fx4SpeedFlash != 0.0)
{
if (fxColor.r > 0.001 || fxColor.g > 0.001 || fxColor.b > 0.001)
{
fxColor.rgb *= Flash(fxUV, _Fx4SpeedFlash, 1, _Fx4ParametersFlash);
}
}
mColor.rgb += fxColor;
#endif_ENABLE_FX4 END
half4 color = (tex2D(_MainTex, mTexcoord) + _TextureSampleAdd) * mColor;
#else
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
#endif
#ifdef UNITY_UI_CLIP_RECT
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
#endif
#ifdef UNITY_UI_ALPHACLIP
clip(color.a - 0.001);
#endif
return color;
}
ENDCG
}
}
}