效果:
案例:新仙剑,王者之剑。
在切换场景的时候,就会有这样的全屏扭曲效果。
思路:
1.用GrabPass抓屏到一张纹理中。
2.进行扭曲,绘制到UGUI的Image上。
准备:
去官网下载Unity内置Shader,当前最新版本:builtin_shaders-5.3.1f1
http://unity3d.com/cn/get-unity/download/archive
里面有Image用的默认Shader:Sprites-Default
我们要在这个shader的基础上加上扭曲效果。
GrabPass比较耗,加上我没有好看的场景,这里就用一张全屏的背景图进行扭曲了。
代码中//–add 就是在原来基础上添加部分
Shader "Custom/ImageSwirl"
{
Properties
{
[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
_Color("Tint", Color) = (,,,)
[MaterialToggle] PixelSnap("Pixel snap", Float) =
} SubShader
{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
"PreviewType" = "Plane"
"CanUseSpriteAtlas" = "True"
} Cull Off
Lighting Off
ZWrite Off
Blend One OneMinusSrcAlpha //-----add
GrabPass
{
"_MyGrabTex"
}
//--------- Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ PIXELSNAP_ON
#include "UnityCG.cginc" struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
}; struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
}; fixed4 _Color; //------------add
float _Radius;
float _Angle;
sampler2D _MyGrabTex;
float2 swirl(float2 uv);
float2 swirl(float2 uv)
{
//先减去贴图中心点的纹理坐标,这样是方便旋转计算
uv -= float2(0.5, 0.5); //计算当前坐标与中心点的距离。
float dist = length(uv); //计算出旋转的百分比
float percent = (_Radius - dist) / _Radius; if (percent < 1.0 && percent >= 0.0)
{
//通过sin,cos来计算出旋转后的位置。
float theta = percent * percent * _Angle * 8.0;
float s = sin(theta);
float c = cos(theta);
//uv = float2(dot(uv, float2(c, -s)), dot(uv, float2(s, c)));
uv = float2(uv.x*c - uv.y*s, uv.x*s + uv.y*c);
} //再加上贴图中心点的纹理坐标,这样才正确。
uv += float2(0.5, 0.5); return uv;
}
//--------------- v2f vert(appdata_t IN)
{
v2f OUT;
OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
OUT.texcoord = IN.texcoord;
OUT.color = IN.color * _Color;
#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap(OUT.vertex);
#endif return OUT;
} sampler2D _MainTex;
sampler2D _AlphaTex;
float _AlphaSplitEnabled; fixed4 SampleSpriteTexture(float2 uv)
{
fixed4 color = tex2D(_MainTex, uv); //----------modify
//fixed4 color = tex2D(_MyGrabTex, float2(uv.x,1-uv.y));
//----------- #if UNITY_TEXTURE_ALPHASPLIT_ALLOWED
if (_AlphaSplitEnabled)
color.a = tex2D(_AlphaTex, uv).r;
#endif //UNITY_TEXTURE_ALPHASPLIT_ALLOWED return color;
} fixed4 frag(v2f IN) : SV_Target
{
//---add
IN.texcoord = swirl(IN.texcoord);
//-------- fixed4 c = SampleSpriteTexture(IN.texcoord) * IN.color;
c.rgb *= c.a;
return c;
}
ENDCG
}
}
}
核心:
//uv = float2(dot(uv, float2(c, -s)), dot(uv, float2(s, c)));
uv = float2(uv.x*c - uv.y*s, uv.x*s + uv.y*c);
我的另一篇文章:基础知识:Q&A 中有对旋转矩阵进行简单推导。
C#脚本:以时间驱动来增长角度和半径
using UnityEngine;
using System.Collections;
using UnityEngine.UI; public class Swirl : MonoBehaviour
{
float angle = ;
float radius = 0.1f;
Material mat;
void Start ()
{
mat = this.GetComponent<Image>().material; //延迟2秒开始,每隔0.2s调用一次
InvokeRepeating("DoSwirl", 2f, 0.2f);
} void DoSwirl()
{
angle += 1f;
radius += 0.1f; mat.SetFloat("_Angle",angle);
mat.SetFloat("_Radius",radius); //rest
if (radius >= 0.6f)
{
angle = ;
radius = 0.1f;
}
}
}
- 本文固定链接: http://www.shihuanjue.com/?p=284
- 转载请注明: 乔 2016年01月11日 于 是幻觉 发表