おもちゃラボ

Unityで遊びを作ってます

【Unityシェーダ入門】uvスクロールで水面を動かす

シェーダを使ってテクスチャを動かすことで、水面を表現してみます。テクスチャを動かせれば水面だけではなく、滝や川など様々なものを表現できるようになります。今回はテクスチャを動かすために、uvスクロールという方法を使います。

f:id:nn_hokuson:20161020201348p:plain

今回の内容は次のような感じです。

UVスクロールとは

前の記事で、ポリゴンにテクスチャを貼り付けるときに、テクスチャのどこの部分を貼り付けるのかは、u座標とv座標を使って指定することを説明しました。

nn-hokuson.hatenablog.com

テクスチャの左下が(u, v)=(0, 0)、右上が(u, v)=(1, 1)になります。テクスチャをスクロールためには、フレームごとにuv座標にオフセットを足していきます。

f:id:nn_hokuson:20161016170315p:plain

ただし、サーフェイスシェーダは前フレームの状態を覚えておくことはできず、分かるのは「テクスチャのどこを使うか」だけです。したがって「前フレームのuv座標にオフセットを足していく」ことはできません。

そこで「フレームごとにuv座標にオフセットを足す」かわりに、「uv座標にスクロール速度✕時間を足す」方法を使います。スクロール速度✕時間=移動距離なので、結局は同じことをしていますが、この方法を使えば非常に簡単なプログラムでuvスクロールが実現できます。

ステージと水面を作る

まずは水面を表示するためのパネルと、水面の周りの地形(Terrain)を配置しましょう。まずはヒエラルキービューから「Create」→「3D Object」→「Terrain」でテラインを配置します。

f:id:nn_hokuson:20161016171707p:plain

Terrainの地形ツールを使って水面を表示するための窪地を作ります。ついでにTerrainにテクスチャも配置しておきます。

f:id:nn_hokuson:20161016172038p:plain

水面となるPlaneを追加します。ヒエラルキービューから「Create」→「3D Object」→「Plane」を選択し、先ほどTerrainで作った窪地に配置します。

f:id:nn_hokuson:20161016172423p:plain

最後に水面のテクスチャを表示するためのマテリアルと、水面を動かすためのシェーダファイルを作成します。プロジェクトビューで右クリックして「Create」→「Shader」→「Standard Surface Shader」を選択しwaterという名前で保存します。いま作成したwaterシェーダを選択した状態で、右クリック→「Create」→「Material」を選択し、waterという名前で保存します。

Panelのシェーダを「Custom/sample」に変更します。シェーダの詳しい作成方法と設定方法は下の記事で紹介していますので参照して下さい。

nn-hokuson.hatenablog.com

水面を動かすシェーダを作る

UVスクロールを使って水面を動かすためのシェーダプログラムは次のようになります。

Shader "Custom/water" {
	Properties {
		_MainTex ("Water Texture", 2D) = "white" {}
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		#pragma surface surf Standard fullforwardshadows
		#pragma target 3.0

		sampler2D _MainTex;

		struct Input {
			float2 uv_MainTex;
		};

		void surf (Input IN, inout SurfaceOutputStandard o) {
			fixed2 uv = IN.uv_MainTex;
			uv.x += 0.1 * _Time;
			uv.y += 0.2 * _Time;
			o.Albedo = tex2D (_MainTex, uv);
		}
		ENDCG
	}
	FallBack "Diffuse"
}

インスペクタから水面のテクスチャをセットできるようにPropertiesにテクスチャ変数を追加しています。また、サーフェイスシェーダが処理するテクスチャ座標を受け取るため、Input構造体にuv_MainTexを宣言しています。

surfメソッドの中でテクスチャをスクロールさせています。まずは「テクスチャのどの部分を使うか」という情報をuv変数に代入しています。次の2行では、uv変数に対してどれだけのオフセットをたすのかを指定しています。オフセットは「スクロール速度✕時間(=移動距離)」で計算しています。ここではu方向とv方向でスクロール速度を変えています。

_Time変数はUnityのシェーダにデフォルトで用意されている変数で、時間とともに値が増加します。詳しくは次のページを参考にして下さい。

docs.unity3d.com

結果

シェーダで水面を動かした結果は次のようになりました。非常に単純なシェーダですが、上にも書いたとおりuvスクロールを使えば滝や川、雲など様々な効果が実現できます。



Unity5の教科書、絶賛発売中です!
よろしくお願いします^^