【UnityShader】UVスクロールで水面を作る #12
前回の成果
ステンドグラスのシェーダーができました。
今回やること
今回はuvスクロールを使用して、水面のようなものを制作していきます。
前準備
SceneにPlaneを置き、今回制作したMaterialのinspectorに水面の画像をアタッチします。
画像を頂戴したサイト様はこちらです。
ソースコード
Shader "Custom/waterSurface" { Properties { _MainTex("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; fixed speed = 1.0f; uv.x += speed * _Time.x; uv.y += speed * _Time.x; o.Albedo = tex2D (_MainTex, uv); } ENDCG } FallBack "Diffuse" }
inputからもらってきたUV座標をtimeでズラしているように見えます。
uv.x += speed * _Time.x
前フレームのUV値を保持しておいて、そこから加算していけばよいのでは?と思う方もいると思います。
しかし、Shader上の変数に値を入れても、Shaderはフレーム間で状態を保持しないので不可能なのです。
これはSurfaceShaderに限った話ではありません。
なので、uv座標にスクロールする速度×時間を足すことによって実現させます。
_Time
これはUnityの変数にデフォルトで用意されている変数です。
Timeはステージの読み込みからの時間を表していて、Shaderの中で主にアニメーションを使用する際に用いられます。
名称 | 用途 |
---|---|
_Time.x | time/20 |
_Time.y | time |
_Time.z | time*2 |
_Time.w | time*3 |
※ timeはステージを読み込んだ時からの時間
実行すると・・・?
このまま実行すると、textureはズレているのですが、うまくいっていません。
原因は元のtextureの設定にあります。
textureのinspectorのWarp ModeがClampになっているので、uvスクロールがうまくいっていません。
これをClampからRepeatに変更します。
すると、しっかりとuvスクロールしてくれるようになりました!
他のWarp Mode
わかりやすいように、textureに絵を1つのみにして、Tilingを3に変更しています。
Clamp
画像を左下に移動させて足りない部分は無理やり補っています。
Repeat
同じtextureを描画させています。
Mirror
textureを上下左右に反転させています。
Mirror Once
textureを一度ミラーリングしてから、エッジピクセルに固定しています。
見た目はClampと変わりません。
Per-axis
x軸とy軸で項目を選んで、描画させることができます。
画像ではx軸をMirrorに、y軸をClampにしています。
ソースコードにコメントを付与
Shader "Custom/waterSurface" { // プロパティ Properties { // テクスチャのデータ _MainTex("Texture", 2D) = "white" {} } // Shaderの中身の記述 SubShader { // 一般的なShaderを使用 Tags { "RenderType" = "Opaque" } // しきい値 LOD 200 // cg言語記述 CGPROGRAM // フォワードレンダリング #pragma surface surf Standard fullforwardshadows // Shader Model #pragma target 3.0 // Input構造体 struct Input { // テクスチャのuv座標 float2 uv_MainTex; }; // テクスチャのデータ sampler2D _MainTex; // surf関数 void surf (Input IN, inout SurfaceOutputStandard o) { // uv値の取得 fixed2 uv = IN.uv_MainTex; // uvスクロールの速度 fixed speed = 1.0f; // x軸の移動 uv.x += speed * _Time.x; // y軸の移動 uv.y += speed * _Time.x; // ズレを適応させる o.Albedo = tex2D (_MainTex, uv); } // Shaderの記述終了 ENDCG } // SubShaderが失敗した時に呼ばれる FallBack "Diffuse" }
以上になります! 次回も引き続きShaderの勉強をしていきます!