符号付き距離フィールド(2D)をリアルタイムで高速に生成するにはどうすればよいですか?


21

前の質問、それが署名した距離フィールドは、事前に計算実行時にロードされ、そこから使用することができることが示唆されました。

この質問の最後に(興味のある人のために)説明する理由のために、距離フィールドをリアルタイムで作成する必要があります。

面取り距離変換やボロノイ図近似ベースの変換(Pixeljunk Shooter dev guyによるこのプレゼンテーションで提案されている)の方法など、リアルタイム環境で実行可能なさまざまな方法に関する論文がいくつかありますが、私は(したがって、他の多くの人々と見なされる可能性があります)彼らは通常長く、大部分が数学で肥大化しており、説明はあまりアルゴリズム的ではないため、実際に使用するのは非常に困難です

距離フィールドをリアルタイムで(好ましくはGPU上で)作成するために、特に距離フィールドの品質を考慮して、どのアルゴリズムを提案しますか?

別の論文やスライドへのリンクとは対照的に、実際の説明/チュートリアルを探しているので、この質問は1つに適格になると賞金を受け取ります:-)。

リアルタイムで実行する必要がある理由は次のとおりです。

大規模な2D環境用にこれらのSDFを事前計算する必要がある場合(大規模なTerrariaのようなマップの場合)、これは、ストレージスペース(およびマップ生成時間)のかなり大きなオーバーヘッドを受け入れ、より多くのリアルタイムのSDF生成に十分高速な複雑なアルゴリズム。

たとえば、タイルサイズが10 * 10ピクセルで1000 * 256(幅*高さ)の比較的小さなマップで、合計サイズが10000 * 2560ピクセルの場合、比較的小さなサイズを選択すると、すでに約2メガバイトのサイズがかかります。 0〜255の距離値のみを保存すると仮定すると、128x128のSDF解像度。

明らかに、これはすぐに大きくなりすぎる可能性があり、私が望んでいないオーバーヘッドです。

他にも何かあります:

SDFは(衝突検出など)多くのことに使用でき、いくつかの有用なアプリケーションは潜在的にまだ発見されていません。多くの人が将来これらのことを探すと思います。ここで包括的な答えが得られれば、私たちは多くの人を助けると思います。


「符号付き距離フィールドとは」をグーグル で検索し、最初にヒットしたのはGPUバージョンです。
パトリックヒューズ

1
何かが足りないかもしれませんが、リアルタイムでそれを行う必要がある理由(特に、ネタバレがタグ付けされている理由)の説明に多少混乱しています。まず、128x128のSDFの2MBの数値はどこで取得しますか?第二に、なぜ2MBを特にメモリ使用量が多いと考えるのですか?私はそれが実体的ではないことに同意しますが、それはあなたの全体的なマップのメモリ使用量のほんの一部のようです。そして第三に、リアルタイムでフィールドを生成すると、そのメモリがどのように節約されますか?その場で生成されたものであれ事前計算されたものであれ、まったく同じデータを保存する必要がありますか?
スティーブンスタドニッキー

もっと広く言えば、SDFがあなたが必要とする技術ではないということは簡単です。特定の状況に関する詳細な情報-静的障害物カウント、動的障害物カウントなど-正確にどのような効果を達成したいのかは、あなたにとって最も役立つと思われるものを突き止めるのに役立ちます。
スティーブンスタドニッキー

1
距離フィールドをリアルタイムで生成した場合、それらの2MBをフレームごとに1回だけ作成します(画面に必要なのは1つだけなので、合計メモリオーバーヘッドは常に1つの距離フィールドに必要なメモリになります)。1000x128の例よりも大きなマップがある場合(大きなTerrariaマップは10000をはるかに超えると思います)、そのマップの1000x128サブマップごとに2mbのいずれかが必要です。そもそもSDFが必要な理由は、この質問の最初にリンクした最初の質問(GPU 2Dシャドウキャスティング用)で説明されています。
TravisG

1
@heisheは、フレームごとに2Mbのデータを生成しようとしていますか?マジ?
kaoD

回答:


9

Catalin Zimaは、彼の記事で動的な2Dシャドウを実現する方法を説明しています-そして、彼は符号付き距離フィールドを使用しています(このコンテキストではシャドウバッファーの単なる空想的な名前であるとわかります)。彼の方法にはGPUが必要であり、彼の実装は現状では最適ではありません(私のマシンの約20のライトで60 Hz未満に低下し、私のマシンでは約500のライトが得られました)。彼は速度よりもコードの明快さを好んでいるので、これは予想されることです。

実装

彼が実装したとおり:

  1. すべてのシャドウキャスターをテクスチャにレンダリングします。
  2. 各ピクセルのライトの中心までの距離を計算し、その値を不透明ピクセルのRGBに割り当てます。
  3. 3Dカメラがこれらのピクセルをどのように見ているかを表すように、画像を歪ませます。
  4. 彼の記事で説明されている異常なサイズ変更を使用して、画像を2xNサイズの画像に押しつぶします(単純なサイズ変更は機能しません)。
  5. これで、2xN画像は、光の4つの象限すべての符号付き距離フィールドになります(1つの象限は基本的に90度の単一のカメラ錐台であることを思い出してください)。
  6. ライトマップをレンダリングします。
  7. ソフトシャドウを得るために、ライトからの距離に基づいてライトマップをぼかします。

私の最終的な実装は次のとおりです(各ステップは単一のシェーダーです):

  1. する(1)。
  2. います(2)及び(3)
  3. 行う(4)。彼の実装は本当に遅いです:もしあなたがこれのためにGPGPUを試して使用できるなら。GPGPU(XNA)を使用できなかったので、次のようにしました。
    • 最初のN / 2列が正確な位置(最終バッファの最初の列をカバー)でN / 2クワッドで表されるメッシュを設定しますが、テクスチャ座標は異なります(2番目のN / 2列でも同じ)
    • GPUで深度テストをオフにします。
    • MINピクセルブレンド機能を使用します。
  4. (6)および(7)を実行します。

これは非常に独創的です。基本的には、3Dでのシャドウの処理方法を2Dに直接変換したものです。

落とし穴

主な落とし穴は、一部のオブジェクトをシャドウイングしないことです。この例では、Liero(リアルタイムワーム)クローンを作成していたため、たとえばプレイヤーのワーム(少なくとも1つ)をシャドウイングしたくありませんでした各プレーヤーの画面上)。これらの「特別な」オブジェクトに対して行ったのは、最後のステップとしてそれらを再描画することだけでした。皮肉なことに、ほとんどのオブジェクト(ワーム、風景の前景)はシャドウされていないため、ここにオーバードローの問題があります。


サイズ変更方法の調整は、60fpsを超える500個のライトを処理するためにスピードアップする唯一の方法でしたか?
TravisG

OK、元の問題を解決するので答えを受け入れますが、私が賞金を与えたものには本当に答えません。私は待って、多分誰かが署名された距離フィールド生成のためのいくつかのO(N)メソッドの1つを説明するのに長く来ます。
TravisG

最初の質問に関する@heishe:よくわかりません。すべての最適化を1回のパスで実行しました。ただし、オフにしてフレームレートが大幅に低下するのを覚えていると思います。ライトごとに全部で6つのドローコールがあると、フレームレートが低下します。私が言うことができるように見えると言ったように、あなたはステップ(5)で4つの署名された距離フィールドを持っていますが、それらについてもっと知っている人はそれを確認する必要があります
ジョナサンディキンソン

まあ、それは署名された距離フィールドの非常に特別なケースです。通常の符号付き距離フィールドでは、すべてのピクセルに最も近い障害物までの距離が含まれています。このアルゴリズムでは、距離フィールドに含まれる障害は1つだけです。また、障害は画像(光源)全体で1ピクセルしかないため、この距離フィールドはO(N)で生成できます。
TravisG

1
@heisheここに私のシェーダは次のとおりです。gist.github.com/2384073。DistortPSは2 + 3です。
ジョナサンディキンソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.