【Blender 5.0】Repeat Zoneで行うSDFを使ったレイマーチング

blender
記事内に広告が含まれています。

Blender 5.0 では、シェーダーノードでも Repeat Zone が使用できるようになりました。
これにより、SDF(Signed Distance Field:符号付き距離場)を利用したレイマーチングを、ノードだけで比較的簡単に構築できるようになっています。

レイマーチングが使えるようになると、
数式による複雑な形状やフラクタル表現、
さらには Blender のテクスチャやノードを組み合わせた独自の空間表現まで、
シェーディングだけで柔軟に作成・アニメーションできるようになります。

一見すると難しそうですが、実際に使っている考え方はとてもシンプルです。

この記事では、自分自身の理解整理も兼ねて、

  • SDFとは何か
  • レイマーチングとは何か
  • Repeat Zoneを使ってどう実装するのか
  • おまけ:座標反復法(距離場評価)について

を順に解説していきます。

スポンサーリンク

SDFとは何か

SDF(Signed Distance Field)とは、
空間上の任意の点から、最も近い表面までの距離を返す関数のことです。

特徴は以下の通りです。

  • 表面上の点 → 0
  • 内部 → マイナス
  • 外部 → プラス

例えば、半径1の球のSDFは
「中心からの距離 − 1」
という非常にシンプルな式で表せます。

右図は、オブジェクト座標から各位置の原点(0,0,0)までの距離を、
白黒のグラデーションとして可視化したものです。

中心が最も距離が小さく黒く表示され、
外側に行くほど距離が大きくなり白く表示されます。

ここから 0.7 などの一定の値を引くと、
距離がちょうど 0 になる位置が境界となり、
円状の形が現れます。

境界の内側は値がマイナス、外側はプラス、
境界そのものは 0 という値になります。
これが SDF(Signed Distance Field)を使った図形表現です。

この距離場を使うことで、
境界に線を引いたり、内側と外側で色を分けたりしながら、
さまざまなパターンや図形を作ることができます。

つまり、作りたい形の「境界が 0 になる関数」を作ればいい ということになります。

Blenderでは、Voronoiノードの Distance 出力などを使って、
SDFに近い距離場を簡単に作ることができます。

※この記事では、厳密な数学的SDFだけでなく、「SDF的に使える距離場」も含めて扱います。

スポンサーリンク

レイマーチングとは?

レイマーチングは 描画手法(アルゴリズム) です。
考え方は単純で、

  • レイの開始位置を決める
  • レイ方向に少しずつ位置を進める
  • 各地点で「何があるか」を調べる
  • 表面に十分近づいたらヒットとみなす

という処理を繰り返します。
重要なのは、
位置を反復的に更新しているかどうか

SDFを使うとなぜ効率がいいのか

SDFを使うと、「次にどれくらい進んでも安全か」を距離として得られます。

step = sdf(pos) pos += dir * step
この方法は Sphere Tracing と呼ばれ、

  • 無駄に細かく刻まない
  • 表面に最短距離で近づける
  • ノイズが少ない

というメリットがあります。

Repeat Zoneでのレイマーチング

右図は、Repeat Zone で行われるレイマーチングのイメージ図です。
カメラ方向(視線方向)からレイを出し、
SDF などの距離場の値に応じてレイを進めていきます。
そして、図形の黒い「0 の境界」に到達した時点で、
そのレイの処理が終了します。

※ 実際の Repeat Zone 実装では、距離場の性質やノード構成によって、レイの進み方は必ずしも均一にはなりません。

Repeat Zone の中で、
pos = pos + dir * step
のような処理をしていれば、
それはレイマーチングです。

今回の Repeat Zone を使った実装では、
SDF 的な値やテクスチャの出力を step として用いることで、
Sphere Tracing の考え方をノードで再現しています。

※ただし、必ずしも数学的に正確な SDF ではないため、厳密には一般的な Sphere Tracing とは異なります。

レイとは

ここで言う「レイ」とは、実際に光線を飛ばしているわけではなく、
各ピクセルが参照する空間座標視線方向に少しずつ更新していく処理を指しています。

この座標更新によって、2D の画像上に奥行きを持った表現が現れます。

スポンサーリンク

Worldシェーダーでのレイマーチ

非常にわかりやすいノードの組み方をしている方がいたので紹介します。この組み方を例にして典型的なレイマーチングを解説したいと思います。

大きな要素として以下の3つの要素があります。

  • カメラの位置(レイが飛ぶ最初の位置)
  • レイの方向(カメラから視界の範囲の全ての方向への方向ベクトル、正規化されて1、Ray Direction)
  • SDF(レイの位置と物体の表面でぶつかる距離)

レイマーチングの流れ

  • まずSDFを計算
    • 最初の位置はカメラの位置
    • 球の中心とカメラの位置の距離から、ある半径(例えば1.0)を引くと、カメラから球の表面までの距離がわかる。
  • レイマーチする
    • この距離を半径、カメラの位置を中心にした円を描く
    • カメラから出る全てのレイがその円のフチまで進行する。貫通しない安全な距離だから(これがレイマーチング1回目)
    • 上のノードでいうと、Ray DirectionにSDFで得た数値を掛けて、元のPositionにそのベクトルを足してレイマーチングしている
  • 2回目のSDF
    • 1回目のレイマーチで進んだ位置P2から始める
    • 球の中心とP2の距離から、ある半径(例えば1.0)を引くと、P2から球の表面までの距離がわかる。
  • 2回目のレイマーチ
    • この距離を半径、P2の位置を中心にした円を描く
    • P2はその方向のまま進み円のフチまで進行する。(これがレイマーチング2回目)
  • 3回目のSDF、レイマーチへ続く…

SDF/Distance Estimatorを使うと、物体にぶつからずに進める安全な距離を事前に知ることができます。この安全距離を使って、カメラから出る各光線(レイ)は少しずつ進んでいきます。レイが物体に接触すると、距離が0になり、進行を止めます。つまり、カメラからのレイは物体表面の位置で止まり、他のレイも同様に進行距離に応じて止まるまで進むことで、空間内に物体が存在するようにシーンが描画されます。

補足ですが、今回のように物体までの距離を正確に計算できる場合は、その距離検出をSDF(Signed Distance Function)と呼びます。一方、計算が複雑で、距離を完全には正確に求められない場合はDistance Estimator(距離推定器)と呼ばれます。両者はほぼ同じ概念なので、神経質に使い分ける必要はあまりありません。
関係:SDF ⊂ Distance Estimator

スポンサーリンク

Objectシェーダーでのレイマーチ

通常のobjectにつけるシェーダーノードでレイマーチ表現もできます。その場合はそのオブジェクト内に結果が表示されます。

レイはPositionの位置ベクトルからスタートし、
そこからレイの方向(カメラから視界の範囲の全ての方向への方向ベクトル、Ray Direction)に
SDFで取得した大きさでレイマーチングしていきます。

※大体の流れは上のWorldシェーダーでのレイマーチと同じです。

スポンサーリンク

おまけ:座標反復法(距離場評価)

レイマーチングとは異なるアプローチとして、座標を反復的に更新しながら距離場を評価する手法があります。本記事ではこれを座標反復法(距離場評価)と呼びます。

この手法では、各点の位置ベクトルを基点とし、その座標を反復的に変形・更新しながら、毎回距離場を再評価します。ここで重要なのは、空間内を進むレイのように位置が物理的に移動しているわけではなく、あくまで各点ごとに内部的な座標が更新されている点です。

処理の流れは概ね次のようになります:

  • 初期座標をもとに距離場を評価する
  • 座標に対して変形(スケーリングや方向ベクトルとの乗算など)を行う
  • 更新された座標で再び距離場を評価する
  • この処理を複数回繰り返す

この反復により、距離場の値は安定した領域と不安定な領域に分かれ、結果として0付近(境界)の構造が強調されます。これは、反復しても値が大きく変化しない領域が視覚的に残りやすいためです。

この手法はレイマーチングのように表面への到達を目的とするものではなく、座標の変形と距離場評価の組み合わせによってパターンや構造を抽出・強調することに特徴があります。そのため、エッジ強調や抽象的な立体表現など、アート寄りの表現に適しています。

スポンサーリンク

参考

以下の素晴らしいチュートリアルを参考にしています。

コメント