示意
2种效果,一种边缘模糊,一种边缘清晰。对应2种材质。
闭眼效果.gif
说明
将Img的材质设置为使用了Blink Shader的材质。
Shader
Blink(边缘模糊)
材质默认参数
_img.material.SetVector("_Param", new Vector4(0.6f, y, 1, 1));
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
Shader "Custom/Blink"
{
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)]
_Param("Param", vector) = (0.6, 0.3, 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
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;
UNITY_VERTEX_OUTPUT_STEREO
};
sampler2D _MainTex;
fixed4 _Color;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
float4 _MainTex_ST;
half3 _Param;
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);
OUT.color = v.color * _Color;
return OUT;
}
fixed4 frag(v2f IN) : SV_Target
{
//half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
half4 color = IN.color;
float x = IN.texcoord.x - 0.5;
float y = IN.texcoord.y - 0.5;
float oval = x * x / (_Param.x * _Param.x) + y * y / (_Param.y * _Param.y);
color.a = oval;
#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
}
}
}
Blink2(边缘清晰)
材质默认参数
_img.material.SetFloat("_Height", y);
//对图片的mask处理,只有椭圆部分
Shader "Custom/Blink2"
{
Properties
{
_MainTex("Base (RGB), Alpha (A)", 2D) = "black" {}
_CenterX("CenterX", float) = 0.5
_CenterY("CenterY", float) = 0.5
_Width("Width", float) = 1.8
_Height("Height", float) = 0.15
_LengthRate("LengthRate", float) = 0.1
_LengthRateTransition("LengthRateLerp", float) = 0.01
}
SubShader
{
LOD 200
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
Pass
{
Cull Off
Lighting Off
ZWrite Off
Fog{ Mode Off }
Offset -1,-1
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
half4 _MainTex_ST;
half _CenterX;
half _CenterY;
half _Width;
half _Height;
half _LengthRate;
half _LengthRateTransition;
struct appdata_t
{
half4 vertex : POSITION;
half2 texcoord : TEXCOORD0;
fixed4 color : COLOR;
};
struct v2f
{
half4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
fixed4 color : COLOR;
};
v2f o;
v2f vert(appdata_t v)
{
o.vertex = UnityObjectToClipPos(v.vertex);
o.texcoord = v.texcoord;
o.color = v.color;
return o;
}
fixed4 frag(v2f IN) : COLOR
{
float2 pt = IN.texcoord - float2(_CenterX,(1 - _CenterY));
float h = (pt.x*pt.x) / (_Width*_Width) + (pt.y*pt.y) / (_Height*_Height);
float4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
float sub = _LengthRate - h;
if (h < _LengthRate && sub < _LengthRateTransition)
{
c.a = c.a - sub / _LengthRateTransition ;
return c;
}
else if (h < _LengthRate)
{
discard;
}
return c;
}
ENDCG
}
}
SubShader
{
LOD 100
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
Pass
{
Cull Off
Lighting Off
ZWrite Off
Fog{ Mode Off }
Offset -1,-1
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
ColorMaterial AmbientAndDiffuse
SetTexture[_MainTex]
{
Combine Texture * Primary
}
}
}
}
测试代码
闭眼效果的y值变化using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Blink : MonoBehaviour
{
[SerializeField]
private Image _img;
[SerializeField,Header("最后一组的duration无实际作用!")]
private BlinkData[] _data;
[SerializeField]
private Material[] _mats;
private int _curMatId;
private IEnumerator _blinkCoroutine;
private void OnEnable()
{
_curMatId = 0;
}
private void OnDestroy()
{
SetValue(0);
}
public void ChangeMat()
{
_curMatId++;
if (_curMatId >= _mats.Length)
{
_curMatId = 0;
}
_img.material = _mats[_curMatId];
}
public void PlayBlink()
{
if (_blinkCoroutine != null)
{
StopCoroutine(_blinkCoroutine);
_blinkCoroutine = null;
}
_blinkCoroutine = BlinkCoroutine();
StartCoroutine(_blinkCoroutine);
}
IEnumerator BlinkCoroutine()
{
SetValue(_data[0].Value);
for (int i = 0; i < _data.Length - 1; i++)
{
var begin = _data[i].Value;
var end = _data[i + 1].Value;
var duration = _data[i].Duration;
var timer = 0f;
while (timer < duration)
{
SetValue(Mathf.Lerp(begin, end, timer / duration));
timer += Time.deltaTime;
yield return null;
}
SetValue(end);
}
}
public void SetValue(float y)
{
if (_curMatId == 0)
{
_img.material.SetVector("_Param", new Vector4(0.6f, y, 1, 1));
}
else if (_curMatId == 1)
{
_img.material.SetFloat("_Height", y);
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
ChangeMat();
}
if (Input.GetKeyDown(KeyCode.Space))
{
PlayBlink();
}
}
[System.Serializable]
private class BlinkData
{
public float Value;
public float Duration;
}
}
网友评论