将两个图像附加到 fbo 以进行 mrt 渲染

Posted

技术标签:

【中文标题】将两个图像附加到 fbo 以进行 mrt 渲染【英文标题】:attach two images to fbo for mrt rendering 【发布时间】:2013-12-29 17:23:08 【问题描述】:

我想将两个渲染目标附加到一个 fbo,这样我就可以一次渲染到两个目标。我有一个函数可以接受两个渲染目标。

void render(struct glhexbutton *_this, GLuint target0, GLuint target1)

  GLenum buffers[2];
  GLfloat vertices[] =  -1.0, -1.0,
                         -1.0,  1.0,
                          1.0, -1.0,
                          1.0,  1.0  ;

  GLubyte indices[] =  0, 1, 2,
                        1, 2, 3  ;

  GLuint fbo;

  struct 
      int x;
      int y;
   position;


  /*Load variables into shader program*/
  glUniform4f(glhexbutton_static.uni_address, 1.0, 1.0, 1.0, 1.0);

  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, _this->data.texture);
  glUniform1i(glhexbutton_static.uni_texture, /*GL_TEXTURE*/0); 
  glBindTexture(GL_TEXTURE_2D, 0);

  glUseProgram(_this->data.static_data->program);

  /*create fbo and attach render targets*/

  glGenFramebuffers(1, &fbo);

  glBindFramebuffer(GL_FRAMEBUFFER, fbo);

  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                       target0, 0);
  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
                       target1, 0);

  /*Set the viewport of the fbo*/

  position.x = glutGet(GLUT_WINDOW_WIDTH)*_this->data.position.relative.x+_this->data.position.offset.x;
  position.y = glutGet(GLUT_WINDOW_HEIGHT)*_this->data.position.relative.y+_this->data.position.offset.y;
  glViewport(position.x, position.y,
             _this->data.size.width, _this->data.size.height);

  buffers[0] = GL_COLOR_ATTACHMENT0;
  buffers[1] = GL_COLOR_ATTACHMENT1;

  glDrawBuffers(2, buffers);



  glEnableVertexAttribArray(_this->data.static_data->att_coord);
  glVertexAttribPointer(_this->data.static_data->att_coord,
                        2,
                        GL_FLOAT,
                        GL_FALSE,
                        0,
                        vertices);
  glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);
  glDisableVertexAttribArray(_this->data.static_data->att_coord);


  glBindFramebuffer(GL_FRAMEBUFFER, 0);
  glDeleteFramebuffers(GL_FRAMEBUFFER, &fbo);

我的顶点着色器:

#version 330
attribute vec2 coord;
varying vec2 f_coord;
void main() 
  gl_Position = vec4(coord, 0.0, 1.0);
  f_coord = (1.0+coord)/2.0;

我的像素/片段着色器:

#version 330
uniform sampler2D texture;
uniform vec4 address;
varying vec2 f_coord;
void main() 
  gl_FragData[0]=texture2D(texture,f_coord);
  gl_FragData[1]=address;
  if(texture2D(texture,f_coord).a == 0.0)
    discard;

当我打电话时

render(glhexbutton, 0, texture);

render(glhexbutton, texture, 0);

我只是得到一个黑色的空白屏幕

【问题讨论】:

【参考方案1】:

我想将两个渲染目标附加到默认 fbo,这样我就可以一次渲染到两个目标。

没有默认的 FBO。有一个默认帧缓冲区,它是由您将上下文绑定到的可绘制对象提供的(通常是一个窗口)。您不能将纹理/渲染缓冲区附加到默认 FB,并且GL_COLOR_ATTACHMENTs 对默认 FB 中的glDrawBuffer 无效。因此,您的代码只会产生一些 GL 错误并继续以单一渲染目标模式渲染到之前设置的绘制缓冲区。

【讨论】:

我已经更新了代码,我添加了两行用于创建和绑定 fbo,以及两行用于取消绑定和删除 fbo。但现在我得到一个空白屏幕。 @user2798943:当然可以。因为您现在渲染到纹理中,而不是渲染到屏幕上。我不知道您要达到什么目标,但是您目前所做的没有意义。附带说明:为某些没有绑定的颜色附件启用绘制缓冲区(您的“0”情况)将导致无效状态。在这种情况下,您可以使用 GL_NONE。如果您以某种方式认为将纹理 0 附加到某些 FBO 并最终再次渲染到默认 FB,那您就错了。你要么渲染到某个 FBO,要么渲染到默认的 FB,而且 cen 永远不会混合两者。 好的,我已经更改了代码,所以两个参数现在都是纹理 ID。好的 target0 现在渲染得很好,但不是 target1。 target1 一个保持空白。【参考方案2】:

由于没有默认的离屏 fbo,您需要在代码中实现一个乒乓方案,然后使用 FBO 作为输入纹理以显示绘图。您可以查看 sgxperf 中的简单代码,了解设置 FBO 并使用它渲染到显示器的工作示例,此处为https://gist.github.com/prabindh/8173489

【讨论】:

以上是关于将两个图像附加到 fbo 以进行 mrt 渲染的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL ES 多目标渲染(MRT)

FBO 用于分离纹理

渲染到窗口帧缓冲区和 FBO 以保存全尺寸纹理图像

OpenGL FBO 与 MRT 写入后台缓冲区

使用 FBO 和着色器 OpenGL 渲染到纹理

是否可以将默认渲染缓冲区附加到 FBO?