シェーダーにおいて、頂点を移動させるというのは、よく見かけるテクニックです。頂点を移動させることにより、ウェイトアニメーションでは到底再現できないような動きを作ることもできます。また、動きはすべて数式として表現されるため、とくに規則的で連続したアニメーションを作ることに向いています。たとえば、水面や旗の揺らめきといった部分で、頂点シェーダーは非常に有用です。
今回は、頂点を上下させて波を作る頂点シェーダーの作り方を紹介します。
Contents
頂点をy軸方向に動かす
頂点を移動させるには、頂点シェーダーの中で頂点座標を加算・減算します。下のコードは例として、y座標を1だけ上昇させています。
v2f vert (appdata v)
{
v2f o;
o.vertex = v.vertex; //シェーダーに渡ってきた頂点座標をコピー
o.vertex.y += 1; //y軸方向に+1
o.vertex = UnityObjectToClipPos(o.vertex); //頂点座標をMVP変換
return o;
}
普通のスクリプトのように加算したり、減算するだけなので非常に簡単ですね。なお、シェーダーにおいては、ワールド空間にある座標は投影座標に変換する必要があるので、UnityObjectToClipPosというメソッドで変換することを忘れないようにしましょう。
頂点の移動を反復させる
頂点を一定の間隔で往復させるには、三角関数を使うといいでしょう。以下のように、_Timeというあらかじめ用意されているプロパティから時間を取り扱うことができます。なお、_Timeのxyzwは(t/20、t、t×2、t×3)というふうに、進みの違う時間がセットされているので、注意が必要です。
//o.vertex.y += 1;
o.vertex.y += sin(_Time * 100); //100倍速にしています
移動する頂点に差分を付けて波打たせる
先ほど説明したコードでは、頂点は均一にしか上下移動しませんでした。次は各頂点が微妙に差を付けながら上下するように書き換えてみます。それぞれの頂点が持つx座標を利用して_Timeに差を付けてみます。
//o.vertex.y += sin(_Time * 100);
o.vertex.y += sin(v.vertex.x + _Time * 100);
すると、以下のようにシェーダーが波打つようになりました。もし、波打つ方向を変えたい場合や軸方向を調整したい場合は、vertex.xやvertex.zに差し替えてみてください。
シェーダー全体
ここまで紹介してきたシェーダーの全容は、以下の通りです。
Shader "CAGraphicsAcademy/WavedVertex"
{
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = v.vertex;
o.vertex.y += sin(v.vertex.x + _Time * 100);
o.vertex = UnityObjectToClipPos(o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return float4(1, 0, 0, 0);
}
ENDCG
}
}
}
まとめ
頂点移動するシェーダーの作り方について紹介してきましたが、すこし応用することで旗や水面といったものも表現することができます。このほかにもシェーダーの作り方を紹介しているので、ぜひご覧になっていってください。