调用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)顶点是正确的。因此很高兴看到他们的声明是确定的。

+0

是的,使用glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,4 * LEN(三角形),ADT.voidDataPointer(三角形),GL_STATIC_DRAW_ARB)。用sizeof(unsigned int) – Calvin1602 2011-05-25 13:56:18

+0

的python替换“4”好的谢谢,但是当我尝试这样做时,我在那里发生了崩溃。该缓冲区是否有一些最大尺寸?目前,我的三角形长度为353439,字节数为1413756。这是否会导致崩溃? – Bogdan 2011-05-25 15:27:27

+0

忽略我最后的评论。我会仔细看看,然后回来。 – Bogdan 2011-05-25 15:30:23

根据我的经验,一旦你开始使用一些更高级的OpenGL调用,Python OpenGL封装器就非常麻烦。许多调用似乎无缘无故地导致崩溃,有时甚至会以相同顺序的不同调用来替代它们......我为OpenGL切换了编程语言,而不必处理这些问题。

+0

是的,我注意到,仍然有一些越野车方面,尤其是当使用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) 

(参见https://*.com/a/14365737/478380