Android的RenderBuffer优化是否可行?

时间:2013-04-03 15:00:39

标签: android opengl-es fbo

我在Android Java上使用RenderBuffer和OpenGL而不是Canvas和Bitmap。但是,绘制到纹理需要时间。我提到this question并试图提高速度(减少glEnableVertexAttribArray,glClearColor,glBindFramebuffer的调用),但它无效。这是GPU和Android OS的限制吗?

*这是该程序的摘录。

GLES20.glAttachShader(program, vertex);
GLES20.glAttachShader(program, fragment);
GLES20.glLinkProgram(program);
GLES20.glUseProgram(program);

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[i]);
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);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, s, s,
0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);

GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbs[i]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,
GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, textures[i], 0);

GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, renders[i]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, s, s);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER,
GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, renders[i]);


GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbs[i]);
GLES20.glClearColor(fr, fg, fb, fa);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

GLES20.glGetIntegerv(GLES20.GL_FRAMEBUFFER_BINDING, old, 0);

GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbs[pos]);
GLES20.glViewport(0, 0, ww, hh);

:
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
:

GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, old[0]);
GLES20.glViewport(0, 0, scw, sch);

1 个答案:

答案 0 :(得分:2)

根据我的理解,如果你每次需要绘制一些内容时都使用了粘贴的所有代码,那么你的程序运行缓慢就不足为奇了。

OpenGL(无论是否为ES)基于“状态机”模型:OpenGL上下文保留您对其所做的更改(使用各种glXXX命令),并修改OpenGL对未来命令的反应方式(大多数)特别是你用于绘画的那些)。

这意味着当您发出命令时:

GLES20.glClearColor(fr, fg, fb, fa);

你真正在做的是设置

GL_COLOR_CLEAR_VALUE

状态机内的变量为[fr,fg,fb,fa]。从那一刻起,GL_COLOR_CLEAR_VALUE已经设置为[fr,fg,fb,fa],并且每次使用相同参数对glClearColor的额外调用都不会在机器中发生任何变化。

OpenGL ES 2.0 glClearColor reference page

我为什么要这样做?因为 OpenGL状态更改是性能关键(有些更多是其他更改):更改上下文的状态会产生性能损失,这通常超出了简单的变量赋值,因为它可能需要OpenGL“交谈” “到GPU,丢弃缓存和诸如此类的东西。在设置阶段完成时,这是一个必要的恶魔,但频繁的更改可能会在每帧完成时产生巨大的性能损失。

因此,您应该做的第一件事是通过创建初始化方法和drawframe方法来最小化程序中glXXX命令每秒的绝对数量。

标准方法是使用GLSurfaceView.Renderer类

Android GLSurfaceView.Renderer class reference

将所有初始化命令填入

public abstract void onSurfaceCreated (GL10 gl, EGLConfig config)

public abstract void onSurfaceChanged (GL10 gl, int width, int height)

并输入方法:

public abstract void onDrawFrame (GL10 gl)

尽可能少的OpenGL命令(正是你需要实际绘制的东西)

将理论放在一边并进入具体内容,以下是我建议您考虑的优化列表:

  • 如果您使用的是单个程序,请将整个程序保留下来:
    GLES20.glAttachShader(program, vertex);
    GLES20.glAttachShader(program, fragment);
    GLES20.glLinkProgram(program);
    GLES20.glUseProgram(program);

在设置部分阻止(即使你不这样做,只需用glUseProgram在程序之间切换:你不必反复链接它!)。 glLinkProgram可能会有性能受欢迎!

  • 纹理初始化进入设置(在“状态改变”之上,你实际上是将相同的非常数据从CPU内存一遍又一遍地移动到GPU内存中,每一帧)

  • 帧缓冲初始化(所有渲染缓冲区的创建和绑定)也在设置中。此外,为什么还需要多个帧缓冲区呢? :)

  • glViewport进入onSurfaceChanged方法

  • 在我看来你正在使用不同的帧缓冲区绘制不同的对象:我不确定你想要完成什么,但我建议你改变策略:绘制到整个屏幕和相同的缓冲区,除非你有充分的理由不这样做。

最后但同样重要的是,这是一本关于这个主题的好书:

OpenGL ES 2.0 Programming Guide

它既是对OpenGL ES 2.0的一个很好的介绍,也是对OpenGL的一个很好的介绍(我没有减少他们的销售;-))

希望有所帮助