2011-05-25 23 views
7

Ok, todavía estoy luchando para que esto funcione. Las partes importantes de mi código son: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) 

no creo que haya nada malo aquí, por lo que he leído hasta ahora acerca de VBO. Así que ahora tengo mis buffers de vértices, normales (no utilizados aún) e índices de triángulos. Ahora para el sorteo 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 ?!)** 

Ahora funciona el glDrawArrays. Pero en el caso en que tengo que dibujar mis triángulos, no dibuja los triángulos que he definido en los TIPOS de Búfer (esto es normal por lo que he leído ya que DrawArrays no usa índices? ¿O estoy equivocado aquí?). El problema es que si trato de usar los accidentes glDrawElements todo con:

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 

Ahora estoy lo que me estoy perdiendo aquí? Por lo que puedo entender, ¿probablemente estoy pasando un puntero malo en alguna parte? Tenga en cuenta que incluso si trato de usar glDrawElements (tipo, 24, GL_UNSIGNED_INT, 0) aún se bloquea, aunque el número de triángulos definidos es mucho mayor, así que no creo que tenga nada que ver con el tamaño.

Saludos, Bogdan

EDIT: Ok por lo que ahora que he hecho algunas comprobaciones adicionales y aquí es mi situación actual: He cambiado las len (triángulos) para ADT.byteCount, no hay solución todavía. Así que revisé todos los datos que recibía y es así: la matriz de vértices contiene ~ 60000 * 3 = 180000 entradas de vértices de tipo GL_Float, al igual que la matriz normal. Como solo hay < 62535 vértices, estoy usando un corto sin signo para los triángulos. Así que tengo len (triángulos) es ~ 135000. También he cambiado los glDrawElements (GL_TRIANGLES, len (self.triangles), GL_UNSIGNED_SHORT, 0). También he verificado y todos los datos de la matriz de triángulos están entre 0 y 62534, ya que pensaba que tal vez algún índice que está fuera de rango deslizado. ¿Qué más podría estar mal aquí? ¿Cómo funciona glDrawElements (GL_POINTS, ...)? ¿También necesita algún tipo de índices?

Edit2 He actualizado el código anterior y como se ha dicho allí, ahora dibujar elementos empates mis GL_POINTS, pero no estoy seguro de dónde se pone índices? ¿O no son necesarios en caso de GL_POINTS? Y para las GL_TRIANGLES, funciona de esta manera, con glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER_ARB, self.bufferTriangles) comentado, pero nuevamente, ¿qué tipo de índices toma aquí ahora que el elemento buffer está enlazado a 0?! Y otra cosa es que glDrawElements no dibujará todos los puntos que glDrawArrays tiene. Para una mejor explatin:

glDrawArrays(GL_POINTS, 0, len(self.vertices)); 

Esto atrae a todos mis puntos correctamente:

glDrawElements(type, len(self.vertices), GL_UNSIGNED_SHORT, 0) 

Esto parece atraer visiblemente mucho menos puntos que glDrawArrays. Ahora, lo curioso es que si paso algo como 10 * len (self.vertices) para dibujar elementos dibujará todos los puntos (algunos tal vez dos o más, ¿puedo verificar esto?) Pero ¿no se supone que se cuelga?

Regards

Edit3

Algo de información más precisa sobre las matrices:

vértices - una serie de flotadores,

len (vértices) = 180000 byteCount (vértices) = 720000

triángulos - una matriz de numpy.uint16

len (triángulos) = 353439 byteCount (triángulos) = 706878 min (triángulos) = 0 max (triángulos) = 59 999, por lo que deben estar apuntando a los vértices válidos

se realiza el dibujo:

glDrawElements (GL_TRIANGLES, len (self.triangles), GL_UNSIGNED_SHORT, 0)

ACTUALIZACIÓN

Ok justo cuando me enseñó que tengo cómo debería funcionar, he tratado de saltar la VBO de los elementos y se fue apenas:

glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, ADT.voidDataPointer(self.triangles)) 

Ahora no sólo funciona esto y señala a todos mis triángulos perfectamente, pero el FPS es mejor. ¿No debería el VBO ser más rápido? Y lo que podría hacer que el enfoque anterior para trabajar, pero el siguiente a la caída:

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) 

Respuesta

4

no tengo experiencia con Python GL, pero creo que vi algo. Utiliza len(self.triangles) en la llamada al glDrawElements, así que supongo que le da la cantidad de índices en la matriz de triángulos. Pero ¿por qué entonces usando len(triangles) como tamaño en glBufferData y no ADT.arrayByteCount como en las otras llamadas. Por lo tanto, su memoria intermedia es demasiado pequeña, ya que contiene len(triangles) bytes, aunque los triángulos contienen entradas sin signo. Si los triángulos realmente contienen bytes (lo que dudo) tendrías que usar GL_UNSIGNED_BYTE en glDrawElements.

EDIT: Según sus ediciones obtuve algunas respuestas más. Por supuesto, glDrawElements(GL_POINTS, ...) también necesita índices. Simplemente usa cada índice para dibujar un punto, en lugar de cada tres índices para un triángulo. Es solo que para los puntos, a menudo no necesitas glDrawElements, ya que no reutilizas los vértices de todos modos, pero aún necesitas índices para ello. No se convierte mágicamente en una llamada glDrawArrays bajo el capó.

Y tenga en cuenta que la matriz vertices contiene flotantes y glDrawArrays dibuja vértices, por lo que debe dibujar los vértices len(vertices)/3. Recuerda que un elemento es un índice (de un solo vértice), no un triángulo y un vértice con 3 flotantes (o lo que hayas especificado en glVertexPointer), no solo uno.

Pero si la matriz triangles realmente contiene tuplas de 3 índices (y por lo tanto len(triangles) es la cuenta del triángulo y no el número de índice) que tendría que llamar la 3*len(triangles) elementos (índices).y si su matriz vertices contiene vectores y no solo flotantes, entonces dibujar los vértices len(vertices) en la llamada glDrawArrays es correcto. Por lo tanto, sería bueno ver sus declaraciones para estar seguro.

+0

Sí, utilizar glBufferDataARB (GL_ELEMENT_ARRAY_BUFFER_ARB, 4 * len (triángulos), ADT.voidDataPointer (triángulos), GL_STATIC_DRAW_ARB). Remplace "4" por el equivalente de Python de sizeof (unsigned int) – Calvin1602

+0

Ok, gracias, pero cuando lo intento así, me da un accidente allí mismo. ¿Hay algún tamaño máximo para ese buffer? Actualmente estoy teniendo la longitud de triángulos en 353439 y eso da 1413756 para el recuento de bytes. ¿Se supone que debe causar un bloqueo? – Bogdan

+0

Ignora mi último comentario. Lo miraré más de cerca y regresaré. – Bogdan

0

En mi experiencia, el contenedor Python OpenGL es muy defectuoso una vez que comienzas a utilizar algunas de las llamadas OpenGL más avanzadas. Muchas llamadas parecen causar un bloqueo sin motivo y algunas veces funcionan si las reemplaza con una secuencia equivalente de llamadas diferentes ... Cambié los lenguajes de programación para OpenGL en lugar de tener que lidiar con estos problemas.

+0

Sí, he notado que todavía hay algunos aspectos defectuosos, especialmente cuando uso VBO, pero realmente no tengo otra opción aquí, excepto ir a la C estándar e integrar después, que dejaré como último recurso. – Bogdan

0

La razón por la

glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, ADT.voidDataPointer(self.triangles)) 

obras y

glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, 0) 

no es porque PyOpenGL espera None como puntero nulo, en vez de 0. Tenga cuidado al usar OpenGL ejemplos escritos en C, porque usan (void*)0 como el puntero void, que no es interpretado correctamente como un puntero por PyOpenGL, que en cambio trata 0 como un valor no nulo.

su lugar, debe utilizar

glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, None) 

(Ver también https://stackoverflow.com/a/14365737/478380)

Cuestiones relacionadas