2010-10-02 27 views
11

En mi aplicación dibujo un montón de cubos a través de OpenGL ES Api. Todos los cubos tienen las mismas dimensiones, solo que están ubicados en diferentes coordenadas en el espacio. Puedo pensar en dos formas de dibujarlos, pero no estoy seguro de cuál es el más eficiente. No soy un experto en OpenGL, así que decidí preguntar aquí.Manera eficiente de dibujar en OpenGL ES

Método 1, que es lo que uso ahora: dado que todos los cubos son de dimensiones idénticas, calculo el buffer de vértice, el buffer de índice, el buffer normal y el buffer de color solo una vez. Durante una actualización de la escena, repaso todos los cubos, hago bufferData() para el mismo conjunto de búferes y luego dibujo la malla triangular del cubo usando la llamada a drawElements(). Como cada cubo está en una posición diferente, traduzco el mvMatrix antes de dibujar. bufferData() y drawElements() se ejecuta para cada cubo. En este método, probablemente guarde mucha memoria, al no calcular los búferes todo el tiempo. Pero estoy haciendo muchas llamadas a drawElements().

El método 2 sería: Tratar todos los cubos como un conjunto de polígonos repartidos por toda la escena. Calcule vértices, índices, colores, búferes normales para cada polígono (en realidad, triángulos dentro de los polígonos) y empújelos a la memoria de la tarjeta gráfica en una sola llamada a bufferData(). Luego, dibuja con una sola llamada a drawElements(). La ventaja de este enfoque es que hago solo una llamada bindBuffer y drawElements. La desventaja es que uso mucha memoria para crear los buffers.

Mi experiencia con OpenGL es lo suficientemente limitada como para no saber cuál de los métodos anteriores es mejor desde el punto de vista del rendimiento.

Lo estoy usando en una aplicación WebGL, pero es una pregunta genérica de OpenGL ES.

+0

No sé la respuesta, pero después de 2 días sin respuestas yo suspiro Pero su mejor enfoque es intentar implementar el método 2 y ejecutar algunas pruebas de rendimiento. – LarsH

+0

Sí, creo que también. Publicaré lo que encuentre. – Jayesh

Respuesta

14

Implementé el método 2 y gana por un deslizamiento de tierra. La supuesta desventaja de la gran cantidad de memoria parecía ser solo mi imaginación. De hecho, el recolector de basura fue invocado en el método 2 solo una vez, mientras que fue invocado por 4-5 veces en el método 1.

Su escenario OpenGL puede ser diferente al mío, pero si llegó aquí en busca de consejos de rendimiento, la lección de esta pregunta es: Identifique las partes de su escena que no cambian con frecuencia. No importa cuán grandes sean, colóquelos en un solo buffer set (VBO) y cargúelos a la memoria gráfica un mínimo de veces. Así es como deben ser usadas las VBO. El ancho de banda de memoria entre el cliente (es decir, su aplicación) y la tarjeta gráfica es precioso y no desea consumirlo a menudo sin motivo.

Lea la sección "Objetos de búfer vértice" en el cap. 6 de la "Guía de programación de OpenGL ES 2.0" para comprender cómo se supone que deben usarse. http://opengles-book.com/

+0

Como regla general en WebGL: Menos llamadas de extracción === Más rápido. Si tus cubos son estáticos o raramente se mueven (como, por ejemplo, un paisaje de Minecraft) entonces sí, un único buffer estático es el camino a seguir. No me preocuparía demasiado por el uso de memoria involucrado. Los cubos son bastante livianos. – Toji

+0

¿Cómo enviaste a tu GPU todos tus datos de cubos para que puedas dibujar en una sola llamada drawElements? – AlvinfromDiaspar

-1

propongo siguiente enfoque:

En carga:

  1. Generar coordenadas memoria intermedia (para un cubo) y cargarlo en VBO (gl.glGenBuffers, gl.glBindBuffer)

Por sorteo:

  1. tampón de enlace (gl.glBindBuffer)

  2. dibujar cada celda (circular)

    2,1. Mueva la posición actual al centro del cubo actual (gl.glTranslatef(position.x, position.y, position.z)

    2.2.Dibujar cubo actual (gl.glDrawArrays)

    2.3. Mover la posición hacia atrás (gl.glTranslatef(-position.x, -position.y, -position.z))

+0

Para empezar, no necesita repetir el "gl". Es solo gl.drawArrays, por ejemplo. Dos, OpenGL ES no tiene glTranslate ni ninguna de las otras funciones de la matriz. Tres, básicamente describiste los carteles "Método 1", que en realidad es el más lento de los dos métodos. (Pero ya sea o no, el mejor método depende realmente de las necesidades del programa) – Toji

5

Sé que esta pregunta ya está contestada, pero creo que vale la pena señalar la presentación de Google IO acerca de la optimización de WebGL:

http://www.youtube.com/watch?v=rfQ8rKGTVlg

que cubren, esencialmente , este mismo problema (mucho de formas idénticas con diferentes colores/posiciones) y habla de algunas formas geniales de optimizar una escena (¡y la suya también es dinámica!)

+0

"Dinámico" es un poco exagerado: las posiciones de los objetos están predeterminadas ('x = sin (tiempo)' etc.) para que todo pueda calcularse en la GPU. No hay gráfico de escena y las mallas nunca cambian. Aunque fue una charla útil. – Timmmm

Cuestiones relacionadas