6

我正在使用 opengl es 2.0 编写 Android 2d 游戏。在我将精灵绘制到后台缓冲区后,我将灯光绘制到 FBO 并尝试再次将其混合到后台缓冲区。当我将 FBO 绘制到帧缓冲区时,即使是没有任何颜色的透明,三星 Galaxy w 上的帧速率也会从 60 下降到 30(它有一个 adreno 205 作为 gpu)。我到处搜索并尝试了所有方法,即使我在场景中绘制了一个精灵并将一个透明的 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);

我在表面创建时这样做过一次。不确定是否正确。我保留纹理和帧缓冲区 ID,以便在需要时切换到它们。我的绘图代码:

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 纹理时性能就被破坏了。非常感谢您的帮助。我为此非常努力,但没有找到解决方案。

4

1 回答 1

13

根据 qualcomm docs,您需要在每个 glbindframebuffer 之后进行 glclear,这是与平铺架构相关的问题,如果您正在切换帧缓冲区,则需要将数据从 fastmem 复制到普通内存以保存当前帧缓冲区,并从 slowmem 复制到 fast mem 以获得新绑定帧的内容,以防您在 glbind 之后清除没有数据从 slowmem 复制到 fastmem 并且您可以节省时间,但是您需要经常重新设计渲染管道,这样可以避免在慢速和慢速之间来回读取数据快速内存,因此在每次绑定后尝试执行 glclear 应该会有所帮助,您还可以使用 adreno 分析器来获取有关有问题的调用的其他信息,但我怀疑它对 adreno200 有帮助我正在尝试获取两个用于模糊的缓冲区,我是以10fps结束,如果未清除 bindframebuffer 调用最多可能需要 20 毫秒,如果已清除,则应在 2 毫秒结束。

于 2012-06-15T14:13:41.783 回答