Appearance
第08回 水面表現1:波と法線
前回: 第07回 ボリュームレイマーチ
今回の授業内容
- 複数の方向を持つ波を合成する
- 高さ関数を頂点変形と法線計算で共有する
- 有限差分で水面の接線と法線を求める
- フレネルで視線角度による反射を調整する
- 正弦波とノイズを組み合わせて規則性を崩す
水面を構成する要素
水面は青い半透明マテリアルだけではありません。後期で学んだ技術を、次の役割に分けて統合します。
| 要素 | 表現するもの |
|---|---|
| 頂点変形 | 大きな波とシルエット |
| 法線 | 細かな波と光の反射 |
| フレネル | 斜めから見たときの反射 |
| ノイズ | 周期的すぎる波の崩し |
| 深度 | 水深による色と透過の変化 |
今回は波、法線、フレネルを作り、深度と屈折は次回追加します。
方向のある波を作る
hlsl
float DirectionalWave(
float2 positionXZ,
float2 direction,
float frequency,
float speed,
float amplitude,
float time)
{
float phase = dot(positionXZ, normalize(direction)) * frequency;
phase += time * speed;
return sin(phase) * amplitude;
}波の方向と位置の内積を使うと、その方向に進む位相を作れます。複数の波を異なる方向、周波数、振幅で加算します。
hlsl
float WaterHeight(float2 p, float time)
{
float height = 0.0;
height += DirectionalWave(p, float2(1.0, 0.2), 1.2, 1.0, 0.18, time);
height += DirectionalWave(p, float2(-0.3, 1.0), 2.1, 1.5, 0.08, time);
height += DirectionalWave(p, float2(0.7, 0.7), 4.0, 2.2, 0.03, time);
return height;
}低周波の波は大きな起伏、高周波の波は細かな表面変化を担当します。
高さ関数から法線を求める
現在位置と X、Z 方向に少しずらした位置で高さを求め、2つの接線から法線を作ります。
hlsl
float3 WaterNormal(float2 p, float time)
{
const float e = 0.02;
float h = WaterHeight(p, time);
float hx = WaterHeight(p + float2(e, 0.0), time);
float hz = WaterHeight(p + float2(0.0, e), time);
float3 tangentX = normalize(float3(e, hx - h, 0.0));
float3 tangentZ = normalize(float3(0.0, hz - h, e));
return normalize(cross(tangentZ, tangentX));
}頂点変形と法線が異なる高さ関数を使うと、見た目と光の反射がずれます。共通の WaterHeight を使います。
フレネルで反射量を決める
hlsl
float ndv = saturate(dot(normalWS, viewDirectionWS));
float fresnel = pow(1.0 - ndv, fresnelPower);
float3 waterColor = lerp(baseWaterColor, reflectionColor, fresnel);水面を真上から見ると水中が見え、水平に近い角度から見ると周囲の反射が強く見えます。今回は反射色で代用し、後で Reflection Probe や画面反射へ発展できる構成にします。
実習:波の層を組み立てる
- 細分化された Plane と URP Lit Shader Graph を用意する
- HLSL の
WaterHeightを Vertex Position に加える - 1方向の波で動作を確認する
- 方向と周波数の異なる3つの波を合成する
- 有限差分で法線を再構築する
- フレネルで基本色と反射色を混ぜる
- FBM を弱く加え、正弦波の規則性を崩す
授業内課題:3つの水面を作り分ける
- 静かな池:低い振幅、細かい法線、強めの反射
- 海:大きな波、複数方向、遠くで見える輪郭
- 幻想的な水:色、波、ノイズを意図的に強調
各設定で、波の方向、周波数、振幅、フレネルの値を記録します。
完成条件
- 複数方向の波で頂点を変形できる
- 高さ関数から法線を再構築できる
- フレネルで視線角度による色を変化させられる
- 用途の異なる3種類の水面を比較できる
今回のまとめ
水面の大きな形は頂点、細かな光の変化は法線で表します。同じ高さ関数を共有し、フレネルで視線角度を加えることで、前期の頂点アニメーションを有機的な材質表現へ発展させます。