1

I'm using RenderBuffer and OpenGL instead of Canvas and Bitmap on Android Java. However, drawing to a texture takes time. I referred to this question and tried speed improvement (Reduces the call of glEnableVertexAttribArray, glClearColor, glBindFramebuffer), but it's ineffective. Is this limitations of GPU and Android OS?

*This is an extract of the program.

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

1 回答 1

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 参考页

我为什么要进入这个?因为OpenGL 状态更改对性能至关重要(有些比其他更重要):更改上下文状态对性能的影响通常超出简单的变量分配,因为它可能需要 OpenGL 与 GPU“对话”,丢弃缓存等等。在设置阶段完成这是一个必要的邪恶,但频繁的更改可能会在每帧完成时对性能产生巨大影响。

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

标准方法是使用 GLSurfaceView.Renderer 类

Android GLSurfaceView.Renderer 类参考

将所有初始化命令塞进

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 编程指南

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

希望能帮助到你

于 2013-04-04T09:46:15.100 回答