glDrawArrays vs glDrawElements

Bog*_*dan 8 opengl pyopengl

好的,所以我仍然在努力让这个工作.我的代码的重要部分是:

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)
Run Code Online (Sandbox Code Playgroud)

从目前为止我读到的关于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 ?!)**
Run Code Online (Sandbox Code Playgroud)

现在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
Run Code Online (Sandbox Code Playgroud)

我现在在这里错过了什么?根据我的理解,我可能在某处传递了一个坏指针?请注意,即使我尝试使用glDrawElements(type,24,GL_UNSIGNED_INT,0),它仍然会崩溃,即使定义的三角形数量更大,所以我认为它与大小没有任何关系.

此致,波格丹

编辑: 好的,所以现在我做了一些额外的检查,这是我目前的情况:我已经将len(三角形)更改为ADT.byteCount,还没有解决方案.所以我检查了我得到的所有数据,它是这样的:顶点数组包含GL_Float类型的~60000*3 = 180000个顶点条目,normals数组也是如此.由于只有<62535个顶点,我使用无符号的三角形短.所以我有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会是什么样的索引呢?另一件事是glDrawElements不会绘制glDrawArrays所做的所有点.为了更好地解释:

glDrawArrays( GL_POINTS, 0, len(self.vertices) );
Run Code Online (Sandbox Code Playgroud)

这正确地得出了我的所有观点:

glDrawElements(type, len(self.vertices), GL_UNSIGNED_SHORT, 0)
Run Code Online (Sandbox Code Playgroud)

这似乎明显比glDrawArrays吸引的点少得多.现在有趣的是,如果我传递像10*len(self.vertices)这样的大小来绘制元素,它将绘制所有点(有些可能是两次或更多;我可以检查一下吗?)但它不会假设崩溃?

问候

EDIT3

有关阵列的一些更精确的信息:

顶点 - 浮点数组,

len(vertices)= 180000 byteCount(vertices)= 720000

triangles - numpy.uint16的数组

len(三角形)= 353439 byteCount(三角形)= 706878 min(三角形)= 0 max(三角形)= 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))
Run Code Online (Sandbox Code Playgroud)

现在,这不仅可以完美地绘制我的所有三角形,而且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)
Run Code Online (Sandbox Code Playgroud)

Chr*_*ica 4

我没有使用 Python GL 的经验,但我想我发现了一些东西。len(self.triangles)您在对 的调用中使用glDrawElements,所以我想这会为您提供三角形数组中的索引数。但为什么然后使用len(triangles)as sizeglBufferData而不是ADT.arrayByteCount像其他调用一样。所以你的缓冲区太小了,因为它包含len(triangles)字节,尽管三角形包含无符号整数。如果三角形确实包含字节(我对此表示怀疑),则必须GL_UNSIGNED_BYTEglDrawElements.

编辑:根据您的编辑,我得到了更多答案。当然glDrawElements(GL_POINTS, ...)也需要索引。它只是使用每个索引来绘制一个点,而不是每三个索引来绘制一个三角形。只是对于您通常不需要的点glDrawElements,因为您无论如何都不会重用顶点,但您仍然需要它的索引。它不会神奇地成为glDrawArrays幕后的调用。

请记住,该vertices数组包含浮点数并glDrawArrays绘制顶点,因此您必须绘制len(vertices)/3顶点。请记住,元素是(单个顶点的)索引,而不是三角形,并且顶点是 3 个浮点(或您在 中指定的内容glVertexPointer),而不仅仅是一个。

但是,如果您的triangles数组确实包含 3 个索引的元组(因此len(triangles)是三角形计数而不是索引计数),则必须绘制3*len(triangles)元素(索引)。如果您的vertices数组包含向量而不仅仅是浮点数,那么len(vertices)在 glDrawArrays 调用中绘制顶点是正确的。因此,很高兴看到他们的声明是确定的。