我在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);
答案 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的一个很好的介绍(我没有减少他们的销售;-))
希望有所帮助