Estoy desarrollando un juego 2D basado en sprites para plataformas móviles y estoy usando OpenGL (bueno, en realidad Irrlicht) para renderizar gráficos. Primero implementé el renderizado de sprites de una manera simple: cada objeto del juego se representa como un quad con su propia llamada de sorteo de GPU, lo que significa que si tuviera 200 objetos de juego, haría 200 llamadas de sorteo por cuadro. Por supuesto, esta fue una mala elección y mi juego estaba completamente vinculado a la CPU porque hay una pequeña sobrecarga de CPU en cada llamada de sorteo de GPU. GPU permaneció inactivo la mayor parte del tiempo.
Ahora, pensé que podría mejorar el rendimiento al recopilar objetos en grandes lotes y renderizar estos lotes con solo unas pocas llamadas de sorteo. Implementé el procesamiento por lotes (para que cada objeto del juego que comparte la misma textura se procese en el mismo lote) y pensé que mis problemas se habían ido ... solo para descubrir que mi velocidad de fotogramas era incluso más baja que antes.
¿Por qué? Bueno, tengo 200 (o más) objetos de juego, y se actualizan 60 veces por segundo. Cada cuadro que tengo que volver a calcular la nueva posición (traslación y rotación) para vértices en la CPU (la GPU en plataformas móviles no admite la creación de instancias, por lo que no puedo hacerlo allí), y hacer este cálculo 48000 por segundo (200 * 60 * 4 desde cada sprite tiene 4 vértices) simplemente parece ser demasiado lento.
¿Qué podría hacer para mejorar el rendimiento? Todos los objetos del juego se mueven / giran (casi) cada cuadro, así que realmente tengo que volver a calcular las posiciones de los vértices. La única optimización que se me ocurre es una tabla de búsqueda de rotaciones para no tener que calcularlas. ¿Ayudarían los sprites de punto? ¿Algún truco desagradable? ¿Algo más?
Gracias.
fuente
Recomendaría tener un VBO, con cada vértice que contiene la posición / rotación de cada objeto renderizado y el procesamiento por lotes basado en la textura como lo está haciendo. No estoy muy familiarizado con ogl ES, por lo que no estoy seguro de qué versión de glsl admite, pero es posible que incluso pueda agrupar en función de un conjunto de texturas y almacenar cuál de las 4 texturas que está pasando estarías usando dentro del vértice. Los sprites de punto definitivamente mejorarían su rendimiento porque reducirían drásticamente la cantidad de datos que está enviando, y el procesamiento por lotes nunca debería disminuir el rendimiento si lo hace correctamente. Además, podría mejorar un poco el rendimiento calculando la rotación en el sombreador y solo pasando un valor int / float en los parámetros o dentro del vértice mismo. (los parámetros serían más rápidos,
fuente
Menciona plataformas móviles que no tienen instancias. Pero, todavía tienes sombreadores de vértices, ¿no?
En ese caso, aún puede hacer pseudo instancing, que también es muy rápido. Haga un VBO (GL_STATIC_DRAW) con los puntos de esquina (en relación con el punto central del sprite, por ejemplo, -1 / -1, 1 / -1, 1/1, -1/1) y las coordenadas de textura que necesite, en él .
Luego establezca uno de los atributos de vértice genéricos para cada llamada de dibujo al punto central del sprite, y dibuje los dos triángulos con el búfer enlazado. Dentro del sombreador de vértices, lea el atributo de vértice genérico y agregue las coordenadas del vértice.
Eso te ahorrará el bloqueo en una transferencia de datos para cada sprite y debería ser mucho más rápido. El número real de llamadas de extracción no es tan terriblemente importante, lo es el bloqueo / bloqueo en el medio.
fuente
El problema reside en la cantidad de datos que está enviando a la GPU cada fotograma. Simplemente cree un VBO para cada lote y complételo una vez, luego aplique las matrices de transformación correspondientes (a través de glMultMatrix o un sombreador si está utilizando ES 2.0) al dibujar los lotes.
fuente