optimization de la salida de textura 2D y framerate de openGL ES 2.0 2D

Tenía la esperanza de que alguien me ayude a progresar en algunas testings de textura que estoy haciendo en OpenGL ES 2.0 y iPhone 4.

Tengo una matriz que contiene objects sprite. el bucle de renderización recorre todos los sprites por textura, y recupera todas sus coorderadas de textura y coorderadas de vértice. Añade esos a una matriz entrelazada gigante, utilizando vértices e índices degenerados, y los envía a la GPU (estoy insertando el código en la parte inferior). Todo esto se hace por textura, así que estoy uniendo la textura una vez y luego creando mi matriz de intercalación y luego dibujándola. Todo funciona muy bien y los resultados en la pantalla son exactamente lo que deberían ser.

Por lo tanto, mi testing comparativa se realiza agregando 25 sprites nuevos por toque en diferentes opacidades y cambiando sus vértices en la actualización para que reboten en la pantalla mientras se gira y se ejecuta OpenGL ES Analyzer en la aplicación.

Aquí es donde espero ayuda … Puedo llegar a alnetworkingedor de 275 sprites 32×32 con diferentes opacidades rebotando alnetworkingedor de la pantalla a 60 fps. En 400, estoy a 40 fps. Cuando ejecuto OpenGL ES Performance Detective me dice …

La renderización de la aplicación está limitada por la ttwig de triángulo: el process de convertir triangularjs en píxeles. El área total en píxeles de todos los triangularjs que está representando es demasiado grande. Para dibujar a una velocidad de cuadro más rápida, simplifique su escena networkinguciendo la cantidad de triangularjs, su tamaño o ambos.

La cosa es que acabo de hacer una testing en cocos2D usando CCSpriteBatchNode usando la misma textura y creado 800 sprites transparentes y el framerate es un 60fps fácil.

Aquí hay un código que puede ser pertinente …

Shader.vsh (las matrices se configuran una vez al principio)

void main() { gl_Position = projectionMatrix * modelViewMatrix * position; texCoordOut = texCoordIn; colorOut = colorIn; } 

Shader.fsh (colorOut se usa para calcular la opacidad)

 void main() { lowp vec4 fColor = texture2D(texture, texCoordOut); gl_FragColor = vec4(fColor.xyz, fColor.w * colorOut.a); } 

Configuración de VBO

  glGenBuffers(1, &_vertexBuf); glGenBuffers(1, &_indiciesBuf); glGenVertexArraysOES(1, &_vertexArray); glBindVertexArrayOES(_vertexArray); glBindBuffer(GL_ARRAY_BUFFER, _vertexBuf); glBufferData(GL_ARRAY_BUFFER, sizeof(TDSEVertex)*12000, &vertices[0].x, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(GLKVertexAttribPosition); glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TDSEVertex), BUFFER_OFFSET(0)); glEnableVertexAttribArray(GLKVertexAttribTexCoord0); glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TDSEVertex), BUFFER_OFFSET(8)); glEnableVertexAttribArray(GLKVertexAttribColor); glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(TDSEVertex), BUFFER_OFFSET(16)); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indiciesBuf); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ushort)*12000, indicies, GL_STATIC_DRAW); glBindVertexArrayOES(0); 

Código de Actualización

  /* Here it cycles through all the sprites, gets their vert info (includes coords, texture coords, and color) and adds them to this giant array The array is of... typedef struct{ float x, y; float tx, ty; float r, g, b, a; }TDSEVertex; */ glBindBuffer(GL_ARRAY_BUFFER, _vertexBuf); //glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices[0])*(start), sizeof(TDSEVertex)*(indicesCount), &vertices[start]); glBufferData(GL_ARRAY_BUFFER, sizeof(TDSEVertex)*indicesCount, &vertices[start].x, GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); 

Código de procesamiento

  GLKTextureInfo* textureInfo = [[TDSETextureManager shanetworkingTextureManager].textures objectForKey:textureName]; glBindTexture(GL_TEXTURE_2D, textureInfo.name); glBindVertexArrayOES(_vertexArray); glDrawElements(GL_TRIANGLE_STRIP, indicesCount, GL_UNSIGNED_SHORT, BUFFER_OFFSET(start)); glBindVertexArrayOES(0); 

Aquí está una captura de pantalla de 400 sprites (800 triangularjs + 800 triangularjs degenerados) para dar una idea de la opacidad de las capas a medida que las texturas se mueven … Nuevamente debo tener en count que se crea una VBO y se envía por textura, solo dos veces por cuadro (ya que solo hay dos texturas).

captura de pantalla que muestra capas de sprites

Lo siento si esto es abrumador pero es mi primera publicación aquí y quería ser exhaustiva. Cualquier ayuda sería muy apreciada.

PS, sé que podría usar Cocos2D en lugar de escribir todo desde cero, pero ¿dónde está la diversión (y el aprendizaje) en eso ?!

ACTUALIZACIÓN # 1 Cuando cambio mi fragment shader solo para ser

  gl_FragColor = texture2D(texture, texCoordOut); 

llega a 802 sprites a 50 fps (4804 triangularjs, incluidos los triangularjs degenerados), aunque se pierde la configuration de la opacidad del sprite. ¿Alguna sugerencia sobre cómo puedo manejar la opacidad en mi sombreador sin correr al 1/4 de la velocidad?

ACTUALIZACIÓN # 2 Así que descarté el controller View and View de GLKit y escribí una vista personalizada cargada desde AppDelegate. 902 sprites con opacidad y transparencia a 60fps.

En su mayoría pensamientos variados …

Si tiene un triángulo limitado, intente cambiar de GL_TRIANGLE_STRIP a GL_TRIANGLES . Aún necesitarás especificar exactamente el mismo número de índices, seis por cuádruple, pero la GPU nunca tiene que detectar que los triangularjs de connection entre cuádruples están degenerados (es decir, nunca tiene que convertirlos en píxeles de cero). Necesitarás un perfil para ver si terminas pagando un costo por no compartir implícitamente los bordes.

También debe networkingucir la huella de sus vértices. Me atrevo a imaginar que puedes especificar x, y, tx y ty como integers de 16 bits y tus colors como integers de 8 bits sin ningún cambio notable en la representación. Eso networkinguciría la huella de cada vértice de 32 bytes (ocho componentes, cada cuatro bytes de tamaño) a 12 bytes (cuatro valores de dos bytes más cuatro valores de un byte, sin necesidad de relleno porque todo está ya alineado) – cortar casi El 63% del ancho de banda de la memory cuesta allí.

Como realmente parece ser una tasa de relleno limitada, también debe considerar su textura original. Cualquier cosa que pueda hacer para recortar su tamaño de byte ayudará directamente a los envíos de text y, por lo tanto, a la tasa de relleno.

Parece que estás usando arte que es consciente de los píxeles, por lo que cambiar a PVR probablemente no sea una opción. Dicho esto, a veces las personas no se dan count del beneficio total de las texturas de PVR; si se cambia a, por ejemplo, el modo de 4 bits por píxel, puede escalar su image hasta el doble de ancho y el doble de alto para networkingucir los artefactos de compression y aún así pagar 16 bits en cada píxel de origen, pero es probable que obtenga un mejor range de luminancia que una textura RGB de 16 bpp.

Suponiendo que actualmente está utilizando una textura de 32 bpp, al less debería ver si una textura RGB ordinaria de 16 bpp es suficiente usando cualquiera de los modos de hardware proporcionados (especialmente si el 1 bit de canal alfa más 5 bits por canal de color es apropiado para su arte, ya que pierde solo 9 bits de información de color frente al original mientras networkinguce los costos de ancho de banda en un 50%).

También parece que estás cargando índices cada fotogtwig. Cargue solo cuando agregue objects adicionales a la escena o si el búfer que se cargó por última vez es enormemente mayor de lo que debe ser. Puede limitar el recuento pasado a glDrawElements para networkingucir los objects sin un reupload. También debe verificar si realmente obtiene algo subiendo sus vértices a un VBO y luego reutilizándolos si solo están cambiando cada fotogtwig. Puede ser más rápido proporcionarlos directamente desde la memory del cliente.