1

「glDrawElements」(および glDrawArrays) でアプリケーションがクラッシュします。

知りたいのですが、クラッシュの原因は何ですか?

現在、私はそれを持っています:

Foreach mesh

     - Bind VBO/VAO

           if( VAO empty )

                - bind VAO(id)
                - bind VBO(id)

                Foreach attribs
                    - glEnableVertexAttribArray
                    - glVertexAttribPointer
                End foreach

                - unbindVAO(0)
                - unbindVBO(0)

                Foreach attribs
                    - glDisableVertexAttribArray
                End foreach

            endif

     - Bind IBO(id)

     - Bind program/shader(id)
        -> send uniforms

     -> glDrawElements

End foreach
  • 多くの VBO/VAO/IBO があると、glDrawElements でアプリケーションがクラッシュします。
  • さまざまなデバイスで、多くの VAO/VBO/IBO を取得すると、奇妙なアーティファクトが発生します

バッファーに奇妙な点があると思います (競合など)。バインディングの正しい順序は何ですか? VAO、VBO、IBO、プログラム、テクスチャなどのバインドを解除する必要がある場所はどこですか?

編集:

ジオメトリを削除するとクラッシュが発生するようです。彼のバッファは opengl から削除されます (もう使用しないため)。したがって、私のバッファーは常に制限されていると思います。

OpenGL トレース:

glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 8)
glEnableVertexAttribArray(index = 2)
glVertexAttribPointer(indx = 2, size = 3, type = GL_FLOAT, normalized = false, stride = 20, ptr = 0x0)
glEnableVertexAttribArray(index = 0)
glVertexAttribPointer(indx = 0, size = 4, type = GL_UNSIGNED_BYTE, normalized = true, stride = 20, ptr = 0xc)
glEnableVertexAttribArray(index = 4)
glVertexAttribPointer(indx = 4, size = 2, type = GL_UNSIGNED_SHORT, normalized = true, stride = 20, ptr = 0x10)
glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 0)
glBindBuffer(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 7)
glUseProgram(program = 0)
glUseProgram(program = 6)
glUniformMatrix4fv(location = 2, count = 1, transpose = false, value = [1.6974937, 0.0, 0.0, 0.0, 0.0, 2.100419, -0.49304545, -0.49301255, 0.0, -1.1902374, -0.87008023, -0.8700222, -9.582167, -2.1815264, 15.627364, 15.64632])
glActiveTexture(texture = GL_TEXTURE0)
glBindTexture(target = GL_TEXTURE_2D, texture = 1)
glUniform1i(location = 8, x = 0)
glDisable(cap = GL_BLEND)
glBlendFunc(sfactor = GL_LINES, dfactor = GL_POINTS)
glEnable(cap = GL_DEPTH_TEST)
glUniformMatrix4fv(location = 7, count = 1, transpose = false, value = [50.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 50.0, 0.0, 0.0, -0.1, -150.0, 1.0])
glUniform3fv(location = 3, count = 1, v = [0.8235294, 0.8235294, 0.8235294])
glUniform2fv(location = 0, count = 1, v = [0.0, 0.0])
glUniform2fv(location = 1, count = 1, v = [1.0, 1.0])
glDrawElements(mode = GL_TRIANGLE_STRIP, count = 4, type = GL_UNSIGNED_BYTE, indices = 0x0)
4

2 に答える 2

3

VAO のバインドを解除したは、頂点属性配列を無効にしないでください。OpenGL 3 コア コンテキストでは、VAO をアンバインドすると、適用する頂点配列コマンドのコンテキストがなくなります。常に VAO をバインドしておく必要があります。そうしないと、これらのコマンドは無効な操作になります。

さらに、VAO は頂点配列の状態を永続的に保存します。アイデアは、何かを描画するたびに状態を有効または無効にする代わりに、必要なすべての状態が既に設定されている VAO をバインドするだけです。

Vertex Array Objects を使用して頂点配列を設定する方法については、次のように考える必要があります。VAO はほとんどの状態を格納するため、状態リークを防ぐために頂点配列を無効にしたり、VBO をバインド解除したりする必要はありません。別の頂点配列を描画したいときはいつでも、バインドされた VAO を変更するだけです。

ステージ 1: GL 頂点配列/バッファー オブジェクトの初期化

メッシュが構築される場合:

  - VAO、VBO、IBO の生成
  - VAO、VBO、IBOをバインド

   -> 頂点データを VBO にアップロード
   -> インデックス配列を IBO にアップロード

  Foreach 属性 <n>
    - 属性ポインタの設定 (n)
    - 属性配列を有効にする (n)
  Foreach の終了  

ステージ 2:メッシュ インスタンスの描画

オブジェクト (メッシュのインスタンス) がレンダリングされるとき:

  - バインド メッシュの VAO

  - バインド プログラム/シェーダー(id)
    →ユニフォームを送る

  -> glDrawElements

また、ソフトウェアが正しくセットアップされている場合、VAO のバインドを解除する必要はありません (たとえば、頂点配列を使用して描画するものはすべて、状態を管理するための独自の VAO を持っています)。テクスチャの適用について考えてみてください。何かを描画した後にテクスチャをアンバインドすることはめったにありません。描画する次のバッチは、必要なテクスチャの状態を正確に把握している必要があります。別のテクスチャが必要な場合 (またはまったく必要ない場合) はテクスチャの状態を変更する必要があります。バッチごとにテクスチャの状態を復元することはリソースの無駄であり、頂点配列の状態を復元することも同様です。


余談ですが、あなたの OpenGL トレースを調べていて、あなたが気付いていない可能性のあるものに出会いました。GL_UNSIGNED_BYTEAPI によって提供されるが、必ずしもハードウェアによってサポートされているとは限らないインデックスを使用しています。多くのハードウェア (デスクトップ GPU など)GL_UNSIGNED_SHORT推奨されるインデックス タイプです (頂点のコレクションが非常に小さい場合でも)。を使用GL_UNSIGNED_BYTEするとスペースが節約され、頂点が 256 未満の場合にスループットが向上すると思いがちですが、実際には「高速パス」から外れることがあります。ハードウェアが 8 ビットのインデックスをサポートしていない場合、ドライバーは必然的に、インデックスを送信した後にインデックスを 16 ビットに変換する必要があります。そのような場合、ドライバーのワークロードが増加し、残念ながら GPU メモリは節約されません。

于 2013-08-23T21:17:33.983 に答える