はじめに
「HLSLって難しそう…」と思っていたけど、実は短いコードで動く表現が作れると知りました。
今回は、テクスチャを水面のように波打たせるシェーダーを作ります。
影やライティングは一切なし、Unlitでシンプルに。
環境
- Unity 6 (6000.0.28f1) LTS
- Universal Render Pipeline(URP 3D テンプレート)
- 素材は水面やスライムっぽい模様のテクスチャ(模様がある方が動きが分かりやすい)
完成イメージ
実装手順
1. シェーダーを作成
今回はUnlitShaderを作成します。
Shader "Unlit/WaveUV_URP" // シェーダーの名前(マテリアル作成時に選択するパス)
{
Properties
{
_MainTex ("Texture", 2D) = "white" {} // メインテクスチャ(波打たせる画像)
_Amplitude ("Wave Amplitude", Float) = 0.05 // 波の振幅(揺れの大きさ)
_Frequency ("Wave Frequency", Float) = 10.0 // 波の周波数(1単位あたりの波の数)
_Speed ("Wave Speed", Float) = 2.0 // 波の速度
}
SubShader
{
Tags
{
"RenderPipeline"="UniversalPipeline" // URPでのみ使用可能
"RenderType"="Opaque" // 不透明オブジェクトとして描画
"Queue"="Geometry" // 描画順序(ジオメトリキュー)
}
Pass
{
Name "Unlit" // パスの名前(任意)
HLSLPROGRAM // HLSLコードの開始
#pragma vertex vert // 頂点シェーダー関数の指定
#pragma fragment frag // フラグメントシェーダー関数の指定
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" // URPの基本関数や定義を読み込み
// 頂点シェーダーに渡される入力構造体
struct Attributes {
float4 positionOS : POSITION; // オブジェクト空間の頂点座標
float2 uv : TEXCOORD0; // メッシュのUV座標
};
// 頂点シェーダーからフラグメントシェーダーに渡すデータ
struct Varyings {
float2 uv : TEXCOORD0; // 変形後のUV座標
float4 positionHCS: SV_POSITION; // クリップ空間の頂点座標
};
// テクスチャとサンプラーの宣言(URP推奨の書き方)
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
// マテリアルごとの定数バッファ(SRP Batcher対応)
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST; // TilingとOffset(_MainTexの設定から自動で渡される)
float _Amplitude; // 波の振幅
float _Frequency; // 波の周波数
float _Speed; // 波の速度
CBUFFER_END
// 頂点シェーダー
Varyings vert (Attributes v)
{
Varyings o;
o.positionHCS = TransformObjectToHClip(v.positionOS); // オブジェクト空間座標をクリップ空間に変換
float2 uv = v.uv * _MainTex_ST.xy + _MainTex_ST.zw; // TilingとOffsetを適用したUV
// URPでは _TimeParameters.y が経過秒(Built-inの _Time.y と同等)
uv.y += sin(uv.x * _Frequency + _TimeParameters.y * _Speed) * _Amplitude; // 波打ちUVの計算
o.uv = uv; // 計算後のUVを出力にセット
return o;
}
// フラグメントシェーダー
half4 frag (Varyings i) : SV_Target
{
return SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv); // UVに基づいてテクスチャをサンプリングして色を返す
}
ENDHLSL // HLSLコードの終了
}
}
}
2. マテリアルを作成
アテリアルを作成し、先ほど作ったシェーダーをマテリアルで選択します。
-
_MainTex
に模様のあるテクスチャを設定(水面やスライム模様がおすすめ) -
_Amplitude
:0.08〜0.12 -
_Frequency
:8〜12 -
_Speed
:2〜4 - PlayモードでGameビューを確認
3. Quadにマテリアルをアタッチ
応用例
-
縦波:
uv.x
とuv.y
を入れ替える -
二重波:
sin
を2本足して干渉感を出す -
色のゆらぎ:
col.rgb *= 0.9 + 0.1 * sin(_Time.y * 2.0);
※ frag 内で追加
まとめ
-
HLSLは「UVをちょっといじる」だけで動きのある表現が作れる
-
単色より模様のあるテクスチャの方が変化が分かりやすい
-
次は色変化やフェードなども組み合わせてみたい