Рендеринг кадрового буфера FBO в текстуру выполняется очень медленно при использовании OpenGL ES 2.0 на Android. Почему?

Я программирую 2D-игру для Android, используя opengl 2.0. После того, как я отрисовываю спрайты в задний буфер, я отрисовываю свет в FBO и снова пытаюсь смешать его с задним буфером. Когда я рисую FBO в фреймбуфере, даже прозрачном без какого-либо цвета, частота кадров падает с 60 до 30 на Samsung Galaxy w (у него Adreno 205 в качестве графического процессора). Я искал везде и пробовал все, даже если я рисую одиночный спрайт на сцене и смешиваю прозрачную текстуру FBO с экраном, частота кадров падает. Я попробовал другие игры со световыми эффектами на этом телефоне, и они работают нормально, почти все игры на этом телефоне работают нормально, я думаю, что они также используют фреймбуфер. На Galaxy SII (mali 400 gpu) работает нормально, я совсем новичок в opengl, поэтому думаю, что где-то ошибся, делюсь своим кодом.

// 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);

Я делаю это один раз при создании поверхности. Не уверен, что правильно. Я сохраняю идентификаторы текстуры и фреймбуфера, чтобы переключаться на них, когда мне нужно. Мой код отрисовки:

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();

Все отображается на экране правильно, но производительность падает только тогда, когда я рисую текстуру FBO. Спасибо большое за помощь. Я очень много работал над этим и не нашел решения.

6
задан abergmeier 10 December 2012 в 08:17
поделиться