OpenGL 帧缓冲区缺失面

Posted

技术标签:

【中文标题】OpenGL 帧缓冲区缺失面【英文标题】:OpenGL Framebuffer Missing Faces 【发布时间】:2018-09-20 21:54:04 【问题描述】:

我在使用 OpenGL 实现多通道着色器以启用 HDR 时遇到问题。

第一遍将场景渲染到帧缓冲区。

第二遍使用带有颜色和深度的帧缓冲区来渲染到四边形。

(我关注this tutorial。)


问题在于它不会渲染某些(正面、顶部和一侧)立方体面。

如果我在没有帧缓冲区的情况下进行渲染(不更改任何其他渲染代码),它会正常工作。


我尝试使用 GL_CCW 和 GL_CW 更改面的缠绕,但更改 glDepthFunc 无济于事。

这是渲染器初始化的代码:

Renderer::Renderer(Window window): window(window) 
  this->materials = std::map<std::string, Material>();
  this->meshes = std::map<std::string, Mesh>();

  // glEnable(GL_BLEND);
  glEnable(GL_DEPTH_TEST);
  glDisable(GL_CULL_FACE);
  glEnable(GL_FRAMEBUFFER_SRGB);
  glViewport(0, 0, window.width, window.height);  
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  this->load_textures();
  this->load_materials();
  this->load_meshes();

  this->load_shader_programs();

  this->create_hdr(this->shader_programs.find("hdr")->second);

这会在第一次渲染之前生成帧缓冲区:

void Renderer::create_hdr(ShaderProgram sp_hdr) 
  glGenFramebuffers(1, &this->hdr_fbo);

  glGenTextures(1, &this->color_buffer);
  glBindTexture(GL_TEXTURE_2D, this->color_buffer);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, this->window.width, this->window.height, 0, GL_RGBA, GL_FLOAT, NULL);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  glGenRenderbuffers(1, &this->render_buffer);
  glBindRenderbuffer(GL_RENDERBUFFER, this->render_buffer);
  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, this->window.width, this->window.height);

  glBindFramebuffer(GL_FRAMEBUFFER, this->hdr_fbo);
  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->color_buffer, 0);
  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, this->depth_buffer);
  if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 
    std::cout << "Framebuffer not complete!" << std::endl;
  
  glBindFramebuffer(GL_FRAMEBUFFER, 0);

  glUseProgram(sp_hdr.id);
  glUniform1i(glGetUniformLocation(sp_hdr.id, "hdr_buffer"), 0);

这会分两次渲染关卡:

void Renderer::render(Level level, Camera camera, std::vector<std::reference_wrapper<DirectionalLight>> d_lights, std::vector<PointLight> p_lights, std::vector<SpotLight> s_lights) 
  // 1. First Pass - HDR
  glBindFramebuffer(GL_FRAMEBUFFER, this->hdr_fbo);

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  ShaderProgram sp_render = this->shader_programs.find("render")->second;
  glUseProgram(sp_render.id);

  attach_camera(camera, sp_render);
  attach_projection_matrix(camera, sp_render);
  attach_view_matrix(camera, sp_render);

  unsigned int d_light_num = 0;
  for (DirectionalLight d_light : d_lights) 
    attach_d_light(d_light, sp_render, d_light_num);
    d_light_num++;
    

  for (Block block : level.blocks) 
    attach_position(block.position, sp_render);

    Material material = this->materials.find(block.material_id)->second;
    attach_material(material, sp_render);

    Mesh mesh = this->meshes.find(block.mesh_id)->second;
    draw_mesh(mesh, sp_render); 
  

  glBindFramebuffer(GL_FRAMEBUFFER, 0);

  // 2. Second Pass - Render to quad
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  ShaderProgram sp_hdr = this->shader_programs.find("hdr")->second;
  glUseProgram(sp_hdr.id);

  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, this->color_buffer);

  draw_mesh(this->meshes.find("quad")->second, sp_hdr);

【问题讨论】:

【参考方案1】:

我通过实际连接正确的深度渲染缓冲区来解决这个问题:

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, this->depth_buffer);

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, this->render_buffer);

【讨论】:

以上是关于OpenGL 帧缓冲区缺失面的主要内容,如果未能解决你的问题,请参考以下文章

将负值混合到帧缓冲区 0 opengl

快速交换帧缓冲区 OpenGL

如何定义 QT Opengl 帧缓冲区的大小

OpenGL 帧缓冲区 - 渲染到纹理创建带有主帧缓冲区内容的纹理

◮OpenGL-帧缓冲

◮OpenGL-帧缓冲