2013-03-09 92 views
4

我想这是某种可能的,因为这样的:是否可以在OpenGL中将数据从一个帧缓冲复制到另一个帧缓冲?

glBindFramebuffer(GL_READ_FRAMEBUFFER_APPLE, _multisampleFramebuffer); 
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_APPLE, _framebuffer); 
glResolveMultisampleFramebufferAPPLE(); 

正是这么做的,并在上面解决了多重采样。但是,这是一个Apple扩展,我想知道是否有类似的东西将所有逻辑缓冲区从一个帧缓冲区复制到另一个帧缓冲区,并且不会在vanilla实现中执行多重采样部分。 GL_READ_FRAMEBUFFER似乎不是一个有效的目标,所以我猜测没有直接的方法?变通方法如何?

编辑:似乎有可能在OpenGL 4中使用glCopyImageSubData,不幸的是不是在我的情况下,因为我在iPhone上使用OpenGL ES 2.0,这似乎缺乏该功能。任何其他方式?

回答

3

glBlitFramebuffer完成你正在寻找的东西。此外,您可以将一个TEXTURE粘贴到另一个上,而不需要两个帧缓冲区。我不确定在OpenGL ES 2.0中使用一个fbo是可能的,但下面的代码可以很容易地修改为使用两个fbos。您只需将不同的纹理附加到不同的帧缓冲附件。 glBlitFramebuffer函数甚至可以管理反锯齿应用的下采样/上采样!下面是它的用法示例:

// bind fbo as read/draw fbo 
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,m_fbo); 
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo); 

// bind source texture to color attachment 
glBindTexture(GL_TEXTURE_2D,m_textureHandle0); 
glFramebufferTexture2D(GL_TEXTURE_2D, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textureHandle0, 0); 
glDrawBuffer(GL_COLOR_ATTACHMENT0); 

// bind destination texture to another color attachment 
glBindTexture(GL_TEXTURE_2D,m_textureHandle1); 
glFramebufferTexture2D(GL_TEXTURE_2D, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_textureHandle1, 0); 
glReadBuffer(GL_COLOR_ATTACHMENT1); 


// specify source, destination drawing (sub)rectangles. 
glBlitFramebuffer(from.left(),from.top(), from.width(), from.height(), 
        to.left(),to.top(), to.width(), to.height(), GL_COLOR_BUFFER_BIT, GL_NEAREST); 

// release state 
glBindTexture(GL_TEXTURE_2D,0); 
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); 
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,0); 
+2

glBlitFramebuffer是不是在OpenGL ES 2.0的 – Kimi 2013-03-09 17:19:36

+0

妈用,我不知道。我找不到任何文档可用的E​​S glBlitFramebuffer版本,只找到一个说明它可用的OpenGL ES 3.0文档。我不能等到桌面和ES标准收敛,所以我不必在所有该死的时候对功能设置感到困惑。 – 2013-03-09 17:39:55

+0

为什么不只是附加纹理来读取缓冲区并绘制它们来绘制缓冲区? – 2013-03-11 18:11:23

2

在OpenGL 4中测试,glBlitFramebuffer在OpenGL ES 2.0中不受支持。

我在以前的答案固定的错误,并推广到可以支持两个帧缓冲区的函数:

// Assumes the two textures are the same dimensions 
void copyFrameBufferTexture(int width, int height, int fboIn, int textureIn, int fboOut, int textureOut) 
{ 
    // Bind input FBO + texture to a color attachment 
    glBindFramebuffer(GL_READ_FRAMEBUFFER, fboIn); 
    glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureIn, 0); 
    glReadBuffer(GL_COLOR_ATTACHMENT0); 

    // Bind destination FBO + texture to another color attachment 
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboOut); 
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textureOut, 0); 
    glDrawBuffer(GL_COLOR_ATTACHMENT1); 

    // specify source, destination drawing (sub)rectangles. 
    glBlitFramebuffer(0, 0, width, height, 
         0, 0, width, height, 
         GL_COLOR_BUFFER_BIT, GL_NEAREST); 

    // unbind the color attachments 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, 0); 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); 
} 
0

,您可以直接与OpenGL ES 2.0的做到这一点,似乎没有延伸既不。

我并不确定你想要达到的目标,但是一般来说,只需要移除已经完成离屏渲染的FBO的附件。然后绑定默认的FBO以便能够在屏幕上绘制,在这里您可以简单地绘制一个带有填充屏幕的正交相机的四边形和一个将您的离屏生成的纹理作为输入的着色器。 如果您使用多重采样的纹理,您也可以做出决定。

glBindFramebuffer(GL_FRAMEBUFFER, off_screenFBO); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); 

glBindFramebuffer(GL_FRAMEBUFFER, 0); // Default FBO, on iOS it is 1 if I am correct 

// Set the viewport at the size of screen 
// Use your compositing shader (it doesn't have to manage any transform) 
// Active and bind your textures 
// Sent textures uniforms 
// Draw your quad 

这里是着色器的为例:

// Vertex 
attribute vec2 in_position2D; 
attribute vec2 in_texCoord0; 
varying lowp vec2 v_texCoord0; 
void main() 
{ 
    v_texCoord0 = in_texCoord0; 
    gl_Position = vec4(in_position2D, 0.0, 1.0); 
} 

// Fragment 
uniform sampler2D u_texture0; 
varying lowp vec2 v_texCoord0; 

void main() 
{ 
    gl_FragColor = texture2D(u_texture0, v_texCoord0); 
}