ImageEffects_Twirl(轉)

Twirl是一個全屏畫面扭曲的效果,新仙劍的戰(zhàn)斗切換有用到這個效果。

主要有三個設置:

center扭曲的中心點

radius扭曲的范圍

angle扭曲的角度

用到了如下函數(shù)

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

創(chuàng)建一個包括位移,旋轉,縮放的矩陣

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

然后通過material的以下函數(shù)向shader里傳參數(shù)

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;

}

步驟:

腳本

(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;

(2) 將旋轉坐標系 里的uv乘以 旋轉矩陣。

(3) 將uv除以 半徑, 再取長度。長度超過1則為 旋轉區(qū)域外,小于則在區(qū)域內

(4) 如果在區(qū)域外,則為默認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

}

但是運行后,發(fā)現(xiàn)僅僅是簡單旋轉。需要再加上模糊。

分析一下,發(fā)現(xiàn)是由內向外從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

}

點擊運行,效果對了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容