glDrawArrays vs glDrawElements
Ok, então eu ainda estou lutando para fazer isso funcionar. As partes importantes do meu código são:
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)
Acho que não há nada errado aqui com o que li até agora sobre os VBO's. Então agora eu tenho meu buffer de índices de vértice, normais (ainda não usado ainda) e triângulo. Agora, para o sorteio real:
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 ?!)**
Agora o glDrawArrays funciona. Mas no caso em que eu tenho que desenhar meus triângulos, ele não desenha os triângulos que defini em bufferTriangles (isso é normal pelo que li desde que drawArrays não usa índices? Ou estou errado aqui?). O problema é que, se eu tentar usar o glDrawElements, tudo trava com:
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
Agora, o que estou perdendo aqui? Pelo que entendi, provavelmente estou passando um ponteiro ruim em algum lugar? Observe que, mesmo se eu tentar usar glDrawElements (type, 24, GL_UNSIGNED_INT, 0), ele ainda trava, mesmo que o número de triângulos definidos seja bem maior, então eu não acho que isso tenha a ver com o tamanho.
Regards, Bogdan
EDITAR Ok, agora fiz algumas verificações extras e aqui está minha situação atual: alterei o len (triângulos) para ADT.byteCount, ainda não há solução. Portanto, verifiquei todos os dados que estava obtendo e é assim: A matriz de vértices contém ~ 60000 * 3 = 180000 entradas de vértices do tipo GL_Float, assim como a matriz de normais. Como existem apenas <62535 vértices, estou usando abreviação não assinada para os triângulos. Então, eu tenho len (triângulos) é ~ 135000. Também alterei os glDrawElements (GL_TRIANGLES, len (self.triangles), GL_UNSIGNED_SHORT, 0). Também verifiquei e todos os dados da matriz de triângulos estão entre 0 e 62534, pois eu pensava que talvez algum índice fora do intervalo caiu. O que mais poderia estar errado aqui? Ah, e como funciona o glDrawElements (GL_POINTS, ...)? Também precisa de algum tipo de índice?
EDIT2 Atualizei o código acima e, como já foi dito, agora desenhar elementos desenha meus GL_POINTS, mas não tenho certeza de onde ele obtém índices? Ou eles não são necessários no caso de GL_POINTS? E para o GL_TRIANGLES, ele funciona assim, com glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER_ARB, self.bufferTriangles) comentado, mas novamente que tipo de índices leva aqui agora que o buffer do elemento está ligado a 0 ?! E outra coisa é que o glDrawElements não desenha todos os pontos que o glDrawArrays faz. Para melhor explicar:
glDrawArrays( GL_POINTS, 0, len(self.vertices) );
Este desenha todos os meus pontos corretamente:
glDrawElements(type, len(self.vertices), GL_UNSIGNED_SHORT, 0)
Isto parece atrair muito menos pontos do que o glDrawArrays. Agora, o engraçado é que, se eu passar como tamanho algo como 10 * len (self.vertices) para desenhar elementos, ele desenhará todos os pontos (alguns talvez duas ou mais vezes; posso verificar isso?), Mas não suporia falhar?
Saudaçõe
EDIT3
Algumas informações mais precisas sobre as matrizes:
vertices - uma matriz de carros alegóricos,
len (vértices) = 180000 byteCount (vértices) = 720000
triangles - uma matriz de numpy.uint16
len (triângulos) = 353439 byteCount (triângulos) = 706878 min (triângulos) = 0 máx (triângulos) = 59999, portanto, eles devem estar apontando para vértices válidos
O desenho está feito:
glDrawElements (GL_TRIANGLES, len (self.triangles), GL_UNSIGNED_SHORT, 0)
ATUALIZA
Ok, quando pensei em entender como isso deveria funcionar, tentei pular o VBO para os elementos e fui apenas:
glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, ADT.voidDataPointer(self.triangles))
Agora não só isso funciona e desenha todos os meus triângulos perfeitamente, mas o FPS é melhor. O VBO não deveria ser mais rápido? E o que poderia causar o funcionamento da abordagem acima, mas o seguinte travava:
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)