Android 的 RenderBuffer 可以优化吗?

Posted

技术标签:

【中文标题】Android 的 RenderBuffer 可以优化吗?【英文标题】:Is optimization of Android's RenderBuffer possible? 【发布时间】:2013-04-03 15:00:39 【问题描述】:

我在 android Java 上使用的是 RenderBuffer 和 OpenGL,而不是 Canvas 和 Bitmap。但是,绘制到纹理需要时间。我参考了this question 并尝试了提高速度(减少了glEnableVertexAttribArray、glClearColor、glBindFramebuffer 的调用),但效果不佳。这是 GPU 和 Android 操作系统的限制吗?

*这是程序的摘录。

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

【问题讨论】:

这是您的 renderFrame 函数的摘录吗?我的意思是,这一切都是每帧执行的吗? 之前是每一帧,但我现在只在需要时才绘制。但是,在那一刻显示生涩。 【参考方案1】:

据我了解,如果您每次需要绘制某些东西时都使用粘贴的所有代码,那么您的程序运行缓慢也就不足为奇了。

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,丢弃缓存等等。在设置阶段完成这是一个必要的坏事,但频繁的更改可能会在每帧完成时对性能造成巨大影响。

因此,您应该做的第一件事是通过创建一个初始化方法和一个并条框方法,最大限度地减少程序中glXXX 命令的绝对数量每秒。。 p>

标准方法是使用 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(程序,顶点); GLES20.glAttachShader(程序,片段); GLES20.glLinkProgram(程序); GLES20.glUseProgram(程序);

在设置部分中设置块(即使您不这样做,只需使用 glUseProgram 在程序之间切换:您不必一遍又一遍地链接它!)。 glLinkProgram 可能会对性能造成巨大的影响!

纹理初始化在设置中进行(除了“状态更改”之外,您实际上是在将相同的数据从 CPU 内存一次又一次地移动到 GPU 内存,每一帧)

李>

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

glViewport 进入 onSurfaceChanged 方法

在我看来您正在使用不同的帧缓冲区来绘制不同的对象:我不确定您要完成什么,但我建议您更改策略: 绘制到整个屏幕并在同一个缓冲区上,除非你有很好的理由不这样做。

最后但并非最不重要的是,这是一本关于该主题的好书:

OpenGL ES 2.0 Programming Guide

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

希望对你有帮助

【讨论】:

我很高兴您的礼貌解释。我将尽可能将 gl 的初始化分组到 onSurfaceCreated 和 onSurfaceChanged。我认为硬件的性能仍然没有改善是原因。 你每帧画了多少个三角形?如果您正在使用 OpenGL 开发看起来像基于 2D sprite 的游戏,请不要放弃!我没有数据,但我敢打赌,即使是低端 2.2 设备也不会因屏幕上的 100~200 纹素而退缩 绘制到 RenderBuffer 的三角形大约有 20 个,因为它是 2D 的。如果还有其他令人担忧的地方,我会添加一个后记。 20 quads/texel 完全在市场上每部 Android 手机的能力范围内,您可以信赖这一点。暂时忘记有关帧缓冲区和渲染缓冲区的所有内容:Android 提供的默认帧缓冲区实现可能会运行得很好(并且没有什么会阻止您以后添加自己的):考虑从您的代码中删除所有包含单词 Framebuffer 或 Renderbuffer 的行。跨度>

以上是关于Android 的 RenderBuffer 可以优化吗?的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL中Framebuffer和Renderbuffer的概念和区别是啥?

Framebuffer 和 Renderbuffer 的 Webgl 绑定

FrameBuffer & RenderBuffer

我是不是需要在我的 FBO 中使用 RenderBuffer 对象来渲染到保留 Alpha 通道的纹理?

WebGL— FrameBuffer,RenderBuffer,Texture区别

WebGL— FrameBuffer,RenderBuffer,Texture区别