glDrawArrays vs glDrawElements
Ok, also ich bin immer noch kämpfen, um diese zu arbeiten. Die wichtigen Teile von meinem code:
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)
Ich glaube nicht, dass es etwas falsch hier von dem, was ich bisher gelesen habe über die VBO ist. So, jetzt habe ich meine vertex normals(noch nicht verwendet) - und Dreieck-Indizes-Puffer. Jetzt für die eigentliche Attraktion:
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 ?!)**
Nun die glDrawArrays funktioniert. Aber in dem Fall, wo ich ziehen meinem Dreiecke, die es nicht zeichnen sich die Dreiecke, die ich definiert habe, in bufferTriangles(das ist normal von was ich gelesen habe, da drawArrays nicht Indizes ? Oder bin ich hier falsch? ). Das problem ist, dass wenn ich versuche, die glDrawElements alles stürzt ab mit:
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
Bin jetzt was vermisse ich hier? Von was ich verstehen kann bin ich wohl vorbei ein Ungültiger Zeiger irgendwo? Beachten Sie, dass selbst wenn ich versuche, glDrawElements(Art, 24, GL_UNSIGNED_INT, 0) es stürzt immer noch, auch wenn die Anzahl der Dreiecke definiert ist, wie viel größer so dass ich don ' T glaube, es hat etwas zu tun mit der Größe.
Grüße,
Bogdan
EDIT:
Ok also ich hab jetzt schon einige zusätzliche Prüfung und hier ist meine derzeitige situation: ich habe mich verändert die len(Dreiecke) an ADT.byteCount, keine Lösung. So überprüfte ich alle Daten, die ich immer war und ist es so, dass Die vertices-array enthält ~60000 * 3 = 180000 Eckpunkte Einträge von GL_Float Art, wie die-normalen-array. Da gibt es nur < 62535 vertices bin ich mit short-Typ ohne Vorzeichen für die Dreiecke. Also ich habe len(Dreiecke) ist ~135000. Habe ich auch geändert die glDrawElements(GL_TRIANGLES, len(self.Dreiecke), GL_UNSIGNED_SHORT, 0) .Ich habe auch überprüft, und alle Daten aus den Dreiecken array ist zwischen 0 und 62534, als ich dachte, vielleicht einige index out of range rutschte Trog. Was könnte hier falsch sein ?
Oh, und wie funktioniert glDrawElements(GL_POINTS, ...) arbeiten? Es tut brauchen auch Indizes ?
EDIT2
Ich habe aktualisiert, der code oben, und wie gesagt da, nun ziehen Sie Elemente zieht meine GL_POINTS, aber ich bin mir nicht sicher, wo er bekommt Indizes? Oder sind Sie nicht erforderlich, im Falle von GL_POINTS ? Und für die GL_TRIANGLES, es funktioniert wie diese , mit glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, selbst.bufferTriangles) kommentierte, aber wieder was von Indizes dauert es hier jetzt, dass die element-Puffer gebunden zu 0 ?! Und eine andere Sache ist, dass glDrawElements nicht zeichne alle Punkte, die glDrawArrays tut. Besser explatin:
glDrawArrays( GL_POINTS, 0, len(self.vertices) );
Dieser zieht alle meine Punkte richtig:
glDrawElements(type, len(self.vertices), GL_UNSIGNED_SHORT, 0)
Dieser scheint sichtlich zeichnen viel weniger Punkte als glDrawArrays. Jetzt das lustige an der Sache ist, dass wenn ich den pass als Größe so etwas wie 10 * len(self.Scheitelpunkte) ziehen Elementen es zeichnen Sie alle Punkte(einige vielleicht auch zweimal oder mehr ; kann ich das überprüfen? - ) aber würde es wohl zu Abstürzen ?
Hinsichtlich
EDIT3
Etwas genauere info über die arrays:
Ecken - ein array von floats,
len(Knoten) = 180000
byteCount(vertices) = 720000
Dreiecke - ein array von numpy.uint16
len(Dreiecke) = 353439
byteCount(Dreiecke) = 706878
min(Dreiecke) = 0
max(Dreiecke) = 59999 , so dass Sie zeigen sollte, um gültige Eckpunkte
Die Zeichnung ist fertig:
glDrawElements(GL_TRIANGLES, len(self.Dreiecke) , GL_UNSIGNED_SHORT, 0)
UPDATE
Ok gerade als ich den Gedanken bekam ich, wie sollte dies funktionieren, ich habe versucht, das überspringen der VBO für die Elemente und ging nur:
glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, ADT.voidDataPointer(self.triangles))
Nun nicht nur diese Arbeit und zieht alle meine Dreiecke perfekt, aber die FPS ist besser. Sollte nicht die VBO schneller sein? Und was könnte die Ursache der oben erwähnten Ansatz zu arbeiten, aber der folgende Absturz:
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)
Du musst angemeldet sein, um einen Kommentar abzugeben.
Habe ich keine Erfahrung mit Python GL, aber ich denke, entdeckte ich etwas. Verwenden Sie
len(self.triangles)
im AufrufglDrawElements
, so nehme ich an, gibt Sie die Anzahl der Indizes in die Dreiecke array. Aber warum dann mitlen(triangles)
als Größe inglBufferData
und nichtADT.arrayByteCount
wie in den anderen fordert. Also dein Puffer ist einfach zu klein, als es enthältlen(triangles)
bytes, obwohl Dreiecke enthält unsigned ints. Wenn Dreiecke wirklich enthält bytes (was ich bezweifle) würden Sie verwendenGL_UNSIGNED_BYTE
imglDrawElements
.EDIT: Nach deiner edits habe ich einige Antworten mehr. Natürlich
glDrawElements(GL_POINTS, ...)
braucht Indizes auch. Es verwendet einfach jeder index zeichnen ein Punkt, statt alle drei Indizes für ein Dreieck. Es ist nur so, dass für Punkte, die Sie oft nicht brauchenglDrawElements
, als Sie nicht wiederverwenden Eckpunkte sowieso, aber Sie müssen noch Indizes für Sie. Es nicht wie von Zauberhand zu einemglDrawArrays
Anruf unter der Haube.Und im Kopf behalten, dass die
vertices
array enthält schwimmt undglDrawArrays
zieht vertices, so haben Sie zu zeichnenlen(vertices)/3
Eckpunkte. Ragt denken Sie daran, ein element ist ein index (eine einzelne vertex), ein Dreieck und eine vertex 3 floats (oder was Sie angegeben haben, inglVertexPointer
), nicht nur eine.Aber wenn Ihr
triangles
array wirklich enthält Tupel der 3 Indizes (und daherlen(triangles)
ist das Dreieck zählen und nicht die index-Zählung) müssten Sie zeichnen3*len(triangles)
Elemente (Indizes). und wenn Ihrvertices
array Vektoren enthält, und nicht nur schwebt, dann zeichnenlen(vertices)
Eckpunkte in der glDrawArrays call korrekt ist. Daher wäre es schön zu sehen, Ihre Erklärungen, um sicher zu sein.In meiner Erfahrung, die Python-OpenGL-wrapper ist sehr buggy, sobald Sie anfangen, über einige erweiterte OpenGL-Aufrufe. Viele Anrufe scheinen verursachen einen Absturz ohne Grund und manchmal funktioniert, wenn Sie ersetzen Sie Sie durch eine gleichwertige Sequenz von anderen fordert...ich wechselte Programmiersprachen für OpenGL anstatt diese Probleme zu bewältigen.
Der Grund, warum
funktioniert und
nicht ist, weil PyOpenGL erwartet
None
als void-Zeiger, statt 0. Seien Sie vorsichtig bei der Verwendung von OpenGL-Beispiele in C geschrieben, weil Sie(void*)0
als void-Zeiger, das ist nicht richtig interpretieren als Zeiger, die von PyOpenGL, die anstelle behandelt 0 als nicht-void-Wert.Verwenden Sie stattdessen
(Siehe auch https://stackoverflow.com/a/14365737/478380)