2011-03-23 69 views
11

Me encontré con un código OpenGL de muestra que porté a OpenGL ES 2.0 (no había mucho que hacer en realidad), pero no puedo evitar preguntarme para qué sirve la función glBufferData. La fuente original es así:¿Qué es 'glBufferData' en OpenGL ES?

glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 2 * 6, quad, GL_STATIC_DRAW); 
glEnableVertexAttribArray(0); 
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, (void *) 0); 

Pero puede simplificar con éxito como:

glEnableVertexAttribArray(0); 
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, quad); 

Es decir, puedo omitir la función glBufferData sólo mediante el uso de un puntero válido para el conjunto de quad en glVertexAttribPointer .

Entonces, ¿alguien podría explicar para qué sirve la función glBufferData? Por lo que estoy haciendo, parece ser redundante, pero debe ser por mi falta de conocimiento serio de la API. De hecho, intenté leer los documentos al khronos.org, pero esto no me ayudó a entender su uso.

+1

Además de lo que se ha dicho en las respuestas, creo que el nombre del concepto que está buscando aquí es un Objeto de búfer vértice (VBO): http://www.opengl.org/wiki/Vertex_Buffer_Object –

Respuesta

16

Si está reutilizando los mismos datos en varios marcos, usar glBufferData como parte de su configuración/inicialización transferirá datos de la CPU a la GPU solo una vez. Mientras que glVertexAttribPointer se debe llamar a cada fotograma, por lo que usarlo para transferir datos da como resultado el uso de mucho más ancho de banda de bus.

Si está actualizando la matriz de atributos en cada cuadro, no hay mucha ventaja en un sentido u otro.

+0

Aha ! Estoy trabajando en algo así como una API de procesamiento de imágenes para que los vértices no cambien (sin mencionar que solo hay seis de ellos). ¡Muchas gracias! ¡Altamente apreciado! –

+4

El problema no es la llamada a glVertexAttribPointer (de hecho, lo llama con offset 0, sin embargo). La idea clave es que usar glBufferData uno crea una copia de trabajo de los datos en "memoria rápida" (es decir, la RAM a la que tiene acceso directo la GPU), en lugar de tener que transferir los atributos de vértices entre dominios de memoria (es decir, CPU → GPU) cada vez que se llama glDrawElements o glDrawArrays. También significa que puede liberar la memoria con los datos en su programa después de copiar a la memoria "rápida". – datenwolf

+0

@datenwolf, gracias! –

5

Esto es extraño. Si omitir glBufferData funciona de la misma manera, entonces no se enlaza ningún buffer, o hay una llamada glBufferData anteriormente en el programa. Estaba confundido si tal vez OpenGL ES tenía un "comportamiento especial" significativamente diferente, pero he comprobado las especificaciones, y por lo que puedo ver, funciona exactamente igual que en OpenGL "normal".

El dibujo (a través de glDraw [Elementos | Matrices]) se leerá desde el puntero proporcionado previamente por glVertexAttribPointer si no está enlazado buffer (memoria del cliente). Leerá del búfer si está vinculado, tratando el argumento del puntero glVertexAttribPointer como un desplazamiento en el búfer. El dibujo de un búfer que no se ha inicializado obviamente no está definido.

¿Qué hace glBufferData?

glBufferData hace al menos dos cosas, y opcionalmente una tercera. Asigna el almacenamiento intermedio y establece el uso del almacenamiento intermedio. Opcionalmente, si el argumento del puntero no es nulo, llenará el búfer con los datos apuntados. El glBufferSubData similar difiere en la medida en que solo actualiza (posiblemente un subrango de) datos, no asigna almacenamiento ni nada más.