GPUで共有頂点法線を作成する


9

私は、CPUからOpenGLコンピューティングシェーダーへのマーチングキューブの実装の移植にほとんど成功しましたが、私はまだ法線に取り組んでおらず、そのための最善の方法を考えていません。

私の実装では特にバイナリ値フィールドを扱います(まだ距離推定器を持たない3Dフラクタル関数をモデル化しようとしているため)、勾配法と前方差分法は機能しません。動作する頂点を共有しました。私のCPU実装では、ここで説明するQuilezの方法を使用して、隣接する各頂点に面法線を蓄積します。

この実装を別のシェーダーに移植することもできますが、これで発生する問題は、必要なアトミックの膨大な数です。私たちはスカラー整数型でのみアトミックを使用でき、3つの符号付き整数を合計可能な方法で1にパックする方法を考えることができないので、シェーダー呼び出しごとに3軸* 3頂点= 9アトミック追加を意味します。もちろん、それらはメモリ全体に分散されるため、1つのアトミックカウンターを9回ヒットするようなものではありませんが、それでもまだかなりのようです。

もう1つの方法は、ポリゴンごとのシェーダー呼び出しを実行して面の法線リストを作成し(おそらくこの方法でx10y10z10にパックすることができます)、次に頂点ごとのシェーダーで隣接する面の法線をすべて蓄積します。ただし、これは膨大なメモリを消費しますが、最悪の場合に対処するには、面インデックスのストレージスペースに頂点ごとに12 intが必要になります。また、特定の頂点に既に書き込まれている面の数を計算するためにアトミックに頼らずに、このストレージに書き込む方法の問題もあります。

誰でもこれを行う方法についてもっと良いアイデアがありますか?

回答:


5

nVidiaのみのソリューションでは、浮動小数点アトミック追加組み込み関数(NvInterlockedAddFp32など)を使用できます。HLSLのGPU組み込み関数のロック解除| NVIDIA開発者

私は80.000頂点メッシュでこれを試してみましたが、非常に高速です(GTX980Mで1または2 msのようなものです。

組み込みが機能するようにリリースでシェーダーをコンパイルすることに注意してください(nvidiaのバグ/制限のため)

また、頂点の分割にも注意してください(たとえば、UVの不連続性のため)、それらを処理する必要があります。そうしないと、UVの継ぎ目に不要なハードエッジができてしまいます。


質問が古いので、代わりにあなたに尋ねます:-)私が理解していることは、各頂点の隣接情報を持っているだけでは、russには十分ではないということですか?
Andreas

これは昨年の私の論文プロジェクトのためでした。私は、単純な方法で終わり、整数アトミック加算を使用し、精度を最大にするためにスケールアップし、次に浮動小数点ベクトルに正規化しました。最悪の場合のスペースを割り当てず、アトミックカウンターを使用してリストを構築せずに、各頂点の周りに面をリストする方法を理解できませんでした。それは地獄としてはおそらく非効率的ですが、私はまだCPUバージョンと一流のマークから数桁のスピードアップを得たので、私はそれで十分満足しました:)
russ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.