ImageEffects_Twirl(转)

Twirl是一个全屏画面扭曲的效果,新仙剑的战斗切换有用到这个效果。

主要有三个设置:

center扭曲的中心点

radius扭曲的范围

angle扭曲的角度

用到了如下函数

Matrix4x4.TRS(Vector3 pos, Quaternion rotate,Vector3 scale)

创建一个包括位移,旋转,缩放的矩阵

Matrix4x4rotationMatrix =Matrix4x4.TRS(Vector3.zero,Quaternion.Euler(0,0, angle),Vector3.one);

然后通过material的以下函数向shader里传参数

material.SetMatrix("name",value)对应Shader里的 float4x4

material.SetVector("name",value)对应Shader里的 float4

float2 MultiplyUV (float4x4 mat, float2 inUV) {

float4 temp = float4 (inUV.x, inUV.y, 0, 0);

temp = mul (mat, temp);

return temp.xy;

}

步骤:

ImageEffects_Twirl(转)_第1张图片

脚本

(1) 通过Angle得到旋转矩阵

Matrix4x4rotationMatrix =Matrix4x4.TRS(Vector3.zero,Quaternion.Euler(0,0, angle),Vector3.one);

(2) 将矩阵和 旋转中点 及 半径传入shader.

Shader

(1) 将坐标系从左下角的坐标系 转到 以旋转中点为 原点的坐标系

vert里 o.uv = v.texcoord- _CenterRadius.xy;

ImageEffects_Twirl(转)_第2张图片

(2) 将旋转坐标系 里的uv乘以 旋转矩阵。

(3) 将uv除以 半径, 再取长度。长度超过1则为 旋转区域外,小于则在区域内

(4) 如果在区域外,则为默认offset, 在内则是旋转后的offset

脚本

usingUnityEngine;

usingSystem.Collections;

public classTwirlEffectMe :MonoBehaviour{

public Shadershader;

private Materialmat;

public Vector2radius =new Vector2(0.3F,0.3F);

publicfloatangle =50;

public Vector2center =new Vector2(0.5F,0.5F);

voidStart()

{

mat =newMaterial(shader);

}

voidOnRenderImage (RenderTexturesource,RenderTexturedestination) {

RenderDistortion (mat, source, destination, angle, center, radius);

}

publicstaticvoidRenderDistortion(Materialmaterial,RenderTexturesource,RenderTexturedestination,floatangle,Vector2center,Vector2radius)

{

Matrix4x4rotationMatrix =Matrix4x4.TRS(Vector3.zero,Quaternion.Euler(0,0, angle),Vector3.one);

material.SetMatrix("_RotationMatrix", rotationMatrix);

material.SetVector("_CenterRadius",newVector4(center.x, center.y, radius.x, radius.y));

Graphics.Blit(source, destination, material);

}

}

Shader脚本

Shader"Custom/TwirlEffectMe"{

Properties{

_MainTex ("Base (RGB)",2D) ="white"{}

}

SubShader{

Pass{

ZTestAlwaysCullOffZWriteOff

Fog{Modeoff}

CGPROGRAM

#pragmavertex vert

#pragmafragment frag

#include"UnityCG.cginc"

uniformsampler2D_MainTex;

uniformfloat4_MainTex_TexelSize;

uniformfloat4_CenterRadius;

uniformfloat4x4_RotationMatrix;

structv2f {

float4pos : POSITION;

float2uv :TEXCOORD0;

} ;

v2f vert( appdata_img v )

{

v2f o;

o.pos =mul(UNITY_MATRIX_MVP, v.vertex);

o.uv = v.texcoord- _CenterRadius.xy;

returno;

}

float4frag (v2f i) :COLOR

{

float2offset= i.uv;

float2distortedOffset = MultiplyUV (_RotationMatrix,offset.xy);

float2tmp =offset/ _CenterRadius.zw;

float2finalUV;

floatlen =length(tmp);

// out of twirl

if( len >1)

{

finalUV =offset;

}

else

{

finalUV =distortedOffset;

}

// back to normal uv coordinate

finalUV += _CenterRadius.xy;

returntex2D(_MainTex, finalUV);

}

ENDCG

}

}

Fallbackoff

}

但是运行后,发现仅仅是简单旋转。需要再加上模糊。

ImageEffects_Twirl(转)_第3张图片

分析一下,发现是由内向外从distortedOffset 渐渐向 正常offset过度的过程

于是将43行的finalUV =distortedOffset;改为

finalUV =lerp(distortedOffset,offset, len );

整体代码如下:

Shader"Custom/TwirlEffectMe"{

Properties{

_MainTex ("Base (RGB)",2D) ="white"{}

}

SubShader{

Pass{

ZTestAlwaysCullOffZWriteOff

Fog{Modeoff}

CGPROGRAM

#pragmavertex vert

#pragmafragment frag

#include"UnityCG.cginc"

uniform sampler2D_MainTex;

uniformfloat4_MainTex_TexelSize;

uniformfloat4_CenterRadius;

uniformfloat4x4_RotationMatrix;

structv2f {

float4pos : POSITION;

float2uv :TEXCOORD0;

} ;

v2f vert( appdata_img v )

{

v2f o;

o.pos =mul(UNITY_MATRIX_MVP, v.vertex);

o.uv = v.texcoord- _CenterRadius.xy;

returno;

}

float4frag (v2f i) :COLOR

{

float2offset= i.uv;

float2distortedOffset = MultiplyUV (_RotationMatrix,offset.xy);

float2tmp =offset/ _CenterRadius.zw;

float2finalUV;

floatlen =length(tmp);

// out of twirl

if( len >1)

{

finalUV =offset;

}

else

{

finalUV =lerp(distortedOffset,offset, len );

}

// back to normal uv coordinate

finalUV += _CenterRadius.xy;

returntex2D(_MainTex, finalUV);

}

ENDCG

}

}

Fallbackoff

}

点击运行,效果对了。

ImageEffects_Twirl(转)_第4张图片

你可能感兴趣的:(ImageEffects_Twirl(转))