Signed Distance Fieldのレイマーチングは、動的な世界にどのように実装されますか?


10

符号付き距離フィールドレイマーチングの基本を理解していると思います。一連の距離フィールド(http://iquilezles.org/www/articles/distfunctions/distfunctions.htmなど)を使用してシーンをモデル化し、次に、ピクセルを投影するたびに、光線の最初から開始します、その点で最も近いオブジェクトまでの距離を見つけ、何かにぶつかるまでその点を最も近い距離だけ増分します。簡単なレンダラーを何とかして実現しました。そこで、テクニックのほとんどの説明は終わりです。

これにより、SDFレイマーチングを実際のシナリオでどのように使用できるかについて、いくつか質問があります。

質問1:実際のゲームでは、シーンは通常複雑で、CPUにロードされ、多くの動的オブジェクトがあります。基本的なオクルージョンカリング(オクトリーなど)を理解しており、ポリゴンレンダリングを使用して、レンダリングするビューフラストラム内のアイテムの(CPU上に)リストを作成します。

それで、CPUによって制御され、画面上を動く多くのキャラクターと動的オブジェクトを含む非常に複雑なシーンがあると想像してください。レンダリングするオブジェクトをフレームごとにGPUにストリーミングするにはどうすればよいですか?すべての例には、GLSLでハードコードされたシーンがあります。誰かが動的にシェーダーにストリーミングされるレベルの例を共有できますか?

質問2:オブジェクトはどのようにして複数の色を持つことができますか?距離関数は距離を返すだけですが、実装は通常どのように色を返しますか?(たとえば、青い立方体ではなく赤い球体をヒットします。)これがCPU実装である場合、レイマーチャーを終了するヒットであるときに、距離関数内でグローバル関数を呼び出し、ヒットオブジェクトのオブジェクトも渡すことができます。テクスチャ/色。しかし、GLSLでアイテムの色またはテクスチャをどのように返しますか?

ありがとうございました。

回答:


2

これは最小限の回答ですが、より良い回答が得られない場合に備えて情報を共有したいと考えていました。

実際のゲームでレイマーチングを使用する方法については、通常は使用しません。過去2年間で、ゲームがスクリーンスペースの反射を行うために深度バッファーをレイマーチングし始めましたが、私が知っているゲームは、あなたが説明した方法でレイマーチングを使用していることをまだ認識していません。

色などに関する他の質問については、人々は通常、マテリアルをオブジェクトに関連付け、光線がオブジェクトに当たるポイントの「テクスチャ座標」を使用して、オブジェクト上のそのポイントのマテリアルプロパティを計算します。一般的なマテリアルには、拡散色、鏡面反射光強度、放射色、透明度/屈折率などがあります。

それがあなたにとって少なくともいくつかの助けになることを願っています!また、グラフィックススタック交換サイトからも適切な回答が得られる場合があります。


2
「私が認識しているゲームはありません。説明どおりにレイマーチングを使用しています」Media Moleculeの次のゲームDreamsは、ユーザーが生成したコンテンツのスカルプティングに符号付き距離フィールドを使用しますが、正しく理解すると、フィールドはレンダリングではなく点群に変換されてレンダリングされます直接レイマーチされている。この記事にはいくつかのアイデアがあるかもしれません:dualshockers.com/2015/08/15/…–
DMGregory

1
@DMGregoryいいですが、これは厳密にはレイマーチングではないと思います。したがって、ポイントはまだ有効です。ゲームは通常、レイマーチングを使用しません。
concept3d 2016年

1
このスレッドの更新-次のゲームClaybookは、距離フィールドを最初に従来のジオメトリに変換するのではなく、距離フィールドを介して直接発射される光線を使用してシーンをレンダリングすると報告されています。それで「まだ?」2年たってから生まれてきたようです。:)
DMGregory

1

私は現在、スムーズプロシージャジオメトリを表示するレンダリング手法として符号付き距離フィールドを使用するゲームエンジンを開発しています(リンクのような単純なプリミティブで生成され、将来はJuliaとIFSフラクタルを実装する予定です)。私のエンジンは手続き型の生成に焦点を当てており、レイマーチャーに優しい方法で図を定義する必要があるため、この質問に答えるのに適した場所にいると思います。

ストリーミングに関しては、単純な解決策は、ある種の型付きバッファを使用して、レイマーチングを行いたいときにGPUにスローすることです。バッファの各要素は複合型(C / C ++の構造体など)であり、各型には、それを表すために使用する必要がある関数、位置、回転、スケールなど、および平均色を定義する要素が含まれています。次に、プロセスは次のように簡略化されます。

  1. シーンを管理可能なサブセットにカリングします(錐台カリングとオクルージョンカリングは、とにかく光線進行アルゴリズムによって部分的に自動的に実行されることに注意してください)。
  2. サブセットをレンダー入力バッファーに渡す
  3. バッファがない場合はバッファをGPUに渡し、通常の従来のレイマーチングでシーンをレンダリングします。レイマーチャーの反復ごとに、入力バッファー内のどのアイテムが各レイに最も近いかを評価するために、ある種のステップごとの検索を実行する必要があります。また、どちらかのレイに変換を適用する必要があります(その場合) GPUに到達する前にFigureの回転を反転する必要があります)または距離関数自体(位置の変更のために関数の原点を移動し、スケールの変更のために3次の辺の長さを調整するなど)。最も単純なアプローチは、前に光線を変更することですそれらを実際のコア距離関数に渡します。

図の色については、シェーダーを使用すると、プリミティブだけでなく複雑なタイプも定義できることに注意してください;)。これにより、すべてをCスタイルの構造体にスローし、それらの構造体を距離関数から返すことができます。

私のエンジンでは、各構造体には、距離、色、および入力バッファー内の対応するFigure定義に関連付けるIDが含まれています。各IDは、関連する距離関数の周囲のコンテキストから推測されます(マッピング関数は入力バッファーをループして各ステップの各光線に最も近い数値を見つけるため、各SDFが呼び出されたときにループカウンターの値を安全に処理できますその関数の図形IDとして)、距離の値は任意のコアSDF(たとえば、point - figure.pos 球の場合)、および色は、フィギュアバッファー内の適切な要素の平均色から定義される(そのため、フィギュアIDを保持しておくと便利です)、または保存された平均に向かって重み付けされた手続き型カラー(1つの例では、 Mandelbulbのあるポイントの反復カウント。「平均色」をFPカラースペースから整数カラースペースにマッピングし、マッピングされたカラーを反復カウントに対してXORしてパレットとして使用します)。

プロシージャルテクスチャは別のアプローチですが、私はそれらを自分で使用したことがありません。iqはその領域でかなり多くの研究を行い、いくつかの興味深いデモンストレーションをShadertoyに投稿しているため、追加の情報を収集する1つの方法になる可能性があります。

各図の色が静的であるか、手順で生成されるか、または手順テクスチャから魔法のようにサンプリングされるかに関係なく、基本的なロジックは同じです:ある種の中間の複雑なタイプ(構造体など)に図を抽象化しローカル距離ローカルの両方を保存しますその型のインスタンスの色を指定し、距離関数からの戻り値として複合型を渡します。実装に応じて、出力カラーは画面に直接通過するか、コリジョンポイントに従ってライティングコードに進むことができます。

上記が十分に明確であったかどうかはわかりませんので、何か意味のないことを尋ねる心配はありません。HLSLを使用してシェーディングを計算しているので、GLSL /ピクセルシェーディングコードのサンプルを実際に提供することはできませんが、最初に適切に記述しなかったものはすべて試してみて満足しています:)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.