Skip to content

第05回 3D SDF とレイマーチ

前回: 第04回 レイとカメラ、座標空間

今回の授業内容

  • 2D SDF と 3D SDF の共通点を理解する
  • 球、ボックス、平面の距離関数を実装する
  • SDF が返す距離だけレイを進める
  • 命中、未命中、最大ステップを区別する
  • 反復回数と距離をデバッグ表示する

3D SDF で空間の距離を表す

SDF(Signed Distance Field)は、位置を入力し、形状の表面までの符号付き距離を返します。

  • 正の値:形状の外側
  • 0:表面
  • 負の値:形状の内側
hlsl
float SdSphere(float3 p, float radius)
{
    return length(p) - radius;
}

float SdPlane(float3 p, float3 normal, float height)
{
    return dot(p, normalize(normal)) + height;
}

float SdBox(float3 p, float3 halfSize)
{
    float3 q = abs(p) - halfSize;
    return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
}

形状を移動するときは、評価する位置から形状の中心を引きます。

hlsl
float sphere = SdSphere(positionWS - sphereCenter, sphereRadius);

シーンの距離を求める

複数形状があるときは、最も距離の小さい形状を採用します。

hlsl
float MapScene(float3 p)
{
    float sphere = SdSphere(p - float3(-1.0, 0.0, 0.0), 0.8);
    float box = SdBox(p - float3(1.0, 0.0, 0.0), float3(0.6, 0.6, 0.6));
    float ground = SdPlane(p, float3(0.0, 1.0, 0.0), 1.0);
    return min(min(sphere, box), ground);
}

min は和集合、max(a, -b) は差集合、max(a, b) は積集合の基礎になります。

Sphere Tracing でレイを進める

現在位置で SDF を評価すると、少なくともその距離までは表面に衝突しないことが分かります。その距離だけレイを進めます。

hlsl
static const int MAX_STEPS = 96;
static const float MAX_DISTANCE = 100.0;
static const float SURFACE_EPSILON = 0.001;

float Raymarch(float3 rayOrigin, float3 rayDirection, out int steps)
{
    float totalDistance = 0.0;
    steps = 0;

    [loop]
    for (int i = 0; i < MAX_STEPS; i++)
    {
        float3 p = rayOrigin + rayDirection * totalDistance;
        float distanceToScene = MapScene(p);
        steps = i + 1;

        if (distanceToScene < SURFACE_EPSILON) break;
        totalDistance += distanceToScene;
        if (totalDistance > MAX_DISTANCE) break;
    }

    return totalDistance;
}

3つの安全装置を必ず入れます。

定数止める条件
MAX_STEPS反復回数が上限に達した
MAX_DISTANCEシーンの有効範囲を超えた
SURFACE_EPSILON表面に十分近づいた

実習:SDF シーンを描画する

  1. 前回の視線レイを使う
  2. 球1個の MapScene を作成する
  3. レイマーチを実行し、命中時だけ白を出力する
  4. ボックスと平面を追加する
  5. オブジェクトの位置と大きさを変更する
  6. steps / MAX_STEPS を色にして反復回数を表示する
  7. totalDistance / MAX_DISTANCE を色にして距離を表示する

授業内課題:SDF の集合演算

球とボックスを使い、次のうち2種類を作成します。

  • 複数形状の和集合
  • 球でボックスを削る差集合
  • 球とボックスが重なる積集合

完成条件

  • 球、ボックス、平面を SDF で描画できる
  • 命中、最大距離、最大ステップでループが終了する
  • 反復回数を色で可視化できる
  • SDF の和集合または差集合を実装している

今回のまとめ

3D SDF は空間上の位置から表面までの距離を返します。レイマーチはその距離を安全な歩幅として使い、数学的な形状の表面を探します。

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