我正在寻找一个最小的例子,其中每个帧将重用前一帧中的三角形。我一直在尝试不成功,所以我没有任何值得展示的代码,虽然我有一个程序可以通过绘制到默认的帧缓冲区来工作。
在绘制过程中,我会向帧缓冲对象添加新的三角形,并将帧复制到默认的帧缓冲区。由于我不会清除帧缓冲区对象,它将保留其rgba值和深度,因此当我在下一帧添加更多三角形时,之前的那些仍将保留。 (稍后我将减少前一帧中三角形的alpha值以产生淡入淡出效果,但为了简单起见,请重复使用前面的三角形,因为它们很好。)
我发现很难理解帧缓冲区对象是如何工作的,以及我是否需要创建渲染,深度和纹理缓冲区。我怀疑我需要渲染和深度缓冲,因为我想在绘制之间保留该信息,但不需要纹理缓冲区。
我认为onDrawFrame方法看起来像这样:
我相信我正在通过绑定framebuffer对象,renderbuffer和深度缓冲区来正确地执行步骤1和2,但我无法找到从一个帧缓冲区复制到另一个帧缓冲区的方法。
答案 0 :(得分:2)
对于第3步,使用渲染的纹理(用作FBO颜色附件的纹理),并在绘制屏幕尺寸四边形时从中进行采样。您可以使用非常简单的着色器。副本的顶点着色器将如下所示:
#version 100
attribute vec2 Pos;
varying vec2 TexCoord;
void main() {
TexCoord = 0.5 * Pos + 0.5;
gl_Position = vec4(Pos, 0.0, 1.0);
}
和片段着色器:
#version 100
uniform sampler2D Tex;
varying vec2 TexCoord;
void main() {
gl_FragColor = texture2D(Tex, TexCoord);
}
然后绘制一个四边形,覆盖x和y中的范围[-1.0,1.0]。
还有另一种选择。不幸的是,它不便携,但可以在某些设备上运行。以下是我最近的答案:Fast Screen Flicker while NOT drawing on Android OpenGL。
对于这种方法,请致电:
eglSurfaceAttrib(display, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
设置上下文/表面时。这要求在eglSwapBuffers()
之后保留缓冲区内容。但它有一个很大的警告:所有设备都不支持此功能。您可以测试它是否支持:
EGLint surfType = 0;
eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfType);
if (surfType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) {
// supported!
}
您也可以在选择配置时请求此功能。作为传递给eglChooseConfig()
的属性的一部分,请添加:
...
EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT,
...
但同样,在所有设备上不支持。因此,如果您针对特定设备进行定位,那么它只是一个选项,如果不支持则具有功能性后备功能。
答案 1 :(得分:1)
帧缓冲对象实际上只是一个元对象,它是包含它的表面(纹理或渲染缓冲区)的容器。您需要创建所需的颜色/深度/模板,并且"附加"他们到了 帧缓冲对象中的相关附着点。
在从一个表面复制到另一个表面方面,你可以使用glBlitFramebuffer,或者只是渲染一个2D四边形,将屏幕外表面加载为纹理,并设置纹理坐标,使其为1:1副本。
注意"渲染超过内存中的内容"在大多数基于磁贴的移动GPU上都是相对昂贵的(它们必须将旧状态读入GPU本地内存),特别是如果您需要单独的副本将屏幕外缓冲区插入到屏幕缓冲区中。我建议进行性能分析,以确保这个方案真的比重新渲染更快,因为它听起来可能不是。