需求
需要在棋盘格上显示两种形状 Tint,一种是十字形,一种是矩形
具有两种形状的、有移动动画的 Tint 的棋盘格 Shader
本来是想沿用我之前的写法
Shader "Unlit/UnlitGrid"
{
Properties
{
[PerRendererData] _MainTex ("Texture", 2D) = "white" {}
_MainTexScale ("Main Texture Scale", float) = 1
_GridSize ("Grid Size", float) = 1
[FloatRange] _GridLineSize ("Grid Line Size", Range(0, 1)) = 0.02
_LineColor ("Line Color", Color) = (0.7, 0.7, 0.7, 1)
[FloatRange] _TintType ("Tint Type", Range(0, 1)) = 0
_ReachableTint ("Reachable Tint", Color) = (0.9, 0.9, 0.9, 1)
_UnreachableTint ("Unreachable Tint", Color) = (0.6, 0.6, 0.6, 1)
_TintCenter("Tint Center", Vector) = (0, 0, 0, 0)
_TintRadius("Tint Radius", float) = 1
_TintPower("Tint Power", float) = 0
_TintSpreadTime("Tint Spread Time", float) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float4 worldSpacePos : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _MainTexScale;
float _GridSize;
float _GridLineSize;
float4 _LineColor;
float _TintType;
float4 _ReachableTint;
float4 _UnreachableTint;
vector _TintCenter;
float _TintRadius;
float _TintPower;
float _TintSpreadTime;
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.worldSpacePos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
float get_dis(float2 vec)
{
float dis_manhattan = abs(vec.x) + abs(vec.y);
float dis_chebyshev = max(abs(vec.x), abs(vec.y));
return lerp(dis_manhattan, dis_chebyshev, _TintType);
}
fixed4 add_tint(fixed4 col, float2 ipos, float2 fpos)
{
float itime = floor(_TintSpreadTime); // integer time
float ftime = frac(_TintSpreadTime); // fraction time
float2 tint_center_to_ipos = ipos - floor(_TintCenter/_GridSize);
float dist_tint_center_to_ipos = get_dis(tint_center_to_ipos);
float stationary_reachable = step(dist_tint_center_to_ipos, itime + 0.001);
float spreading_reachable = step(dist_tint_center_to_ipos, itime + 1.001) - step(dist_tint_center_to_ipos, itime + 0.001);
// move
float2 move_dir = tint_center_to_ipos/(length(tint_center_to_ipos) + 0.1f);
float2 tint_grid_center = float2(0.5, 0.5) - move_dir * (0.5f - ftime/2.0);
// scale
float2 fpos_to_grid_center = fpos - tint_grid_center;
float dist_fpos_to_grid_center = max(abs(fpos_to_grid_center.x), abs(fpos_to_grid_center.y));
spreading_reachable *= step(dist_fpos_to_grid_center, ftime/2.0);
// add tint
float radius_reachable = step(dist_tint_center_to_ipos, _TintRadius + 0.001);
float reachable = (stationary_reachable + spreading_reachable) * radius_reachable;
fixed4 tint = col * _UnreachableTint * (1.0 - reachable) + col * _ReachableTint * reachable;
return lerp(col, tint, _TintPower);
}
fixed4 add_grid(fixed4 col, float2 fpos)
{
float scaled_line_size = _GridLineSize/_GridSize;
float2 bl = step(float2(scaled_line_size, scaled_line_size), fpos); // bottom-left
float2 tr = step(float2(scaled_line_size, scaled_line_size), float2(1.0, 1.0) - fpos); // top-right
float grid_brightness = 1.0 - bl.x * bl.y * tr.x * tr.y;
col = col * (1.0 - grid_brightness) + _LineColor * grid_brightness;
return col;
}
fixed4 frag (v2f i) : SV_Target
{
float2 st = i.worldSpacePos.xy / _GridSize;
float2 st_world = i.worldSpacePos.xy/_MainTexScale;
float2 ipos = floor(st); // integer
float2 fpos = frac(st); // fraction
fixed4 col = tex2D(_MainTex, st_world);
col = add_tint(col, ipos, fpos);
col = add_grid(col, fpos);
return col;
}
ENDCG
}
}
}
切换显示 Tint 方法的核心在
float get_dis(float2 vec)
{
float dis_manhattan = abs(vec.x) + abs(vec.y);
float dis_chebyshev = max(abs(vec.x), abs(vec.y));
return lerp(dis_manhattan, dis_chebyshev, _TintType);
}
dis_manhattan 是十字形,dis_chebyshev 是矩形
脚本用法:
private SpriteRenderer spriteRenderer;
private Sequence tintSeq = null;
private void ShowReachableTint(DraggableChess chess)
{
// 如果已经点选过一次棋子,现在是正在拖动的阶段,那么不用重新显示一遍了
if(hasClickOnce) return;
Vector3 centerPos = chess.transform.position;
int reachableSteps = chess.ReachableSteps;
// tint
spriteRenderer.material.SetVector("_TintCenter", new Vector4(centerPos.x, centerPos.y, 0f, 0f));
spriteRenderer.material.SetFloat("_TintRadius", reachableSteps);
spriteRenderer.material.SetFloat("_TintPower", 0f);
spriteRenderer.material.SetFloat("_TintSpreadTime", 0f);
tintSeq.Pause();
tintSeq = DOTween.Sequence();
tintSeq.Insert(0f, spriteRenderer.material.DOFloat(1f, "_TintPower", 0.3f));
tintSeq.Insert(0f, spriteRenderer.material
.DOFloat(reachableSteps, "_TintSpreadTime", 1f)
.SetEase(Ease.OutQuint));
tintSeq.Play();
}
public void HideReachableTint(DraggableChess chess)
{
spriteRenderer.material.DOFloat(0f, "_TintPower", 0.3f);
}
矩形 Tint 不使用延展效果
矩形 Tint 如果不使用延展效果的话,Shader 可以写成
Shader "Unlit/UnlitGrid"
{
Properties
{
[PerRendererData] _MainTex ("Texture", 2D) = "white" {}
_MainTexScale ("Main Texture Scale", float) = 1
_GridSize ("Grid Size", float) = 1
[FloatRange] _GridLineSize ("Grid Line Size", Range(0, 1)) = 0.02
_LineColor ("Line Color", Color) = (0.7, 0.7, 0.7, 1)
[FloatRange] _TintType ("Tint Type", Range(0, 1)) = 0
_ReachableTint ("Reachable Tint", Color) = (0.9, 0.9, 0.9, 1)
_UnreachableTint ("Unreachable Tint", Color) = (0.6, 0.6, 0.6, 1)
_TintCenter("Tint Center", Vector) = (0, 0, 0, 0)
_TintRadius("Tint Radius", float) = 1
_TintPower("Tint Power", float) = 0
_TintSpreadTime("Tint Spread Time", float) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float4 worldSpacePos : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _MainTexScale;
float _GridSize;
float _GridLineSize;
float4 _LineColor;
float _TintType;
float4 _ReachableTint;
float4 _UnreachableTint;
vector _TintCenter;
float _TintRadius;
float _TintPower;
float _TintSpreadTime;
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.worldSpacePos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
float get_dis_manhattan(float2 vec)
{
return abs(vec.x) + abs(vec.y);
}
float get_dis_chebyshev(float2 vec)
{
return max(abs(vec.x), abs(vec.y));
}
fixed4 add_cross_tint(fixed4 col, float2 ipos, float2 fpos)
{
float itime = floor(_TintSpreadTime); // integer time
float ftime = frac(_TintSpreadTime); // fraction time
float2 tint_center_to_ipos = ipos - floor(_TintCenter/_GridSize);
float dist_tint_center_to_ipos = get_dis_manhattan(tint_center_to_ipos);
float stationary_reachable = step(dist_tint_center_to_ipos, itime + 0.001);
float spreading_reachable = step(dist_tint_center_to_ipos, itime + 1.001) - step(dist_tint_center_to_ipos, itime + 0.001);
// move
float2 move_dir = tint_center_to_ipos/(length(tint_center_to_ipos) + 0.1f);
float2 tint_grid_center = float2(0.5, 0.5) - move_dir * (0.5f - ftime/2.0);
// scale
float2 fpos_to_grid_center = fpos - tint_grid_center;
float dist_fpos_to_grid_center = max(abs(fpos_to_grid_center.x), abs(fpos_to_grid_center.y));
spreading_reachable *= step(dist_fpos_to_grid_center, ftime/2.0);
// add tint
float radius_reachable = step(dist_tint_center_to_ipos, _TintRadius + 0.001);
float reachable = (stationary_reachable + spreading_reachable) * radius_reachable;
fixed4 tint = col * _UnreachableTint * (1.0 - reachable) + col * _ReachableTint * reachable;
return lerp(col, tint, _TintPower);
}
fixed4 add_rect_tint(fixed4 col, float2 ipos)
{
float2 tint_center_to_ipos = ipos - floor(_TintCenter/_GridSize);
float dist_tint_center_to_ipos = get_dis_chebyshev(tint_center_to_ipos);
float radius_reachable = step(dist_tint_center_to_ipos, _TintRadius + 0.001);
fixed4 tint = col * _UnreachableTint * (1.0 - radius_reachable) + col * _ReachableTint * radius_reachable;
return lerp(col, tint, _TintPower);
}
fixed4 add_grid(fixed4 col, float2 fpos)
{
float scaled_line_size = _GridLineSize/_GridSize;
float2 bl = step(float2(scaled_line_size, scaled_line_size), fpos); // bottom-left
float2 tr = step(float2(scaled_line_size, scaled_line_size), float2(1.0, 1.0) - fpos); // top-right
float grid_brightness = 1.0 - bl.x * bl.y * tr.x * tr.y;
col = col * (1.0 - grid_brightness) + _LineColor * grid_brightness;
return col;
}
fixed4 frag (v2f i) : SV_Target
{
float2 st = i.worldSpacePos.xy / _GridSize;
float2 st_world = i.worldSpacePos.xy/_MainTexScale;
float2 ipos = floor(st); // integer
float2 fpos = frac(st); // fraction
fixed4 col = tex2D(_MainTex, st_world);
col = lerp(add_cross_tint(col, ipos, fpos), add_rect_tint(col, ipos), _TintType);
col = add_grid(col, fpos);
return col;
}
ENDCG
}
}
}
拖动矩形框的脚本示例:
private void OnPropDragBegin(PropChess propChess)
{
_propChess = propChess;
spriteRenderer.material.SetFloat("_TintType", 1f);
spriteRenderer.material.SetFloat("_TintRadius", propChess.ReachableSteps);
spriteRenderer.material.SetFloat("_TintPower", 0f);
spriteRenderer.material.DOFloat(1f, "_TintPower", 0.3f);
}
private void OnPropDragEnd()
{
_propChess = null;
spriteRenderer.material.DOFloat(0f, "_TintPower", 0.3f);
}
void Update()
{
if(!_propChess) return;
spriteRenderer.material.SetVector("_TintCenter", new Vector4(_propChess.transform.position.x, _propChess.transform.position.y, 0f, 0f));
}
效果:
透明框的尝试
现在策划要求这个 Tint 是覆盖在整个界面的上方的
于是我拆成了两个部分,一个部分是显示棋盘格的,一个部分是盖在世界棋子的上方,提供 Tint 的
画棋盘格的 Shader
Shader "Unlit/UnlitGrid"
{
Properties
{
[PerRendererData] _MainTex ("Texture", 2D) = "white" {}
_MainTexScale ("Main Texture Scale", float) = 1
_GridSize ("Grid Size", float) = 1
[FloatRange] _GridLineSize ("Grid Line Size", Range(0, 1)) = 0.02
_LineColor ("Line Color", Color) = (0.7, 0.7, 0.7, 1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float4 worldSpacePos : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _MainTexScale;
float _GridSize;
float _GridLineSize;
float4 _LineColor;
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.worldSpacePos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
fixed4 add_grid(fixed4 col, float2 fpos)
{
float scaled_line_size = _GridLineSize/_GridSize;
float2 bl = step(float2(scaled_line_size, scaled_line_size), fpos); // bottom-left
float2 tr = step(float2(scaled_line_size, scaled_line_size), float2(1.0, 1.0) - fpos); // top-right
float grid_brightness = 1.0 - bl.x * bl.y * tr.x * tr.y;
col = col * (1.0 - grid_brightness) + _LineColor * grid_brightness;
return col;
}
fixed4 frag (v2f i) : SV_Target
{
float2 st = i.worldSpacePos.xy / _GridSize;
float2 st_world = i.worldSpacePos.xy/_MainTexScale;
float2 fpos = frac(st); // fraction
fixed4 col = tex2D(_MainTex, st_world);
col = add_grid(col, fpos);
return col;
}
ENDCG
}
}
}
画 Tint 的 Shader
Shader "Unlit/UnlitGridTint"
{
Properties
{
[PerRendererData] _MainTex ("Texture", 2D) = "white" {}
_GridSize ("Grid Size", float) = 1
[FloatRange] _TintType ("Tint Type", Range(0, 1)) = 0
_ReachableTint ("Reachable Tint", Color) = (0.9, 0.9, 0.9, 1)
_UnreachableTint ("Unreachable Tint", Color) = (0.6, 0.6, 0.6, 1)
_TintCenter("Tint Center", Vector) = (0, 0, 0, 0)
_TintRadius("Tint Radius", float) = 1
_TintPower("Tint Power", float) = 0
_TintSpreadTime("Tint Spread Time", float) = 0
}
SubShader
{
Tags { "RenderType"="Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float4 worldSpacePos : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _GridSize;
float _TintType;
float4 _ReachableTint;
float4 _UnreachableTint;
vector _TintCenter;
float _TintRadius;
float _TintPower;
float _TintSpreadTime;
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.worldSpacePos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
float get_dis_manhattan(float2 vec)
{
return abs(vec.x) + abs(vec.y);
}
float get_dis_chebyshev(float2 vec)
{
return max(abs(vec.x), abs(vec.y));
}
fixed4 add_cross_tint(float2 ipos, float2 fpos)
{
float itime = floor(_TintSpreadTime); // integer time
float ftime = frac(_TintSpreadTime); // fraction time
float2 tint_center_to_ipos = ipos - floor(_TintCenter/_GridSize);
float dist_tint_center_to_ipos = get_dis_manhattan(tint_center_to_ipos);
float stationary_reachable = step(dist_tint_center_to_ipos, itime + 0.001);
float spreading_reachable = step(dist_tint_center_to_ipos, itime + 1.001) - step(dist_tint_center_to_ipos, itime + 0.001);
// move
float2 move_dir = tint_center_to_ipos/(length(tint_center_to_ipos) + 0.1f);
float2 tint_grid_center = float2(0.5, 0.5) - move_dir * (0.5f - ftime/2.0);
// scale
float2 fpos_to_grid_center = fpos - tint_grid_center;
float dist_fpos_to_grid_center = max(abs(fpos_to_grid_center.x), abs(fpos_to_grid_center.y));
spreading_reachable *= step(dist_fpos_to_grid_center, ftime/2.0);
// add tint
float radius_reachable = step(dist_tint_center_to_ipos, _TintRadius + 0.001);
float reachable = (stationary_reachable + spreading_reachable) * radius_reachable;
// here dont multi color, because no need
return lerp(_UnreachableTint, _ReachableTint, reachable);
}
fixed4 add_rect_tint(float2 ipos)
{
float2 tint_center_to_ipos = ipos - floor(_TintCenter/_GridSize);
float dist_tint_center_to_ipos = get_dis_chebyshev(tint_center_to_ipos);
float radius_reachable = step(dist_tint_center_to_ipos, _TintRadius + 0.001);
// here dont multi color, because no need
return lerp(_UnreachableTint, _ReachableTint, radius_reachable);
}
fixed4 frag (v2f i) : SV_Target
{
float2 st = i.worldSpacePos.xy / _GridSize;
float2 ipos = floor(st); // integer
float2 fpos = frac(st); // fraction
fixed4 col = lerp(add_cross_tint(ipos, fpos), add_rect_tint(ipos), _TintType);
col.a = _TintPower;
// test
// col = tex2D(_MainTex, st);
return col;
}
ENDCG
}
}
}
但是现在出现一个问题,我这个透明的 sprite 会覆盖下面的使用了 sprite-default 材质的棋子,奇怪的是,没有覆盖掉使用了我定义的 Unlit/UnlitGrid 的棋子
以下是我移动这个透明的 sprite 时的效果
可以看到,有些东西被覆盖了,有些东西没有
为了测试,我还用了一个半透明的贴图,然后在片元着色器中输出直接采样得到的 col
// test
col = tex2D(_MainTex, st);
结果还是一样的
我去看了 sprite-default 的写法,感觉大部分都差别不大,除了他还用了一些透明材质,不知道是怎么来的
之后我一个个把官方 Shader 相关的注释试试,发现起作用的是
SubShader
{
Tags {
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
}
中的 "Queue"="Transparent" 这一行
试了一下 Overlay 也行
于是新的 Tint Shader 写成
Shader "Unlit/UnlitGridTint"
{
Properties
{
[PerRendererData] _MainTex ("Texture", 2D) = "white" {}
_GridSize ("Grid Size", float) = 1
[FloatRange] _TintType ("Tint Type", Range(0, 1)) = 0
_ReachableTint ("Reachable Tint", Color) = (0.9, 0.9, 0.9, 1)
_UnreachableTint ("Unreachable Tint", Color) = (0.6, 0.6, 0.6, 1)
_TintCenter("Tint Center", Vector) = (0, 0, 0, 0)
_TintRadius("Tint Radius", float) = 1
_TintPower("Tint Power", float) = 0
_TintSpreadTime("Tint Spread Time", float) = 0
}
SubShader
{
Tags {
"Queue"="Overlay"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
}
Cull Off
Lighting Off
ZWrite Off
Blend One OneMinusSrcAlpha
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float4 worldSpacePos : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _GridSize;
float _TintType;
float4 _ReachableTint;
float4 _UnreachableTint;
vector _TintCenter;
float _TintRadius;
float _TintPower;
float _TintSpreadTime;
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.worldSpacePos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
float get_dis_manhattan(float2 vec)
{
return abs(vec.x) + abs(vec.y);
}
float get_dis_chebyshev(float2 vec)
{
return max(abs(vec.x), abs(vec.y));
}
fixed4 add_cross_tint(float2 ipos, float2 fpos)
{
float itime = floor(_TintSpreadTime); // integer time
float ftime = frac(_TintSpreadTime); // fraction time
float2 tint_center_to_ipos = ipos - floor(_TintCenter/_GridSize);
float dist_tint_center_to_ipos = get_dis_manhattan(tint_center_to_ipos);
float stationary_reachable = step(dist_tint_center_to_ipos, itime + 0.001);
float spreading_reachable = step(dist_tint_center_to_ipos, itime + 1.001) - step(dist_tint_center_to_ipos, itime + 0.001);
// move
float2 move_dir = tint_center_to_ipos/(length(tint_center_to_ipos) + 0.1f);
float2 tint_grid_center = float2(0.5, 0.5) - move_dir * (0.5f - ftime/2.0);
// scale
float2 fpos_to_grid_center = fpos - tint_grid_center;
float dist_fpos_to_grid_center = max(abs(fpos_to_grid_center.x), abs(fpos_to_grid_center.y));
spreading_reachable *= step(dist_fpos_to_grid_center, ftime/2.0);
// add tint
float radius_reachable = step(dist_tint_center_to_ipos, _TintRadius + 0.001);
float reachable = (stationary_reachable + spreading_reachable) * radius_reachable;
// here dont multi color, because no need
return lerp(_UnreachableTint, _ReachableTint, reachable);
}
fixed4 add_rect_tint(float2 ipos)
{
float2 tint_center_to_ipos = ipos - floor(_TintCenter/_GridSize);
float dist_tint_center_to_ipos = get_dis_chebyshev(tint_center_to_ipos);
float radius_reachable = step(dist_tint_center_to_ipos, _TintRadius + 0.001);
// here dont multi color, because no need
return lerp(_UnreachableTint, _ReachableTint, radius_reachable);
}
fixed4 frag (v2f i) : SV_Target
{
float2 st = i.worldSpacePos.xy / _GridSize;
float2 ipos = floor(st); // integer
float2 fpos = frac(st); // fraction
fixed4 col = lerp(add_cross_tint(ipos, fpos), add_rect_tint(ipos), _TintType);
col.a = _TintPower;
col.rgb *= col.a;
return col;
}
ENDCG
}
}
}
效果像这样
但是这里有一个问题是,白色的 Tint 会把周围的棋子也染上色
这里主要是片元着色器最后一行强行赋值了一个东西
改成乘等于就好了
col.a *= _TintPower;
最终效果:
Tint Shader
Shader "Unlit/UnlitGridTint"
{
Properties
{
[PerRendererData] _MainTex ("Texture", 2D) = "white" {}
_GridSize ("Grid Size", float) = 1
[FloatRange] _TintType ("Tint Type", Range(0, 1)) = 0
_ReachableTint ("Reachable Tint", Color) = (0.9, 0.9, 0.9, 1)
_UnreachableTint ("Unreachable Tint", Color) = (0.6, 0.6, 0.6, 1)
_TintCenter("Tint Center", Vector) = (0, 0, 0, 0)
_TintRadius("Tint Radius", float) = 1
_TintPower("Tint Power", float) = 0
_TintSpreadTime("Tint Spread Time", float) = 0
}
SubShader
{
Tags {
"Queue"="Overlay"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
}
Cull Off
Lighting Off
ZWrite Off
Blend One OneMinusSrcAlpha
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float4 worldSpacePos : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _GridSize;
float _TintType;
float4 _ReachableTint;
float4 _UnreachableTint;
vector _TintCenter;
float _TintRadius;
float _TintPower;
float _TintSpreadTime;
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.worldSpacePos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
float get_dis_manhattan(float2 vec)
{
return abs(vec.x) + abs(vec.y);
}
float get_dis_chebyshev(float2 vec)
{
return max(abs(vec.x), abs(vec.y));
}
fixed4 add_cross_tint(float2 ipos, float2 fpos)
{
float itime = floor(_TintSpreadTime); // integer time
float ftime = frac(_TintSpreadTime); // fraction time
float2 tint_center_to_ipos = ipos - floor(_TintCenter/_GridSize);
float dist_tint_center_to_ipos = get_dis_manhattan(tint_center_to_ipos);
float stationary_reachable = step(dist_tint_center_to_ipos, itime + 0.001);
float spreading_reachable = step(dist_tint_center_to_ipos, itime + 1.001) - step(dist_tint_center_to_ipos, itime + 0.001);
// move
float2 move_dir = tint_center_to_ipos/(length(tint_center_to_ipos) + 0.1f);
float2 tint_grid_center = float2(0.5, 0.5) - move_dir * (0.5f - ftime/2.0);
// scale
float2 fpos_to_grid_center = fpos - tint_grid_center;
float dist_fpos_to_grid_center = max(abs(fpos_to_grid_center.x), abs(fpos_to_grid_center.y));
spreading_reachable *= step(dist_fpos_to_grid_center, ftime/2.0);
// add tint
float radius_reachable = step(dist_tint_center_to_ipos, _TintRadius + 0.001);
float reachable = (stationary_reachable + spreading_reachable) * radius_reachable;
// here dont multi color, because no need
return lerp(_UnreachableTint, _ReachableTint, reachable);
}
fixed4 add_rect_tint(float2 ipos)
{
float2 tint_center_to_ipos = ipos - floor(_TintCenter/_GridSize);
float dist_tint_center_to_ipos = get_dis_chebyshev(tint_center_to_ipos);
float radius_reachable = step(dist_tint_center_to_ipos, _TintRadius + 0.001);
// here dont multi color, because no need
return lerp(_UnreachableTint, _ReachableTint, radius_reachable);
}
fixed4 frag (v2f i) : SV_Target
{
float2 st = i.worldSpacePos.xy / _GridSize;
float2 ipos = floor(st); // integer
float2 fpos = frac(st); // fraction
fixed4 col = lerp(add_cross_tint(ipos, fpos), add_rect_tint(ipos), _TintType);
col.a *= _TintPower;
col.rgb *= col.a;
return col;
}
ENDCG
}
}
}