OpenGL 帧缓冲的PingPong技术
The ping pong technique
- 乒乓是一种交替使用给定渲染输出作为输入的技术.
主要有三种方式:
-
Use one FBO with one attachment per texture that is rendered to, and bind a different FBO in each rendering pass using glBindFramebufferEXT().
使用两个FBO对象. 使用
glBindFramebufferEXT()
绑定新的FBO
-
Use one FBO, reattach the render target texture in each pass using glFramebufferTexture2DEXT().
使用一个FBO对象,重新附着
render texture
使用glFramebufferTexture2DEXT
传递纹理. -
Use one FBO and multiple attachment points, switch using glDrawBuffer().
使用一个FBO对象,附着多个
attachment texture
交叉使用glDrawBuffer
Since there are up to four attachment points available per FBO and since the last approach turns out to be fastest, we will explain how to ping pong between different attachments.
由于每个FBO可以有最多四个 附着点. 最后一种方法是最快的.接下来我们会解释如何在不同附着点实现乒乓技术.
To do this, we first need a set of management variables: 首先先设置管理的变量
// two textures identifiers referencing y_old and y_new
GLuint yTexID[2];
// ping pong management vars
int writeTex = 0;
int readTex = 1;
GLenum attachmentpoints[] = { GL_COLOR_ATTACHMENT0_EXT,
GL_COLOR_ATTACHMENT1_EXT
};
During the computation, all we need to do now is to pass the correct value from these two tupels to the corresponding OpenGL calls, and to swap the two index variables after each pass:
交换索引
// attach two textures to FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
attachmentpoints[writeTex],
texture_Target, yTexID[writeTex], 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
attachmentpoints[readTex],
texture_Target, yTexID[readTex], 0);
// enable fragment profile, bind program [...]
// enable texture x (read-only) and uniform parameter [...]
// iterate computation several times
for (int i=0; i<numIterations; i++) {
// set render destination
glDrawBuffer (attachmentpoints[writeTex]);
// enable texture y_old (read-only)
cgGLSetTextureParameter(yParam, yTexID[readTex]);
cgGLEnableTextureParameter(yParam);
// and render multitextured viewport-sized quad
// swap role of the two textures (read-only source becomes
// write-only target and the other way round):
swap();
}