【发布时间】:2012-05-23 23:38:53
【问题描述】:
我正在使用 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 纹理时性能就被破坏了。 非常感谢您的帮助。我为此付出了很多努力,但没有找到解决方案。
【问题讨论】:
-
迟到的答案,但我在 ICS 下的 HD2 上做了类似的事情,而且几乎是一样的。我可以在 60fps 下毫无问题地渲染任何东西,但是当我使用 FBO 时,帧速率会下降到 45,如果我使用另一个 FBO,它会下降到 30。
-
嗯...我看到三星 Galaxy 上的一些游戏运行没有问题,它们似乎使用帧缓冲区来处理 2d 灯光,但我的代码运行缓慢。我想知道我是否犯了错误。
-
galaxy 使用 sgx 芯片组。就像我之前所说的,它与小型 gmem 和平铺架构有关,每次你更改帧缓冲区时,都需要将旧的帧缓冲区复制到普通内存,如果你在绑定后第一次调用时将其清除,则不需要从正常复制回来mem 到 gmem,这就是为什么帧缓冲区很慢的原因,尤其是在 adreno 200 上 :) 如果您有 adreno 设备,您可以检查应用程序是否使用带有 adreno 分析器的帧缓冲区,只需将其插入并下载当前帧,然后检查纹理中的 fb。如果你能找到一个你会确定的,
-
在 HD2 上很大程度上取决于您构建中使用的驱动程序,我有一个 2.3.3 构建,每个 fb 绑定都被识别为阻塞解析,而 ics 上的相同代码被识别为非阻塞解析并以大约 5-10 fps 的速度运行。我认为这可能与高通在 ics 推出后的一段时间内为开发者开放驱动程序有关。
标签: android 2d opengl-es-2.0 framebuffer render-to-texture