2012-05-23 27 views
6

Estoy programando un juego de Android 2D con OpenGL es 2.0. Después de dibujar mis sprites en el backbuffer, traigo luces a un FBO e intento mezclarlo con el buffer de nuevo. Cuando dibujo el FBO en el framebuffer, incluso transparente sin ningún color, la velocidad de fotogramas pasa de 60 a 30 en un Samsung Galaxy w (tiene un adreno 205 como gpu). Busqué en todas partes y probé todo, incluso si dibujo un solo sprite en la escena y mezclo una textura FBO transparente en la pantalla, la velocidad de fotogramas disminuye. Probé otros juegos con efectos de iluminación en ese teléfono y funcionan bien, casi todos los juegos están bien en ese teléfono, creo que también usan el framebuffer. En el Galaxy SII (mali 400 gpu) funciona bien, soy bastante nuevo en opengl, así que creo que estoy cometiendo un error en alguna parte, comparto mi código.Framebuffer FBO renderizar a textura es muy lento, con OpenGL ES 2.0 en Android, ¿por qué?

// Create a framebuffer and renderbuffer 
GLES20.glGenFramebuffers(1, fb, offset); 
GLES20.glGenRenderbuffers(1, depthRb, offset); 

// Create a texture to hold the frame buffer 
GLES20.glGenTextures(1, renderTex, offset); 
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex[offset]); 

GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 
        screenWidth, screenHeight, 0, 
        GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, 
        null); 


GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, 
         GLES20.GL_CLAMP_TO_EDGE); 
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, 
         GLES20.GL_CLAMP_TO_EDGE); 
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, 
         GLES20.GL_LINEAR); 
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, 
         GLES20.GL_LINEAR); 

//bind renderbuffer 
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRb[offset]); 

GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, 
          screenWidth, screenHeight); 

// bind the framebuffer 
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[offset]); 

// specify texture as color attachment 
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, 
           GLES20.GL_TEXTURE_2D, renderTex[offset], 0); 

// specify depth_renderbufer as depth attachment 
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, 
           GLES20.GL_RENDERBUFFER, depthRb[0]); 

// Check FBO status. 
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); 

if (status == GLES20.GL_FRAMEBUFFER_COMPLETE) 
{ 
    Log.d("GLGame framebuffer creation", "Framebuffer complete"); 
} 


// set default framebuffer 
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 

Hago esto una vez en la creación de superficies. No estoy seguro si es correcto. Guardo los ID de textura y framebuffer para cambiarlos cuando lo necesito. Mi código de dibujo:

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId); 
ShaderProgram program = glgame.getProgram(); 

//put vertices in the floatbuffer 
mTriangleVertices.put(vertices, 0, len); 
mTriangleVertices.flip(); 

GLES20.glVertexAttribPointer(program.POSITION_LOCATION, 2, GLES20.GL_FLOAT, false, 
          TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 

//preparing parameter for texture position 
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); 
GLES20.glEnableVertexAttribArray(program.POSITION_LOCATION); 

//preparing parameter for texture coords 
GLES20.glVertexAttribPointer(program.TEXTURECOORD_LOCATION, 2, GLES20.GL_FLOAT, 
          false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, 
          mTriangleVertices); 

//set projection matrix 
GLES20.glEnableVertexAttribArray(program.TEXTURECOORD_LOCATION); 
GLES20.glUniformMatrix4fv(program.MATRIX_LOCATION, 1, false, matrix, 0); 

//draw triangle with indices to form a rectangle 
GLES20.glDrawElements(GLES20.GL_TRIANGLES, numSprites * 6, GLES20.GL_UNSIGNED_SHORT, 
         indicesbuf); 

//clear buffers 
mTriangleVertices.clear(); 
mVertexColors.clear(); 

Todo se representa en la pantalla correctamente, pero el rendimiento se arruinan justo cuando dibujo la textura FBO. Muchas gracias por su ayuda. Trabajé muy duro en esto y no encontré una solución.

+0

Última respuesta, pero estoy haciendo algo similar en un HD2 bajo ICS y es prácticamente lo mismo. Puedo renderizar cualquier cosa sin problemas a 60 fps, pero cuando uso un FBO, la velocidad de fotogramas baja a 45, y si uso otro FBO baja a 30. –

+0

Hmm ... He visto algunos juegos en Samsung Galaxy w funcionando sin problemas y parecían usar un framebuffer para 2d luces, mi código funciona lentamente en su lugar. Me pregunto si estoy cometiendo errores. – mao

+0

galaxy usa el chipset sgx. como he dicho antes, está relacionado con la arquitectura pequeña de gmem y de mosaico, cada vez que cambias el framebuffer anterior necesitas copiarlo a la memoria normal, si lo borras como una primera llamada después de un enlace, no necesita ser copiado de la normal mem to gmem, es por eso que framebuffers son lentos especialmente en adreno 200 :) se puede comprobar es la aplicación usando framebuffers con adreno profiler si tiene dispositivo adreno, simplemente enchúfelo y descargue el cuadro actual, luego verifique fb en texturas. si encuentra uno, estará seguro, – ZZZ

Respuesta

12

De acuerdo con los documentos de Qualcomm, necesita glclear después de cada glbindframebuffer, este es un problema relacionado con la arquitectura de mosaico, si está cambiando framebuffers, los datos deben copiarse de fastmem a la memoria normal para guardar el framebuffer actual y de slowmem a mem rápida para obtener contenido de frame nuevo, en caso de que se borre justo después de glbind no se copian datos de slowmem a fastmem y está ahorrando tiempo, pero necesita rediseñar su canalización de renderizado a menudo, por lo que evitará leer datos nuevamente y entre memoria lenta y rápida, así que intente hacer glclear después de cada enlace y debería ser útil, también puede usar el analizador adreno para obtener información adicional sobre llamadas problemáticas, pero dudo que ayude con adreno200. Estoy tratando de obtener dos almacenamientos intermedios para Desenfoque y estoy terminando con 10 fps, la llamada de bindframebuffer puede tomar hasta 20 mseg si no se borra, si es sho uld final a los 2 ms.

+0

Probaré esto tan pronto como pueda volver a poner mis manos en el Adreno 205. Encontré la documentación de Qualcomm y la seguiré. ¡Muchas gracias por su ayuda! – mao

+0

[Aquí] (https://www.google.sk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CDEQFjAA&url=https%3A%2F%2Fdeveloper.qualcomm.com%2Fdownload%2Fadreno200performanceoptimizationopenglestipsandtricksmarch10 .pdf & ei = DT6IUcaTMYXV4ASEwYHYAQ & usg = AFQjCNFbU3Vf2mT2sf7LTAJQ3xqijdyUAA & sig2 = JMoeTn8G1MQgor9ZGDdFQg & bvm = bv.45960087, d.bGE) es el documento de Qualcomm. –

+1

Si desea conservar el contenido del framebuffer, simplemente haga 'glClear (0);', que también parece solucionar el problema. – Thomas

Cuestiones relacionadas