My project have some skill buttons with cool down effect as this:
I can use 2 image to build it: gray and color image and make color image with fill property. But it’s doubled render calls. So I made a shader and a script which inherit from BaseVertexEffect.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
[RequireComponent(typeof(UnityEngine.UI.Image))]
public class GrayImage : BaseVertexEffect {
[Range(0,1)]
public float fill;
//public Color grayColor = Color.white;
[Range(0,1)]
public float grayScale = 0.7f;
public Shader grayscaleShader;
[System.Serializable]
public enum FillDirection
{
BottomTop,
TopBottom,
LeftRight,
RightLeft,
}
public FillDirection fillDirection;
UnityEngine.UI.Image image;
// Use this for initialization
protected override void Start () {
image = GetComponent<UnityEngine.UI.Image>();
image.material = new Material( grayscaleShader );
}
// Update is called once per frame
void Update () {
image.material.SetFloat("_Fill", fill );
// image.material.SetColor("_GrayColor", grayColor );
image.material.SetFloat("_GrayScale", grayScale );
}
public override void ModifyVertices (List<UIVertex> verts)
{
if (!this.IsActive ())
{
return;
}
float min = float.MaxValue;
float max = float.MinValue;
float len = 0;
for (int i = 0; i < verts.Count; i++)
{
switch( fillDirection )
{
case FillDirection.BottomTop:
case FillDirection.TopBottom:
if( verts[i].position.y < min )
min = verts[i].position.y;
if( verts[i].position.y > max )
max = verts[i].position.y;
break;
case FillDirection.LeftRight:
case FillDirection.RightLeft:
if( verts[i].position.x < min )
min = verts[i].position.x;
if( verts[i].position.x > max )
max = verts[i].position.x;
break;
}
}
len = max - min;
if( len == 0 )
return;
for (int i = 0; i < verts.Count; i++)
{
UIVertex uiVertex = verts[i];
switch( fillDirection )
{
case FillDirection.BottomTop:
uiVertex.uv1.y = (verts[i].position.y - min) / len;
break;
case FillDirection.TopBottom:
uiVertex.uv1.y = (max - verts[i].position.y) / len;
break;
case FillDirection.LeftRight:
uiVertex.uv1.y = (verts[i].position.x - min) / len;
break;
case FillDirection.RightLeft:
uiVertex.uv1.y = (max - verts[i].position.x) / len;
break;
}
verts[i] = uiVertex;
}
}
}
Shader "UI/Grayscale"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_Fill ("Fill", Range(0,1)) = 0
// _GrayColor ("Gray", Color) = (1,1,1,1)
_GrayScale ("GrayScale", Range(0,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
}
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]
Fog { Mode Off }
Blend SrcAlpha OneMinusSrcAlpha
ColorMask [_ColorMask]
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
float2 uv1 : TEXCOORD1;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
half2 texcoord : TEXCOORD0;
half2 uv1 : TEXCOORD1;
};
fixed4 _Color;
fixed _Fill;
// fixed4 _GrayColor;
fixed _GrayScale;
v2f vert(appdata_t IN)
{
v2f OUT;
OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
OUT.texcoord = IN.texcoord;
OUT.uv1 = IN.uv1;
OUT.color = IN.color * _Color;
return OUT;
}
sampler2D _MainTex;
fixed4 frag(v2f IN) : SV_Target
{
half4 color = tex2D(_MainTex, IN.texcoord);
if( IN.uv1.y > _Fill )
{
fixed grayscale = Luminance( color.rgb );
color.rgb = grayscale.xxx * _GrayScale + 1 - _GrayScale;
// color = color * _GrayColor;
}
color = color * IN.color;
clip (color.a - 0.01);
return color;
}
ENDCG
}
}
}
Wish more Effect related classes could be provide.
btw. UIVertex only provide uv0 and uv1. Could you please add more uv channels?
1788575–113799–GrayImage.cs (2.15 KB)
1788575–113800–UI-Grayscale.shader (2.06 KB)