上一篇我们实现了简单的波动效果,这一篇就尝试一下扭曲的效果,如下图:
同样是使用unity的顶点与片段着色器,首先是一些准备工作:
Shader "Custom/Custom-Twirl" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
struct v2f
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
v2f vert(appdata_full v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
float4 frag(v2f i) : COLOR
{
//to do ...
}
ENDCG
}
}
FallBack "Diffuse"
}
为了得到上图的效果, 很明显,我们需要将图片的像素绕中心点进行旋转,而且像素位置距离 中心点越远,其旋转角度越大,为此,我们在片段着色器进行如下处理:
float4 frag(v2f i) : COLOR
{
float2 tc = i.uv;
tc -= float2(0.5,0.5);
float d= length(tc);//与中点的距离
float originAngle = acos(dot(tc, float2(1, 0))/d);//与x轴的夹角,还有其他方法,这个方法需要注意角度的正负
if (tc.y < 0) {
originAngle = -originAngle;
}
float angle =originAngle+ d * _Slider;/*d * _Slider是旋转角度,这里与距中点距离成比例,也可以是其他关系
_Slider是用来控制旋转程度的参数,需要先在属性里定义一下 */
tc = float2(0.5+d*cos(angle),0.5+d*sin(angle));
float3 color = tex2D(_MainTex, tc).rgb;
return float4(color, 1.0);
}
其中我们定义旋转角度与距离成正比,当然也可以由其他关系,其结果如下:
这里我们发现一个问题,如果图形不是圆的,其边缘并不适合上述处理,需要做其他调整,在unity的inspector面板中,将图片的wrap mode 作如下修改,则可恢复正常。
ML