ボクセルレンダリングの場合、より効率的なものは何ですか:既製のVBOまたはジオメトリシェーダーですか?


26

かなり静的なボクセル配列を考えると、より効率的です:CPUを使用してVBOを事前に生成し、ボクセルフェイスをレンダリングします(現時点では、マーチングキューブのような高度なレンダリング形式は無視します)。その場で顔?

変化するボクセルを更新することについてはそれほど心配していませんが、もちろんVBOを再構築する必要がないため、GPUバージョンの利点です。また、GSアプローチはもう少しモダンだと感じています:)

一方、最新のGPUでGSがラスタライズパイプラインと実際にどのように機能するかについては詳しく見ていない。頂点を一種のストリームキャッシュに出力しますか、それとも頂点が通常のGPUメモリに書き込まれますか?後者の場合、オンザフライで生成すると、利用可能な帯域幅と処理能力が残りのGPUタスクから減少する可能性があり、CPUで実行する方が有益です。

回答:


9

私はMinecraftタイプのシーンを考えています。ボクセルとは、実際にポリゴンを使用してレンダリングされるブロックの世界を意味します。

ジオメトリシェーダーを使用する場合、ボクセルごとに正確に3つの面(または何でも)を持つことを避けることは困難です。

同じテクスチャの隣接ブロックが多数ある場合、テクスチャのタイルを使用して、VBOアプローチで(縮退)ストリップの三角形をはるかに少なくすることができます。つまり、草のボクセルの6x6の大きな大きな平らな領域がある場合、64個ではなく2個の三角形で上部全体を描画できます。

GSアプローチを使用すると、VBOアプローチでも非常に簡単な、隣接するボクセルによってオクルードされる面の単純なカリングを実行できません。

GSアプローチは試していませんが、隣接するタイルの繰り返しを組み合わせたVBOアプローチは非常にうまく機能しています。要素のインデックスをいじるのは、頂点を繰り返すよりもずっと遅いことがわかりました。ワールドを素敵な小さな立方体に分割する場合、通常、頂点ごとのコンポーネントごとに1バイトだけを使用し、テクスチャ情報と法線(軸に合わせた立方体の面には3つの法線しかありません)などを4バイトにパックします頂点ごとに4バイトで、高速で高速です。

私は6つの顔のそれぞれに別々のVBOを使用しました。明らかに最大3つしか描画する必要はありません。これは、Minecraftスタイルのボクセルの上部で通常使用されるさまざまなテクスチャリングにうまく適合します。なぜなら、各セットでは法線などが均一だからです。

GL_REPEAT水平軸上にあり、同じアトラス内で90度回転されたバージョンのピックスマップを持つアトラスで垂直に並べられたピックスマップを使用すると、同じ呼び出しで同じVBOを使用して明らかに異なるブロックを大量に描画できることがわかりました。6x6の草地の例では、アトラスの1つの次元でのみ繰り返すため、12個の三角形に分割します。

私はほとんどこれを統合されたグラフィックスチップとモバイルの非常にローエンドで動作するようにしました。


3
ボクセルごとに最大で3つの面を描画する必要がありますが、最適化がそれほど簡単ではないため、視点に応じて各ボクセルに異なる面を描画する必要がありますか?事前に作成されたVBOには、複数のボクセルが含まれます。視点がボクセルの中間にある場合、一方のボクセルの東側と他方のボクセルの西側が表示されます。これが役立つ唯一の方法は、実際の背面を簡単にカリングできることですが、最悪の場合は、ボクセルのグループで6面のうち5面をレンダリングします。視点がVBOの軸方向の制限の外側にある場合、3つの側面をレンダリングするだけです。
ビヨンウェセン

その実行可能なビヨンのスポット。(しかし、私はむしろ、すべての回でVBOsで全世界を持つよりも、必要とするときカメラが移動私が築いてきたものを再考としてのブロックのVBOsを作成しています。私は、これらの選択をする自然な時間を持っているので)
ウィル

10

インスタンス化された配列を使用する3番目のオプションはどうですか?基本的に、1回の描画呼び出しで多数のボックス(単純な8頂点キューブで作成)を描画し、位置(およびその他のデータ)をボクセルデータVBOからインスタンスごとの属性として取得します(glVertexAttribDivisorOpenGLで使用します。 DXにもあります)。これはジオメトリシェーダーアプローチよりも速いかもしれませんが、アプリケーションコード(シェーダーではない)は非常に似ているはずです。 2.1ハードウェア上。

ただし、とにかく、特にボクセルデータが変更される場合は、ジオメトリシェーダーまたはインスタンス化された配列のいずれかが、CPUで構築されたボクセルジオメトリよりも適している必要があります。変換フィードバック(DXのストリーム出力?)と組み合わせて、GPUベースの優れたカリングテクニックを設定できる場合があります。


ええ、これがこの問題の最良の解決策です。なぜ私には起こらなかったのですか?:)
ノタベン

いくつかの実験を行った後、ベイク処理されたジオメトリがインスタンス化を大幅に上回ることを伝える必要があります。ただし、ジオメトリシェーダーはまだ試していません。
ジャリコンパ

@JariKomppaでは、ベイク処理されたジオメトリの意味を詳しく説明できますか?
スティーブンルー

インスタンスは事前に翻訳され、単一のメッシュにコピーされます。100個のキューブなどを表す1つのメッシュを持っているようなものです。
ヤリコンパ

@JariKomppa同じ結果を見て、メッシュの作成がはるかに高速になりました。ただし、gtx 680では、インスタンス化オプションは非常に高速に動作するようです。
レヴィH

1

ジオメトリシェーダーバージョンの方がずっといいですね。ポイントvboと構築ボックスのみをオンザフライで使用できます(入力ポイント、出力三角形ストリーム)。それは高速で(シェーダーモデル5 eq。DX11でテッセレーションユニットを使用する場合はさらに高速)、帯域幅を大幅に削減し、きれいできれいなソリューションになります。

GSについて。頂点シェーダーとピクセルシェーダーの間に配置され、出力される頂点(プリミティブ)ストリームを変更します。頂点シェーダーは頂点でのみ機能しますが、ジオメトリシェーダーはプリミティブ全体で機能します。このストリームの出力はピクセルシェーダーのみに送られ(コースの前にラスタライズされます:))、保存する方法はありません。(たぶん、テクスチャへのクレイジーなレンダリングとそれによる解析によって...しかし、本当の簡単な可能性はありません)

パフォーマンスに関する注意:ジオメトリシェーダーのすべてを実行し、頂点シェーダーをスキップ(データを渡すだけ)できる必要があります。しかし、それは最善の方法ではありません。より良い(より速い)ことは、頂点シェーダーで可能な限りの変換を行い、ジオメトリシェーダープログラムを最小限に抑えることです。必要に応じて、サイクルに使用することを恐れないでください(ボックスの作成など)。コンパイラはそれを展開します。


2
ジオメトリおよび/または頂点シェーダーで隣接するボクセルを確認し、頂点が破棄されるか、面がオクルードされている場合はスキップすることをお勧めします。それ以外の場合、GSソリューションは代わりに使用帯域幅を増やします。
タムシ

帯域幅は(私の経験から)大きな問題にはなりませんが、もちろんそれは真実です。そして、GSの他のプリミティブを検索することはできません(知っていますか:))。
ノタベン

@Tamschi:はい、この問題を書いた直後にこの問題が発生しました。差分..
ビヨンウェセン

1
シェーダーで頂点バッファーをisamplerBufferまたはusamplerBufferユニフォームにバインドしてから、texture(name_of_uniform、index)でルックアップを実行できます。別のオプションは、バッファを均一な配列にバインドすることです。これにより、使用する頂点フォーマットを自由に選択できます。
タムシ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.