Appearance
第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個の
MapSceneを作成する - レイマーチを実行し、命中時だけ白を出力する
- ボックスと平面を追加する
- オブジェクトの位置と大きさを変更する
steps / MAX_STEPSを色にして反復回数を表示するtotalDistance / MAX_DISTANCEを色にして距離を表示する
授業内課題:SDF の集合演算
球とボックスを使い、次のうち2種類を作成します。
- 複数形状の和集合
- 球でボックスを削る差集合
- 球とボックスが重なる積集合
完成条件
- 球、ボックス、平面を SDF で描画できる
- 命中、最大距離、最大ステップでループが終了する
- 反復回数を色で可視化できる
- SDF の和集合または差集合を実装している
今回のまとめ
3D SDF は空間上の位置から表面までの距離を返します。レイマーチはその距離を安全な歩幅として使い、数学的な形状の表面を探します。