是否可以在OpenGL中将数据从一个帧缓冲区复制到另一个帧缓冲区?

时间:2013-03-09 03:44:34

标签: opengl-es opengl-es-2.0

我想这是可能的,因为这个:

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 个答案:

答案 0 :(得分:3)

glBlitFramebuffer完成了你想要的东西。此外,您可以将一个TEXTURE blit到另一个上,而无需两个帧缓冲区。我不确定使用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);

答案 1 :(得分:2)

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

我修复了上一个答案中的错误,并将其推广到一个可以支持两个帧缓冲区的函数中:

// 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);
}

答案 2 :(得分: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);
}