2

アニメーション化されたスプライトコードを見ているだけで、いくつかのアイデアが得られます。
アニメーションは、tex座標を変更することによって作成されました。新しいフレームが要求されると、現在のフレームテクスチャ座標を保持するバッファオブジェクトがあり、新しいテクスチャ座標はglBufferData()によってバッファにフィードアップされます。

そして、すべてのアニメーションフレームのテクスチャ座標を事前に計算し、それらをBOに入れて、描画する必要のあるフレームの数だけでインデックスバッファオブジェクトを作成するとどうなりますか?

 GLbyte cur_frames = 0; //1,2,3 etc

アニメーションを更新する必要があるので、必要なのは、glBufferDataを使用してIBOの1バイト(TRIANGLE_STRIPを使用したクワッド描画の4/クワッド頂点カウント/* 2 / s、t / * sizeof(GLfloat)バイトの代わりに)フレームを更新することだけです。 、BOの初期化後にテクスチャ座標を保持する必要はありません。

私は何かが足りないのですか?コントラとは何ですか?

編集:もちろん、頂点データは、たとえばgl_floatではない場合があります。

4

2 に答える 2

1

ティムが正しく述べているように、これはアプリケーションによって異なります。いくつかの数値について話しましょう。IBOと、すべてのフレームのテクスチャ座標を1つのVBOに挿入することの両方について言及しいるので、それぞれの影響を見てみましょう。

典型的な頂点が次のようになっているとします。

struct vertex
{
    float x,y,z; //position
    float tx,ty; //Texture coordinates
}

zコンポーネントを追加しましたが、それを使用しない場合、またはより多くの属性がある場合、計算は同様です。したがって、この属性が20バイトかかることは明らかです。

単純なスプライト、つまり2つの三角形で構成される四角形を想定します。非常に単純なモードでは、2x3の頂点を送信6*20=120し、GPUにバイトを送信するだけです。

三角クワッド

インデックス作成では、実際には4つの頂点しかありません1,2,3,4。2つの三角形1,2,32,3,4。したがって、2つのバッファをGPUに送信します。1つは4つの頂点(4*20=80バイト)を含み、もう1つは三角形のインデックスのリスト([1,2,3,2,3,4])を含みます。これを2バイトで実行できるとしましょう(65535のインデックスで十分です)。6*2=12バイトに。合計バイトで、バイトまたは約92を節約しました。また、GPUをレンダリングすると、頂点シェーダーで各頂点が1回だけ処理される可能性が高いため、処理能力もある程度節約できます。2823%

したがって、すべてのアニメーションのすべてのテクスチャ座標を一度に追加する必要があります。最初に注意しなければならないのは、インデックス付きレンダリングの頂点はすべての属性によって定義されるため、位置のインデックスとテクスチャ座標のインデックスに分割することはできないということです。したがって、テクスチャ座標を追加する場合は、位置を繰り返す必要があります。80したがって、追加する各「フレーム」は、VBOにバイトを追加12し、IBOにバイトを追加します。64フレームあるとすると、最終的に64*(80+12)=5888バイトになります。1000個のスプライトがあるとすると、これは約になり6MBます。これはそれほど悪くはないように見えますが、非常に高速にスケーリングされることに注意してください。各フレームはサイズだけでなく、各属性も追加します(繰り返す必要があるため)。

それで、それはあなたに何をもたらしますか?

  1. データをGPUに動的に送信する必要はありません。VBO全体を更新するには、80バイトまたは640ビットを送信する必要があることに注意してください。1000フレームあたりのスプライトに対して301秒あたりのフレーム数でこれを行う必要があるとすると、 19200000bpsまたは19.2Mbps(オーバーヘッドは含まれません)になります。これは非常に低いですが(たとえば、16xPCI-e32Gbpsで処理できます)、他の帯域幅の問題がある場合(たとえば、テクスチャリングが原因)は、検討する価値があります。また、VBOを慎重に構築する場合(たとえば、個別のVBOまたは非インターリーブ)、テクスチャ部分のみを更新するように減らすことができます16。これは、上記の例ではスプライトごとに1バイトのみであり、帯域幅をさらに減らす可能性があります。
  2. 次のフレーム位置の計算に時間を無駄にする必要はありません。ただし、これは通常、テクスチャのエッジを処理するためのいくつかの追加と少数の追加です。ここで多くのCPUパワーが得られるとは思えません。

最後に、アニメーション画像を多くのテクスチャに単純に分割することもできます。これがどのようにスケーリングするかはまったくわかりませんが、この場合、より複雑な頂点属性を操作する必要はなく、アニメーションのフレームごとに別のテクスチャをアクティブにするだけです。

編集:別の方法は、サンプリングの前に、フレーム番号をユニフォームで渡し、フラグメントシェーダーで計算を行うことです。単一の整数ユニフォームを設定することは、それだけのオーバーヘッドになるはずです。

于 2012-08-13T22:59:35.117 に答える
1

最新のGPUの場合、1バイトへのアクセス/アンパックは、整数型やベクトル(レジスタサイズやロード命令など)へのアクセスよりも必ずしも高速ではありません。メモリを節約できるため、メモリ帯域幅を節約できますが、これによって他のすべての頂点属性配列アクセスとの違いが大きくなるとは思いません。

アニメーション化されたスプライトにフレームインデックスを提供する最も速い方法は、均一であるか、1回の描画呼び出しで複数のスプライトをレンダリングする必要がある場合は、インスタンス化された頂点属性配列を使用することです。後者を使用すると、頂点の固定サイズのサブシーケンスに単一のインデックスを提供できます。たとえば、「sprite-quads」を描画する場合、4つの頂点ごとに1つのフレームインデックスフェッチがあります。3番目のアプローチは、インスタンス化されたレンダリングを使用する場合のバッファテクスチャです。

時間/フレームインデックスの計算にはグローバル(共有)ユニフォームをお勧めします。これにより、シェーダー内でアニメーションインデックスをオンザフライで計算できます。これにより、インデックスバッファーを更新する必要がなくなります(これにより、スプライト)

于 2012-08-13T23:06:03.483 に答える