调用glDrawArrays VS glDrawElements
好了,所以我仍然在努力得到这个工作。我的代码的重要部分是:调用glDrawArrays VS glDrawElements
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(类型,24,GL_UNSIGNED_INT,0),它仍然崩溃甚至寿定义的三角形数量是这样的方式更大,所以我不认为这有什么与大小。
问候, 波格丹
编辑: 好了,所以现在我已经做了一些额外的检查,这里是我目前的情况:我已经改变了LEN(三角形),以ADT.byteCount,无解然而。所以我检查了我得到的所有数据,它是这样的:顶点数组包含~60000 * 3 = 180000个GL_Float类型的顶点条目,和法线数组一样。由于只有< 62535顶点我使用无符号三角形短。所以我有len(三角形)是~135000。我也改变了glDrawElements(GL_TRIANGLES,LEN(self.triangles),GL_UNSIGNED_SHORT,0).I've还检查了所有的数据从三角形阵列是0和62534之间,我想也许一些指数这是超出范围滑槽。这里还有什么可能是错的? 哦,glDrawElements(GL_POINTS,...)是如何工作的?它是否也需要某种指数?
EDIT2 我已经更新上面的代码和说有,现在画的元素吸引我的GL_POINTS,但我不知道他在哪里得到指数?或者在GL_POINTS的情况下不需要它们?而对于GL_TRIANGLES,它是这样工作的,与glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,self.bufferTriangles)commentated,却又什么样的指标它现在的元素缓冲区绑定到0采取这里?!另一件事是,glDrawElements不会绘制glDrawArrays所做的所有点。为了更好地explatin:
glDrawArrays(GL_POINTS, 0, len(self.vertices));
这正确吸取我的所有点:
glDrawElements(type, len(self.vertices), GL_UNSIGNED_SHORT, 0)
这似乎明显吸取少得多百分点,比调用glDrawArrays。现在,有趣的是,如果我通过为大小像10 * LEN(self.vertices)来绘制,将绘制所有点元素(有的也许两次以上的;我可以检查这个?),但母舰一样想崩溃?
问候
EDIT3
关于阵列的一些更精确的信息:
顶点 - 浮点数的数组,
LEN(顶点)= 180000 BYTECOUNT(顶点) = 720000
triangles - 一个numpy.uint16的数组
LEN(三角形)= 353439 BYTECOUNT(三角形)= 706878 分钟(三角形)= 0 最大值(三角形)= 59999,所以它们应指向有效顶点
的附图进行:
glDrawElements(GL_TRIANGLES,LEN(self.triangles),GL_UNSIGNED_SHORT,0)
UPDATE
好吧只是当我因子评分我这应该是如何工作的,我试图跳过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)
我有使用Python GL没有经验,但我想我发现了一些东西。你在调用glDrawElements
时使用len(self.triangles)
,所以我想这会给你三角形数组中索引的数量。但为什么然后在glBufferData
中使用len(triangles)
作为大小,而不是在其他调用中使用ADT.arrayByteCount
。所以你的缓冲区太小了,因为它包含len(triangles)
字节,尽管三角形包含未签名的整数。如果三角形确实包含字节(我怀疑),您将不得不在glDrawElements
中使用GL_UNSIGNED_BYTE
。
编辑:根据您的编辑我得到了更多的答案。当然glDrawElements(GL_POINTS, ...)
也需要索引。它只是使用每个索引来绘制一个点,而不是每三个三角形的索引。这只是因为你经常不需要glDrawElements
,因为你不会重复使用顶点,但是你仍然需要它的索引。它不会神奇地变成引擎盖下的glDrawArrays
。
并记住,vertices
数组包含浮动和glDrawArrays
绘制顶点,因此您必须绘制len(vertices)/3
顶点。 Juts记得,一个元素是一个索引(单个顶点),而不是一个三角形,顶点是3个浮点数(或者你在glVertexPointer
中指定的),而不仅仅是一个。
但是,如果您的triangles
数组确实包含3个索引的元组(因此len(triangles)
是三角形数而不是索引数),则必须绘制3*len(triangles)
元素(索引)。并且如果您的数组包含矢量而不仅仅是浮点数,则在glDrawArrays调用中绘制len(vertices)
顶点是正确的。因此很高兴看到他们的声明是确定的。
根据我的经验,一旦你开始使用一些更高级的OpenGL调用,Python OpenGL封装器就非常麻烦。许多调用似乎无缘无故地导致崩溃,有时甚至会以相同顺序的不同调用来替代它们......我为OpenGL切换了编程语言,而不必处理这些问题。
是的,我注意到,仍然有一些越野车方面,尤其是当使用VBO的时候,但除了标准C和后面的集成之外,我没有其他选择,我将作为最后的手段离开。 – Bogdan 2011-06-05 16:31:51
之所以
glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, ADT.voidDataPointer(self.triangles))
作品和
glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, 0)
不会是因为PyOpenGL预计None
为void指针,而不是0使用C语言编写的OpenGL的例子时要小心,因为它们使用(void*)0
作为void指针,而PyOpenGL并没有将它正确地解释为一个指针,而它将0视为一个非空值。
相反,你应该使用
glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, None)
是的,使用glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,4 * LEN(三角形),ADT.voidDataPointer(三角形),GL_STATIC_DRAW_ARB)。用sizeof(unsigned int) – Calvin1602 2011-05-25 13:56:18
的python替换“4”好的谢谢,但是当我尝试这样做时,我在那里发生了崩溃。该缓冲区是否有一些最大尺寸?目前,我的三角形长度为353439,字节数为1413756。这是否会导致崩溃? – Bogdan 2011-05-25 15:27:27
忽略我最后的评论。我会仔细看看,然后回来。 – Bogdan 2011-05-25 15:30:23