好的,所以我仍然在努力让这个工作起来。我的代码的重要部分是:
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(三角形)更改为ADT.byteCount,还没有解决方案。所以我检查了我得到的所有数据,它是这样的:顶点数组包含GL_Float类型的~60000 * 3 = 180000个顶点条目,normals数组也是如此。因为只有< 62535个顶点我正在使用三角形的无符号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会是什么样的索引呢?另一件事是glDrawElements不会绘制glDrawArrays所做的所有点。为了更好地解释:
glDrawArrays( GL_POINTS, 0, len(self.vertices) );
这正确地得出了我的所有观点:
glDrawElements(type, len(self.vertices), GL_UNSIGNED_SHORT, 0)
这似乎明显比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)
更新
好的,当我考虑到我应该如何工作时,我试图跳过元素的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)
答案 0 :(得分:4)
我没有Python GL的经验,但我想我发现了一些东西。你在len(self.triangles)
的调用中使用glDrawElements
,所以我想这会给你三角形数组中的索引数。但是为什么然后在len(triangles)
中使用glBufferData
作为其他调用中的ADT.arrayByteCount
而不是len(triangles)
。所以你的缓冲区太小了,因为它包含GL_UNSIGNED_BYTE
个字节,尽管三角形包含无符号整数。如果三角形确实包含字节(我怀疑),则必须在glDrawElements
中使用glDrawElements(GL_POINTS, ...)
。
编辑:根据您的修改,我得到了更多答案。当然glDrawElements
也需要索引。它只是使用每个索引绘制一个点,而不是三角形的每三个索引。对于您通常不需要glDrawArrays
的点而言,因为您不会重复使用顶点,但您仍然需要索引。它并没有神奇地成为引擎盖下的vertices
电话。
请记住,glDrawArrays
数组包含浮点数,len(vertices)/3
绘制顶点,因此您必须绘制glVertexPointer
个顶点。 Juts记住,元素是一个索引(单个顶点),而不是三角形,顶点是3个浮点数(或者你在triangles
中指定的那个),而不仅仅是一个。
但是如果你的len(triangles)
数组确实包含3个索引的元组(因此3*len(triangles)
是三角形计数而不是索引计数),则必须绘制vertices
个元素(索引) 。如果你的len(vertices)
数组包含向量而不仅仅是浮点数,那么在glDrawArrays调用中绘制{{1}}个顶点是正确的。因此,很高兴看到他们的声明是肯定的。
答案 1 :(得分:0)
根据我的经验,一旦你开始使用一些更高级的OpenGL调用,Python OpenGL包装器就会非常错误。许多调用似乎无缘无故地导致崩溃,如果用相同的不同调用序列替换它们,有时会工作......我为OpenGL切换了编程语言而不必处理这些问题。
答案 2 :(得分:0)
原因
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)