8

わかりましたので、これを機能させるのにまだ苦労しています。私のコードの重要な部分は次のとおりです。

def __init__(self, vertices, normals, triangles):
    self.bufferVertices = glGenBuffersARB(1)
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, self.bufferVertices)
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, ADT.arrayByteCount(vertices), ADT.voidDataPointer(vertices), GL_STATIC_DRAW_ARB)
    self.vertices = vertices
    self.bufferNormals = glGenBuffersARB(1)
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, self.bufferNormals)
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, ADT.arrayByteCount(normals), ADT.voidDataPointer(normals), GL_STATIC_DRAW_ARB)
    self.normals = normals
    self.bufferTriangles = glGenBuffersARB(1)

    glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, self.bufferTriangles)
    glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ADT.arrayByteCount(triangles), ADT.voidDataPointer(triangles), GL_STATIC_DRAW_ARB)

    self.triangles = triangles
    glDisableClientState(GL_VERTEX_ARRAY) **(Not sure if any of the following influence in any way)** 
    glDisableClientState(GL_NORMAL_ARRAY)
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)
    glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)

VBOについてこれまで読んだことから、ここに何か問題があるとは思いません。これで、頂点、法線 (まだ使用されていません)、三角形のインデックス バッファーができました。実際の抽選は次のとおりです。

def draw(self, type):
    glDisableClientState(GL_VERTEX_ARRAY)  
    glDisableClientState(GL_NORMAL_ARRAY)
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)
    glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)
    **Again above line not sure if they have any use.**        
    glEnableClientState(GL_VERTEX_ARRAY)         
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, self.bufferVertices)
    glVertexPointer(3, GL_FLOAT, 0, None)

    glEnableClientState(GL_NORMAL_ARRAY);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, self.bufferNormals)
    glNormalPointer(GL_FLOAT, 0, None)

    if type == GL_POINTS:    
        #glDrawArrays( GL_POINTS, 0, len(self.vertices) );    
        glDrawElements(type, len(self.vertices), GL_UNSIGNED_SHORT, 0)
    else:
        #glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, self.bufferTriangles)**(If I uncomment this doesnt seem to make any difference?!)**
        #glDrawArrays( GL_TRIANGLES, 0, len(self.triangles) );  
        glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, 0)**(What does it draw now since GL_ELEMENT_ARRAY_BUFFER_ARB is binded to 0 ?!)**

glDrawArrays が機能するようになりました。しかし、三角形を描画する必要がある場合、bufferTriangles で定義した三角形は描画されません (drawArrays はインデックスを使用しないため、これは私が読んだものからは正常です? または、ここで間違っていますか? )。問題は、glDrawElements を使用しようとすると、すべてが次のようにクラッシュすることです。

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x000000003150ebbc
Crashed Thread:  0

Thread 0 Crashed:
0   com.apple.GeForce8xxxGLDriver   0x1a3e7050 gldGetTextureLevel + 743600
1   com.apple.GeForce8xxxGLDriver   0x1a3e7563 gldGetTextureLevel + 744899
2   GLEngine                        0x1a206eee gleDrawArraysOrElements_VBO_Exec + 1950

今、私はここで何が欠けていますか? 私が理解できることから、おそらくどこかで悪いポインターを渡していますか? glDrawElements(type, 24, GL_UNSIGNED_INT, 0) を使用しようとしても、定義された三角形の数がはるかに多くてもクラッシュするので、サイズとは関係ないと思います。

よろしく、 ボグダン

編集: わかりましたので、追加のチェックを行ったので、現在の状況を以下に示します: len(triangles) を ADT.byteCount に変更しましたが、まだ解決策はありません。取得していたすべてのデータを確認したところ、次のようになりました。頂点配列には、法線配列と同様に、GL_Float タイプの ~60000 * 3 = 180000 頂点エントリが含まれています。< 62535 個の頂点しかないため、三角形には unsigned short を使用しています。したがって、len(三角形) は ~135000 です。glDrawElements(GL_TRIANGLES, len(self.triangles), GL_UNSIGNED_SHORTも変更しました, 0) .私もチェックしましたが、三角形配列からのすべてのデータは 0 から 62534 の間にあります。ここで他に何が間違っている可能性がありますか? ああ、glDrawElements(GL_POINTS, ...) はどのように機能しますか? ある種のインデックスも必要ですか?

EDIT2上記のコードを更新しました。そこで述べたように、描画要素がGL_POINTSを描画するようになりましたが、彼がどこでインデックスを取得するのかわかりませんか? それとも GL_POINTS の場合は必要ありませんか? GL_TRIANGLES の場合、glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, self.bufferTriangles) がコメント化された状態で、このように機能しますが、エレメント バッファーが 0 にバインドされた今、ここでどのような種類のインデックスが必要になるのでしょうか?! もう 1 つのことは、glDrawElements は glDrawArrays が行うすべてのポイントを描画しないということです。よりよく説明するには:

glDrawArrays( GL_POINTS, 0, len(self.vertices) );

これは私のすべてのポイントを正しく描画します:

glDrawElements(type, len(self.vertices), GL_UNSIGNED_SHORT, 0)

これは、glDrawArrays よりもはるかに少ないポイントを目に見えて描画するようです。ここで面白いことに、要素を描画するために 10 * len(self.vertices) のようなサイズを渡すと、すべてのポイントが描画されます (おそらく 2 回以上; これを確認できますか?)。

よろしく

EDIT3

配列に関するより正確な情報:

vertices - float の配列、

len(頂点) = 180000 byteCount(頂点) = 720000

三角形 - numpy.uint16 の配列

len(triangles) = 353439 byteCount(triangles) = 706878 min(triangles) = 0 max(triangles) = 59999 であるため、有効な頂点を指している必要があります

描画は次のように行われます。

glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, 0)

アップデート

これがどのように機能するかを理解したとき、要素の VBO をスキップしようとしましたが、次のようになりました。

glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, ADT.voidDataPointer(self.triangles))

これが機能し、すべての三角形を完全に描画するだけでなく、FPS も改善されました。VBO は高速であるべきではありませんか? そして、上記のアプローチが機能するのに、次のものがクラッシュする原因は何ですか。

glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, self.bufferTriangles)
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ADT.arrayByteCount(triangles), ADT.voidDataPointer(triangles), GL_STATIC_DRAW_ARB)
glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, 0)
4

3 に答える 3

4

私は Python GL の経験はありませんが、何かを見つけたと思います。len(self.triangles)の呼び出しで使用するglDrawElementsので、三角形配列のインデックスの数が得られると思います。しかし、なぜlen(triangles)サイズを使用し、他の呼び出しでは好きではglBufferDataないのですか。したがって、三角形には符号なし整数が含まれていますが、バッファーにはバイトがADT.arrayByteCount含まれているため、バッファーが小さすぎます。len(triangles)三角形に実際にバイトが含まれている場合 (私には疑問です)、 in で使用する必要がありGL_UNSIGNED_BYTEますglDrawElements

編集:あなたの編集によると、私はいくつかの答えを得ました。もちろんglDrawElements(GL_POINTS, ...)インデックスも必要です。三角形の 3 つのインデックスごとではなく、すべてのインデックスを使用して点を描画します。とにかく頂点を再利用しないので、ポイントの場合は必要ないことがよくありますglDrawElementsが、それでもインデックスが必要です。魔法のように内部でglDrawArrays呼び出しになるわけではありません。

また、vertices配列には float が含まれておりglDrawArrays、頂点を描画するため、頂点を描画する必要があることに注意してくださいlen(vertices)/3。覚えておいてください、要素は (単一の頂点の) インデックスであり、三角形ではなく、頂点は 3 つのフロート (または で指定したものglVertexPointer) であり、1 つだけではありません。

しかし、triangles配列に実際に 3 つのインデックスのタプルが含まれている場合 (したがってlen(triangles)、三角形の数であり、インデックスの数ではありません)、3*len(triangles)要素 (インデックス) を描画する必要があります。vertices配列にフロートだけでなくベクトルが含まれている場合len(vertices)、glDrawArrays 呼び出しで頂点を描画することは正しいです。したがって、彼らの宣言を確認できるとよいでしょう。

于 2011-05-25T13:30:32.513 に答える
0

その理由

glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, ADT.voidDataPointer(self.triangles))

作品と

glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, 0)

NoneC で記述された OpenGL の例を使用する場合は注意してください。これは、PyOpenGL によってポインターとして正しく解釈されず、代わりに 0 を扱う void ポインターとして使用されるためです(void*)0。非 void 値として。

代わりに、使用する必要があります

glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, None)

( https://stackoverflow.com/a/14365737/478380も参照)

于 2015-09-17T00:23:15.193 に答える
0

私の経験では、より高度な OpenGL 呼び出しを使い始めると、Python OpenGL ラッパーは非常にバグが多くなります。多くの呼び出しは理由もなくクラッシュを引き起こすようであり、それらを別の呼び出しの同等のシーケンスに置き換えるとうまくいくことがあります...これらの問題に対処する代わりに、プログラミング言語を OpenGL に切り替えました。

于 2011-06-03T20:29:57.873 に答える