Gran búfer de vértices frente a múltiples llamadas de sorteo

14

Recién estoy comenzando con OpenGL, y estoy intentando usarlo para crear un juego 2D. En este juego, tengo una cuadrícula hexagonal compuesta de una gran variedad de hexágonos de diferentes colores. Como programador novato de OpenGL, veo dos formas de dibujar esta cuadrícula:

  1. Usando un búfer de vértices con los datos para un solo hexágono, luego usando un valor de compensación uniforme e iterando en la CPU para dibujar el mismo programa muchas veces hasta que tenga una cuadrícula.
  2. Crear un búfer de vértice precalculado muy grande y singular que dibuja todos los hexágonos en una sola llamada.

¿Cuál es el método más eficiente? ¿Hay una mejor manera de hacer esto?

Alexis King
fuente
Su búfer de vértice precalculado solo necesita extenderse más allá de la pantalla en un hexágono, luego puede fingirlo desplazándose suavemente hasta obtener un hexágono completo y luego "deformarse" hacia atrás, en cuanto a los colores en ese escenario, puede mantener un Textura 2D en la GPU, léala en el sombreador de vértices e interpola plana en el sombreador de fragmentos.
MickLH
Los pases generalmente se refieren a una situación en la que una operación de representación depende de los resultados de una operación anterior. Lo que está preguntando en esta pregunta en realidad está relacionado con la reducción del número de llamadas de extracción dentro de un solo pase. Sé que suena pedante, pero es muy importante entender la diferencia; de lo contrario, los algoritmos de múltiples pasadas no tendrán mucho sentido;)
Andon M. Coleman
@ AndonM.Coleman Hmm, gracias, claramente no estoy familiarizado con la terminología gráfica. Entonces, en este caso, ¿cómo lo describiría? ¿Llamadas de sombreador / programa múltiples?
Alexis King
Puede saber de inmediato que se trata de un algoritmo de paso único porque no hay dependencia del orden; puedes dibujar estos hexágonos en cualquier orden y aún así obtener el mismo resultado. Puede tomar múltiples llamadas de extracción para proporcionar a OpenGL los datos necesarios para representarlas, pero OpenGL es efectivamente libre de dibujarlas todas en paralelo ya que no hay dependencias. Si se tratara de múltiples pasadas , entonces el hexágono B podría requerir el resultado del hexágono A antes de que se pudiera dibujar, o podría necesitar dibujar el mismo hexágono varias veces y combinar el resultado.
Andon M. Coleman

Respuestas:

9

De hecho, hay algunas maneras de hacer una cuadrícula de este tipo.

La forma más eficiente sería la instancia. De esta manera, crea su hexágono solo una vez en un VBO y lo renderiza cien, mil o un millón de veces. Puede hacerlo manualmente usando sombreadores con uniformes como dijo en el punto 1, pero también tiene una funcionalidad OpenGL incorporada. Para eso, eche un vistazo a glDrawElementsInstanced .

Tenga en cuenta que la creación de instancias solo es más rápida que otros métodos si dibuja más de una cierta cantidad de objetos instanciados. Por ejemplo, dibujar 300 puede ser más rápido usando 1 VBO grande, pero dibujar 2 millones puede ser más rápido si usa renderizado instanciado.

Si utiliza la representación instanciada, puede enviar datos por objeto utilizando divisores de atributos . En su caso, desearía enviar la posición y el color.

Un buen tutorial sobre renderizado instanciado: haga clic

Realmente, la mejor manera es probar ambos métodos y verificar la cantidad de milisegundos que se necesitan para dibujar 1 fotograma. De esta manera también aprendes en ambos sentidos, lo que siempre es bueno.

También tenga en cuenta que el renderizado instanciado es una funcionalidad moderna de OpenGL, y que tendrá que usar sombreadores para usarlo. Pero siempre es mejor aprenderlo de la manera correcta desde el principio.

Basaa
fuente
2
La instancia no es necesariamente la más eficiente; En muchas implementaciones de las que he visto perfiles, el soporte de instancias se agregó para la conformidad, pero más lento que el dibujo individual de muchos objetos (de hecho, es probable que solo haya un bucle mal implementado en el controlador que hace lo mismo). Es una opción, y una buena, pero se debe tener cuidado de perfilar y probar en el sistema operativo / hardware de destino antes de hacer suposiciones sobre "más eficiente".
Sean Middleditch
Convenido. He visto diferentes actuaciones en Windows / Linux y Ati / nVidia, por ejemplo. Gracias por la adición.
Basaa
1
De hecho. Si dibuja múltiples mallas combinadas dentro de un solo vbo (que comparten el mismo espacio). De ninguna manera la instancia podría ser más rápida. El problema con las instancias es: los vértices no son instancias cruzadas calculadas en paralelo. Solo elimina el gpu / cpu / gpu sync / drawcall. Por lo tanto, es más rápido dibujar un búfer de vértices que contenga 1000 esferas que dibujar 1000 esferas con instancias de hardware. (sin sacrificio de arranque / optimización de detalle de distancia de objeto involucrada)
Jeroen van Langen
3

El método 1 es más simple de codificar y estará bien siempre que no tenga demasiados hexágonos a la vista a la vez. Es posible que desee seguir con esto ya que es nuevo en OpenGL, para evitar poner demasiada complejidad en su plato a la vez.

Si hay una gran cantidad de hexágonos (como varios cientos o más de mil) a la vista, sería necesario un método de sobrecarga más baja para evitar la sobrecarga de la CPU de hacer tantos sorteos individuales. El método 2 funcionaría para esto, o incluso mejor, usar instancias. Esperaría que la instancia sea más rápida que el método 2, o ciertamente no peor, ya que solo tiene que actualizar un búfer de datos por instancia en lugar de un búfer (mucho más grande) de datos de vértice para todas las instancias.

Nathan Reed
fuente