2

私はグラフィックプログラミングに不慣れで、作成しているデモのレンダリングバックエンドを追加する必要があります。皆さんが私を正しい方向に向けてくれることを願っています。

短いバージョン:要素ごとに個別に描画コマンドを発行することなく、OpenGLに個別の要素のデータの配列を送信する方法はありますか?

ロングバージョン:CUDAプログラム(最終的にはOpenCLになる)があり、オブジェクトの束のデータの束を計算します。次に、OpenGLなどを使用してこれらのオブジェクトをレンダリングする必要があります。

CUDAカーネルは頂点を生成でき、OpenGL相互運用機能を使用して、これらをOpenGL VBOに押し込み、データをホストデバイスメモリに転送する必要がありません。しかし、問題は、多数の(100万以上が私たちの目標です)別個のオブジェクトがあることです。ここでの最善の策は、1つのVBOを割り当て、すべてのオブジェクトの頂点をそこに配置することのようです。次に、そのVBO内の各要素のオフセットと長さを使用してglDrawArraysを呼び出すことができます。

ただし、各オブジェクトには可変数の頂点がある場合があります(ただし、シーン内の頂点の総数は制限できます)。特に、フレームごとにCUDA->CPUから開始インデックスと長さのリストを転送する必要はありません。これらの描画コマンドはGPUに直接戻ります。

OpenGLへの呼び出しを1回だけ発行してバッファーをレンダリングし、そのバッファーからいくつかの異なる要素をレンダリングできるように、バッファーにデータをパックする方法はありますか?

(うまくいけば、ここでXY問題を回避するのに十分な情報を提供しました。)

4

2 に答える 2

3

1 つの方法は、これらを個別のオブジェクトとして理解することから離れて、単一の描画呼び出しで描画される単一の大きなオブジェクトにすることです。問題は、オブジェクトを互いに区別するのはどのデータか、つまり、個々の呼び出し間で何を変更するかということglDrawArrays/glDrawElementsです。

色のように単純なものである場合は、これに追加の頂点ごとの属性を提供する方がおそらく簡単でしょう。このようにして、個々のサブオブジェクト (現在は概念的にしか存在しない) を正しく色付けした単一の描画呼び出しを使用して、すべてのオブジェクトを 1 つの大きなオブジェクトとしてレンダリングできます。追加の属性のメモリ コストは、それだけの価値がある場合があります。

もう少し複雑なもの (テクスチャなど) の場合でも、追加の頂点ごとの属性を使用してインデックスを作成できる場合があります。これは、テクスチャ配列へのインデックスのいずれかです (テクスチャ配列は CUDA/OpenCL でサポートされている必要があるため)。可能なハードウェア) または単一の大きなテクスチャ (いわゆるテクスチャ アトラス) の特定のサブ領域へのテクスチャ座標。

しかし、これらのオブジェクトの違いが、シェーダーの違いなど、より複雑な場合は、個々のオブジェクトをレンダリングし、個々の描画呼び出しを行う必要があるかもしれません。ただし、CPU へのラウンドトリップを必ずしも行う必要はありません。ARB_draw_indirect拡張 (これは GL 4.0 以降のコアであると思いますが、GL 3 ハードウェア (および CUDA/CL ハードウェア) でサポートされている可能性があります) を使用すると、次の呼び出しに引数を渡すことができますglDrawArrays/glDrawElements。追加のバッファー (他の GL バッファーと同様に CUDA/CL で書き込むことができます)。そのため、GPU 上の各オブジェクトのオフセット長情報をまとめて、単一のバッファーに格納できます。次に、あなたはあなたのglDrawArraysIndirectこの単一の draw-indirect-buffer へのオフセットをループします (個々のオブジェクト間のオフセットは一定になりました)。


しかし、複数の描画呼び出しを発行する唯一の理由が、オブジェクトを 1 つまたは 1 つGL_TRIANGLE_STRIPGL_TRIANGLE_FANs (または、注意してくださいGL_POLYGON) としてGL_TRIANGLESレンダリングすることである場合は、すべてのオブジェクトを単一の描画呼び出し。トライアングル ストリップを使用することによる (おそらく) 時間とメモリの節約は、特に多数の小さなトライアングル ストリップをレンダリングする場合に、複数の描画呼び出しのオーバーヘッドよりも優先される可能性があります。ストリップまたはファンを本当に使用したい場合は、1 回の描画呼び出しで描画された場合でも、(頂点を繰り返すことによって) 縮退した三角形を導入してそれらを互いに分離することをお勧めします。glPrimitiveRestartIndexまたは、GL 3.1 で導入された機能を調べることもできます。

于 2012-05-22T09:03:01.057 に答える
0

おそらく最適ではありませんが、バッファ全体で単一の glDrawArray を作成できます...

  • GL_TRIANGLES を使用すると、バッファーをゼロで埋めて、必要な頂点だけをカーネルに書き込むことができます。このように、バッファの「空の」領域は、面積が 0 のポリゴンとして描画されます (= 縮退ポリゴン -> まったく描画されません)。
  • GL_TRIANGLE_STRIP を使用する場合も同じことができますが、(0,0,0) とメッシュの間に偽の三角形を作成するために、最初の頂点を複製する必要があります。

これはやり過ぎに思えるかもしれませんが、: - とにかく多くの頂点を処理できる必要があります - 縮退した三角形はフィルレートを使用しないため、ほとんど自由です (ただし、頂点シェーダーはまだ計算されます)。

おそらくより良い解決策は、代わりに glDrawElements を使用することです。カーネルでは、バッファー全体のインデックスリストも生成します。これにより、バッファーの領域を完全にスキップできます。

于 2012-05-22T07:33:34.827 に答える