Skip to content

第09回 水面表現2:深度、屈折、泡

前回: 第08回 水面表現1:波と法線

今回の授業内容

  • Scene Color と Scene Depth が保存する情報を区別する
  • 水面と背景の深度差から水深を近似する
  • 水深に応じて色と透過を変化させる
  • 法線で画面 UV をずらし、屈折を表現する
  • 深度差とノイズで交差部分の泡を作る

URP で画面の色と深度を使う

Scene Color は水面を描画する前の画面色、Scene Depth はカメラから背景オブジェクトまでの奥行きを参照するために使います。

URP Asset で Opaque Texture と Depth Texture を有効にします。Fullscreen Pass を使う場合は、Renderer Feature の Requirements で Color と Depth を要求します。

WARNING

Scene Color には通常、すでに描画された不透明オブジェクトが入ります。透明オブジェクト同士の順序は別に管理されるため、必ずしもすべての透明物が屈折されるわけではありません。

深度差から水深を求める

text
背景の Eye Depth - 水面の Eye Depth = 水中を通過する距離の近似
hlsl
float waterDepth = max(sceneEyeDepth - surfaceEyeDepth, 0.0);
float shallowMask = saturate(waterDepth / shallowDistance);
float deepMask = saturate(waterDepth / deepDistance);

Depth Texture に保存された値は、そのままワールド距離として使えない場合があります。Shader Graph の Eye 空間への変換と、透視投影・正射影投影の違いを確認します。

水深で色と透過を変える

hlsl
float3 depthColor = lerp(shallowColor, deepColor, deepMask);
float transmission = exp(-absorption * waterDepth);
float3 transmittedScene = sceneColor * transmission;
float3 waterBody = depthColor * (1.0 - transmission);
float3 result = transmittedScene + waterBody;

深いところほど背景から届く光が減り、水自体の色が強く見えます。単なる Alpha の変化ではなく、通過距離と色吸収を関係付けます。

法線で Scene Color をずらす

hlsl
float2 distortion = normalWS.xz * refractionStrength;
float2 refractedUV = screenUV + distortion;
float3 refractedColor = SampleSceneColor(refractedUV);

屈折強度が大きすぎると、背景が水面から切れて見えます。また、画面外の UV を読まないように範囲を制御します。

交差部分に泡を作る

hlsl
float intersection = 1.0 - saturate(waterDepth / foamDistance);
float noise = Fbm(worldPosition.xz * foamScale + time * foamSpeed);
float foam = smoothstep(foamThreshold, 1.0, intersection * noise);

水深が小さい場所は、水面と底やオブジェクトが近い場所です。そのマスクをノイズで切り分け、均一な白線ではなく変化する泡にします。

実習:水中の情報を段階的に追加する

  1. Opaque Texture と Depth Texture を有効にする
  2. Scene Depth を白黒で表示し、カメラとの距離を確認する
  3. 水面と背景の深度差を表示する
  4. 浅い色と深い色を水深で混ぜる
  5. 法線で Scene Color の UV をずらす
  6. 深度差と FBM で泡マスクを作る
  7. 前回のフレネル反射と統合する

授業内課題:可視化モードを用意する

Keyword または数値プロパティで次の出力を切り替えます。

  1. 最終色
  2. 背景の深度
  3. 水深
  4. 屈折用法線
  5. 泡マスク

表示が崩れたときに、どの入力が問題か切り分けられるマテリアルにします。

完成条件

  • Scene Color と Scene Depth を参照できる
  • 深度差で水深色を変化させられる
  • 法線で背景を屈折させられる
  • 交差部分にノイズを持つ泡を表示できる
  • 中間計算を可視化して問題を切り分けられる

今回のまとめ

水面は、メッシュの表面だけでなく、背景の色と深度を使って水中の距離を表現します。波、法線、フレネル、深度、屈折、ノイズを役割ごとに統合します。

次回: 第10回 レイトレースの原理