壓扁效果
利用這個可以實(shí)現(xiàn)《跑跑卡丁車》那種被門壓扁然后復(fù)原的效果注益。
主要思路就是從上到下對頂點(diǎn)進(jìn)行偏移。
首先是給出頂和底的Y坐標(biāo)晾匠,以便對所有頂點(diǎn)的Y坐標(biāo)進(jìn)行歸一化:
//Properties
_TopY("Top Y", Float) = 0 //The top Y of the GameObject in world coord
_BottomY("Bottom Y", Float) = 0
//CGPROGRAM
float GetNormalizedDist(float worldPosY)
{
float range = _TopY - _BottomY;
float border = _TopY;
float dist = abs(worldPosY - border);
float normalizedDist = saturate(dist / range);
return normalizedDist;
}
//Vertex
float worldPosY = mul(unity_ObjectToWorld, v.vertex).y;
float normalizedDist = GetNormalizedDist(worldPosY);
然后就是根據(jù)我們的控制值呀癣,讓對應(yīng)的頂點(diǎn)進(jìn)行偏移:
float3 localNegativeY = mul(unity_WorldToObject, float4(0, -1, 0, 1)).xyz;
float val = max(0, _Control - normalizedDist);
v.vertex.xyz += localNegativeY * val;
被門吸收
類似被一扇特殊的門給吸收了食磕,或者反過來是從門那里產(chǎn)生球出來。
其實(shí)思路和上面的壓扁效果是相近的答憔,都是對頂點(diǎn)進(jìn)行偏移味赃,只不過這個是向上偏移,并且對超過頂端的部分進(jìn)行clip虐拓。
//vertex
float3 localPositiveY = mul(unity_WorldToObject, float4(0, 1, 0, 1)).xyz;
float normalizedDist = GetNormalizedDist(worldPos.y);
float val = max(0, _Control - normalizedDist);
v.vertex.xyz += localPositiveY * val;
//fragment
clip(_TopY - i.worldPos.y);
黑洞吸收
這個是上面[被門吸收]的進(jìn)一步改變心俗,這次頂點(diǎn)的移動方向改為向某個點(diǎn)(即圖中黑洞),然后對X方向超過黑洞的部分clip掉。
//Vertex
float3 toBlackHole = mul(unity_WorldToObject, (_BlackHolePos - worldPos)).xyz;
float normalizedDist = GetNormalizedDist(worldPos.x);
float val = max(0, _Control - normalizedDist);
v.vertex.xyz += toBlackHole * val;
//Fragment
clip(_BlackHolePos.x - i.worldPos.x);
殘影
思路是另外用一個Pass來渲染殘影城榛,而殘影有兩個主要實(shí)現(xiàn)點(diǎn)揪利,其一是偏離本位,其二是殘影自身的抖動狠持。
首先是殘影偏離本位疟位,這個比較簡單,向特定方向整體移動殘影即可:
v.vertex += _Offset * cos(_Time.y * _ShakeSpeed) * _ShakeDir; //偏移
然后就是讓殘影抖動喘垂,我這里是讓本地坐標(biāo)十倍x(即原來x的第一位小數(shù))的偶數(shù)部分頂點(diǎn)進(jìn)行偏移:
float yOffset = 0.5 * (floor(v.vertex.x * 10) % 2);
v.vertex += _ShakeLevel * yOffset * sin(_Time.y * _ShakeSpeed) * _ShakeDir; //抖動
渲染殘影的主要代碼如下:
v2f vert(appdata_base v)
{
float yOffset = 0.5 * (floor(v.vertex.x * 10) % 2);
v2f o;
v.vertex += _Offset * cos(_Time.y * _ShakeSpeed) * _ShakeDir * _Control; //偏移
v.vertex += _ShakeLevel * yOffset * sin(_Time.y * _ShakeSpeed) * _ShakeDir * _Control; //抖動
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return fixed4(tex2D(_MainTex, i.uv).rgb * _GhostColor, _GhostAlpha);
}
折紙
思路是對頂點(diǎn)以折疊處為中心進(jìn)行旋轉(zhuǎn)甜刻。如果只是折疊一邊,則只旋轉(zhuǎn)一邊正勒;如果折疊兩邊得院,則兩邊一起旋轉(zhuǎn)
主要代碼如下:
float angle = _FoldAngle;
float r = _FoldPos - v.vertex.x;
#if ENABLE_DOUBLE
if(r <= 0)
angle = 360 - _FoldAngle;
#else
if(r <= 0)
angle = 180;
#endif
v.vertex.x = _FoldPos + r * cos(angle * UNITY_PI / 180);
v.vertex.y = r * sin(angle * UNITY_PI / 180);