Skip to content

第07回 ボリュームレイマーチ

前回: 第06回 レイマーチのライティング

今回の授業内容

  • 表面と体積をレイで描画する違いを理解する
  • レイ上で密度を一定間隔でサンプリングする
  • 色と Alpha を手前から合成する
  • FBM で霧、煙、雲の密度を作る
  • ステップ数、歩幅、透過率の品質を比較する

表面で止まらず体積を通過する

SDF のレイマーチは表面を見つけたら終了します。霧や雲は明確な表面を持たず、レイ上の密度が少しずつ色と透明度に影響します。

ボリューム内をレイが進む流れ
カメラ
レイを進める
低密度領域
低密度領域
密度をサンプリングする
高密度領域
高密度領域
色とAlphaを蓄積する
低密度領域
低密度領域
体積を通過する
背景

手前から順に色と Alpha を蓄積し、ほぼ不透明になったらそれ以降の計算を終了できます。

密度を定義する

hlsl
float DensityField(float3 p, float time)
{
    float heightFade = saturate(1.0 - abs(p.y) * 0.25);
    float noise = Fbm3D(p * 0.7 + float3(time * 0.1, 0.0, 0.0));
    return saturate((noise - 0.45) * 3.0) * heightFade;
}

密度をノイズだけで決めると、空間全体に散らばります。高さ、球、ボックスなどの大きな形で範囲を決め、ノイズで境界と内部を崩します。

密度をループで蓄積する

hlsl
float4 RaymarchVolume(float3 rayOrigin, float3 rayDirection, float time)
{
    float4 accumulated = 0.0;
    float distanceAlongRay = 0.0;
    const float stepSize = 0.12;

    [loop]
    for (int i = 0; i < 80; i++)
    {
        float3 p = rayOrigin + rayDirection * distanceAlongRay;
        float density = DensityField(p, time);
        float alpha = 1.0 - exp(-density * stepSize * 2.0);
        float3 sampleColor = lerp(
            float3(0.25, 0.35, 0.5),
            float3(1.0, 0.95, 0.85),
            density
        );

        accumulated.rgb += (1.0 - accumulated.a) * sampleColor * alpha;
        accumulated.a += (1.0 - accumulated.a) * alpha;

        if (accumulated.a > 0.98) break;
        distanceAlongRay += stepSize;
    }
    return accumulated;
}

1 - accumulated.a は、手前のサンプルを通過して残っている光の割合です。新しいサンプルはその残りにだけ影響します。

実習:霧、煙、雲を作り分ける

  1. 一定密度のボックスを描画する
  2. 手前からの Alpha 合成を確認する
  3. 第03回の FBM を3D座標で使う
  4. 時間でノイズ座標を移動する
  5. 次の3設定を作成する
表現調整方針
低密度、広い範囲、少ないコントラスト
上方への流れ、局所的な高密度、暗い色
高さの範囲、大きな形、明るい光側

授業内課題:品質とシルエットを両立する

  • サンプル数を32、64、96に変える
  • 歩幅を変えて段差やちらつきを確認する
  • 各品質でフレーム時間を記録する
  • 低品質でも表現の意図が残る密度と色を調整する

完成条件

  • レイ上の密度を固定上限のループでサンプリングできる
  • 手前からの Alpha 合成を実装できる
  • FBM と大きな形のマスクを組み合わせている
  • サンプル数と品質、負荷の関係を説明できる

今回のまとめ

ボリュームレイマーチは、表面で止まらずレイ上の密度を蓄積します。プロシージャルノイズとループが、立体的な霧、煙、雲の表現に直接つながります。

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