使用实例化绘图时渲染到纹理

Render To Texture when using instanced drawing

我绘制了几个对象,一些使用 "regular" 方法,一些使用 glDrawArraysInstanced 并且一切正常。

我正在尝试通过使用 Frame Buffers 渲染到纹理来添加一些 post 处理,但是当我这样做时,如果我正在绘制实例化对象,我会得到这个结果:

(你可以在乱七八糟的背后看到实际的物品)。

如果我注释实例对象的 draw 方法,一切都很好。

是否可以将实例化绘图与渲染到纹理一起使用?

一些代码:

实例化对象

void LifeMeter::draw(mat4 wvp)
{
    // Set the program to be used in subsequent lines:
    glUseProgram(program);

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glUniform1i(glGetUniformLocation(program, "texSampler"), /*GL_TEXTURE*/0);

    glBindVertexArray(_vao);
    glUniformMatrix4fv (glGetUniformLocation(program, "wvp") , 1, GL_FALSE, value_ptr(wvp));
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vec4)*amountOfLives, positions);
    glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, amountOfLives);

    // Unbind the Vertex Array object
    glBindVertexArray(0);
    // Cleanup, not strictly necessary
    glUseProgram(0);
}

Post 处理缓冲区

void PPBuffer::init(int screen_width, int screen_height)
{
  // buffer
  // The framebuffer, which regroups 0, 1, or more textures, and 0 or 1 depth buffer.

  glGenFramebuffers(1, &fbo);
  glBindFramebuffer(GL_FRAMEBUFFER, fbo);


  /* Texture  */

  // The texture we're going to render to
  glGenTextures(1, &fbo_texture);

  // "Bind" the newly created texture : all future texture functions will modify this texture
  glBindTexture(GL_TEXTURE_2D, fbo_texture);
  glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA,screen_width, screen_height, 0,GL_RGBA, GL_UNSIGNED_BYTE, 0);

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

  glBindTexture(GL_TEXTURE_2D, 0);

  // depth buffer
  glGenRenderbuffers(1, &rbo_depth);
  glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth);
  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, screen_width, screen_height );

  glBindRenderbuffer(GL_RENDERBUFFER, 0);

  /* Framebuffer to link everything together */
  glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fbo_texture, 0); //use more of these for MRT
  // glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, fbo_texture1, 0);

  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo_depth);

  // Set the list of draw buffers.
  GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};

  glDrawBuffers(1,DrawBuffers); 

  // for MRT:  glDrawBuffers(2,{GL_COLOR_ATTACHMENT0,GL_COLOR_ATTACHMENT1}); 

  GLenum status;
  if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) {
    fprintf(stderr, "glCheckFramebufferStatus: error %d", status);
    exit(0);
  }

  glBindFramebuffer(GL_FRAMEBUFFER, 0);

  // vertices 
  GLfloat fbo_vertices[] = {
    -1, -1,
    1, -1,
    -1,  1,
    1,  1,
  };

  // Create and bind the object's Vertex Array Object:
  glGenVertexArrays(1, &_vao);
  glBindVertexArray(_vao);

  glGenBuffers(1, &vbo_fbo_vertices);
  glBindBuffer(GL_ARRAY_BUFFER, vbo_fbo_vertices);
  glBufferData(GL_ARRAY_BUFFER, sizeof(fbo_vertices), fbo_vertices, GL_STATIC_DRAW);
  glBindBuffer(GL_ARRAY_BUFFER, 0);  

  glBindVertexArray(0);
  // shader
  programManager::sharedInstance()
    .createProgram("pp",
           SHADERS_DIR "postproc.v.glsl",
           SHADERS_DIR "postproc.f.glsl");
  program_postproc = programManager::sharedInstance().programWithID("pp");

  attribute_v_coord_postproc = glGetAttribLocation(program_postproc, "v_coord");
  uniform_fbo_texture = glGetUniformLocation(program_postproc, "fbo_texture");
}

void PPBuffer::setup() {
  glBindFramebuffer(GL_FRAMEBUFFER, fbo);
}

void PPBuffer::render() {
  glBindFramebuffer(GL_FRAMEBUFFER, 0);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

  glClearColor(0.3, 0.0, 0.0, 1.0);

  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

  glUseProgram(program_postproc);

  glActiveTexture(GL_TEXTURE0);

  glBindTexture(GL_TEXTURE_2D, fbo_texture);
  glUniform1i(uniform_fbo_texture, /*GL_TEXTURE*/0);

  glBindVertexArray(_vao);
  glEnableVertexAttribArray(attribute_v_coord_postproc);
  glBindBuffer(GL_ARRAY_BUFFER, vbo_fbo_vertices);
  glVertexAttribPointer(
            attribute_v_coord_postproc,  // attribute
            2,                  // number of elements per vertex, here (x,y)
            GL_FLOAT,           // the type of each element
            GL_FALSE,           // take our values as-is
            0,                  // no extra data between each position
            0                   // offset of first element
            );
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  glDisableVertexAttribArray(attribute_v_coord_postproc);
  glBindBuffer(GL_ARRAY_BUFFER,0);
  glBindVertexArray(0);
  glUseProgram(0);
}

显示功能

void display(void)
{

    _ppbuffer.setup();
    // Clear the screen buffer
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);

    // tell the model to draw itself...
    shuttle->draw(); // Regular object
    lifeMeter->draw(Projection ); // Instanced object


    _ppbuffer.render();

    // Swap those buffers so someone will actually see the results... //
    glutSwapBuffers();
}

我解决了这个问题,所以如果有人偶然发现这个问题,问题出在 blending 功能上。

删除行

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

问题已解决。既然我可以没有他们,我就很满足了。