2012-05-29 12 views
9

Estoy tratando de dibujar un montón de líneas en Android usando OpenGL ES 2.0 y necesito saber la mejor manera de hacerlo.Vértices dinámicos rápidos en OpenGL ES 2.0 en Android

Ahora hice una clase llamada LineEngine que crea un FloatBuffer de todos los vértices para dibujar y luego dibuja todas las líneas a la vez. El problema es que aparentemente FloatBuffer.put() es muy lento y está consumiendo tiempo de CPU como loco.

Aquí es mi clase

public class LineEngine { 
    private static final float[] IDENTIY = new float[16]; 
    private FloatBuffer mLinePoints; 
    private FloatBuffer mLineColors; 
    private int mCount; 

    public LineEngine(int maxLines) { 
     Matrix.setIdentityM(IDENTIY, 0); 

     ByteBuffer byteBuf = ByteBuffer.allocateDirect(maxLines * 2 * 4 * 4); 
     byteBuf.order(ByteOrder.nativeOrder()); 
     mLinePoints = byteBuf.asFloatBuffer(); 

     byteBuf = ByteBuffer.allocateDirect(maxLines * 2 * 4 * 4); 
     byteBuf.order(ByteOrder.nativeOrder()); 
     mLineColors = byteBuf.asFloatBuffer(); 

     reset(); 
    } 

    public void addLine(float[] position, float[] color){ 
     mLinePoints.put(position, 0, 8); //These lines 
     mLineColors.put(color, 0, 4); // are taking 
     mLineColors.put(color, 0, 4); // the longest! 
     mCount++; 
    } 

    public void reset(){ 
     mLinePoints.position(0); 
     mLineColors.position(0); 
     mCount = 0; 
    } 

    public void draw(){ 
     mLinePoints.position(0); 
     mLineColors.position(0); 
     GraphicsEngine.setMMatrix(IDENTIY); 
     GraphicsEngine.setColors(mLineColors); 
     GraphicsEngine.setVertices4d(mLinePoints); 
     GraphicsEngine.disableTexture(); 
     GLES20.glDrawArrays(GLES20.GL_LINES, 0, mCount * 2); 
     GraphicsEngine.disableColors(); 
     reset(); 
    } 
} 

¿Hay una mejor manera de lotes todas estas líneas juntas?

+0

¿Qué versión de Android es el dispositivo ejecutándose? Ha habido [problemas con FloatBuffer] (http://www.badlogicgames.com/wordpress/?p=899). GLES20 exige API nivel 8, por lo que es al menos Froyo. ¿Puedes probar en un dispositivo que ejecute Honeycomb? –

+0

Lo estoy ejecutando en ICS en mi Galaxy Nexus. Comprobaré que en realidad lleva mucho tiempo. – EmbMicro

+0

Acabo de probar el procesamiento por lotes de las líneas y no el procesamiento por lotes en mi Galaxy Nexus y EVO 4G. El EVO aumentó el FPS de 28.8 a 30 y el Galaxy Nexus se mantuvo igual en 58.4. Sin embargo, en el perfilador de métodos muestra que la función de dibujo (que incluye FloatBuffer.put y la llamada real de OpenGL) tomó mucho más tiempo. Pasó del 31.5% al ​​53.1% del tiempo de CPU. ¿Es esto solo el perfilador jugando con cosas? – EmbMicro

Respuesta

1

Lo que estás tratando de hacer se llama SpriteBatching. Si desea que su programa sea robusto en OpenGL, debe verificar lo siguiente (una lista de lo que hace que su programa sea lento):

-Cambio a muchos estados abiertos de ES cada cuadro.

-Abrible // Dissable (texturas, etc.) una y otra vez. Una vez que habilites algo, no tienes que volver a hacerlo, se aplicará automáticamente su marco.

-Utilizando muchos recursos en lugar de spriteSheets. Sí, eso tiene un gran impacto en el rendimiento. Por ejemplo, si tiene 10 imágenes, debe cargar para cada imagen una textura diferente y que sea LENTA. Una mejor forma de hacerlo es crear una hoja de sprites (puedes consultar en Google de forma gratuita los creadores de spritesheet).

-Sus imágenes son de alta calidad. ¡Sí! verifica tu resolución y extensión de archivo. Prefiere los archivos .png.

-Care para el error del buffer flotador api 8 (en su lugar, tiene que usar el búfer int para corregir el error).

-Usando contenedores de Java. Este es el mayor escollo, si utiliza la concatenación de cadenas (que no es un contenedor pero devuelve una cadena nueva cada vez) o una Lista o cualquier otro contenedor que REGRESE UNA INSTANCIA DE NUEVA CLASE, su programa será lento debido a la recolección de basura. Para el manejo de entradas, le sugiero que busque un teqnique llamado Pool Class. Su uso es reciclar objetos en lugar de crear otros nuevos. El recolector de basura es el gran enemigo, trata de hacerlo feliz y evita cualquier técnica de programación que pueda llamarlo.

-Nunca carga cosas sobre la marcha, en su lugar crea una clase de cargador y carga todos los recursos necesarios al comienzo de la aplicación.

Si implementa esta lista, es probable que su programa sea robusto.

Una última adición. ¿Qué es un dosificador de sprites? Un spriteBatcher es una clase que usa una sola textura para representar múltiples objetos. Creará automáticamente vértices, índices, colores, u - v coords y los renderizará como un lote. Este patrón ahorrará energía de la GPU y la potencia de la CPU. De su código publicado no puedo estar seguro de qué causa que disminuya la CPU, pero según mi experiencia se debe a una (o más) cosas de la lista que mencioné anteriormente. Revisa la lista, síguela, busca google para spriteBatching y estoy seguro de que tu programa se ejecutará rápidamente. Espero que ayudé!

Editar: Creo que encontré lo que hace que su programa se ralentice, ¡no da la vuelta al tipo de búfer! Usted acaba de restablecer la posición. Simplemente agrega agrega agrega más objetos y causas sobrecarga de buffer. En el método de reinicio simplemente voltea el buffer. mLineColors.flip mLinePaints.flip hará el trabajo. Asegúrese de llamarlos cada cuadro si envía nuevos verices en cada cuadro.

+0

Hace mucho tiempo que dejé de trabajar en este código, pero tu respuesta tiene mucha información buena y no me sorprendería si voltear el buffer mejorara mucho. ¿No habrá desbordamiento ya que los puntos anteriores se sobrescribirán? ¿O los almacenamientos intermedios no funcionan de esa manera? – EmbMicro

+0

Hola, lamento que me haya llevado tanto tiempo responder que estaba lejos. Así que primero lo primero, ¡feliz Navidad! A su pregunta ahora, un buffer es un array que contiene temporalmente una información masiva que necesita procesarse en lugar de procesar la misma información, uno por uno, hasta el final. Cuando giras un buffer, cambia el tamaño automáticamente para que no tengas que preocuparte por sobrecargarlo (excepto si das un tamaño muy grande). La sobrecarga significa que si el buffer tiene una capacidad de 10 int, estará bien siempre y cuando no proporcione 11. Si da 11, entonces tendrá un desbordamiento de buffer. – KostasRim

+0

Sobrescribir una ubicación de memoria no está sobrecargando. Solo recuerda que cambias el valor de la memoria, no le pides a tu programa que reserve la misma memoria más los puntos nuevos. Acabas de renderizar los puntos del marco de las corrientes (¡los puntos antiguos ya no existen!). Espero haber ayudado, tener un feliz año nuevo :)! – KostasRim

0

FloatBuffer.put (float []) con una matriz de flotación relativamente grande debería ser considerablemente más rápida. Las llamadas de posición única (flotante) tienen mucha sobrecarga.

0

Simplemente elija una función nativa muy simple que se llamará desde su clase. Puede poner float[] en OpenGL directamente, sin necesidad de matar el tiempo de CPU con una interfaz tonta de búfer.

Cuestiones relacionadas