0
\$\begingroup\$

I have read several tutorials and answers regarding framebuffers and glViewport, but I can't seem to resolve this issue I have. I want to take a low resolution framebuffer (400x225) and place it in a 1280x720 window at the position 100x100 (from bottom-left);

  1. Load a 400x225 png image in a framebuffer with the same size
glGenFramebuffers(1, &m_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);

glGenTextures(1, &m_textureColorbuffer);
glBindTexture(GL_TEXTURE_2D, m_textureColorbuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 400, 225, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textureColorbuffer, 0);

glGenRenderbuffers(1, &m_renderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, m_renderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, screenW, screenH); stencil buffer.
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_renderBuffer); 
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    printf("ERROR::FRAMEBUFFER:: Framebuffer is not complete!");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
  1. Generate the quad for the framebuffer:
    float quadVertices[] = { // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
    // positions   // texCoords
    -1.0f,  1.0f,  0.0f, 1.0f,
    -1.0f, -1.0f,  0.0f, 0.0f,
     1.0f, -1.0f,  1.0f, 0.0f,

    -1.0f,  1.0f,  0.0f, 1.0f,
     1.0f, -1.0f,  1.0f, 0.0f,
     1.0f,  1.0f,  1.0f, 1.0f
    };

    unsigned int quadVBO;
    glGenVertexArrays(1, &m_quadVAO);
    glGenBuffers(1, &quadVBO);
    glBindVertexArray(m_quadVAO);
    glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
  1. Create an orthographic projection matrix with the framebuffer size:
glm::mat4 bgProjection = glm::ortho(0.0f, static_cast<float>(400), static_cast<float>(225), 0.0f, -1.0f, 1.0f);
  1. Set the glViewport:
glViewport(0, 0, 400, 225);
  1. Bind the framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
  1. Draw the sprite:
    shader->use();
    glm::mat4 model = glm::mat4(1.0f);
    model = glm::translate(model, glm::vec3(position, 0.0f));  // first translate (transformations are: scale happens first, then rotation, and then final translation happens; reversed order)

    model = glm::translate(model, glm::vec3(0.5f * size.x, 0.5f * size.y, 0.0f)); // move origin of rotation to center of quad
    model = glm::rotate(model, glm::radians(rotate), glm::vec3(0.0f, 0.0f, 1.0f)); // then rotate
    model = glm::translate(model, glm::vec3(-0.5f * size.x, -0.5f * size.y, 0.0f)); // move origin back

    model = glm::scale(model, glm::vec3(size, 1.0f)); // last scale

    shader->setMat4("model", model);
    shader->setMat4("projection", projection);

    shader->setVec3("Colour", color);

    glBindVertexArray(this->quadVAO);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
  1. Unbind the framebuffer:
glBindFramebuffer(GL_FRAMEBUFFER, 0);
  1. Finally render the framebuffer:
    shader.use();
    glBindVertexArray(m_quadVAO);
    glBindTexture(GL_TEXTURE_2D, m_textureColorbuffer); // use the color attachment texture as the texture of the quad plane
    glDrawArrays(GL_TRIANGLES, 0, 6);

This is the output I get when glViewport(0, 0, 400, 225); enter image description here

But when I set the glViewport(100, 100, 400, 225); I get these black borders: enter image description here

As you can see, the glViewport has moved to 100x100, but it has also created a 100x100 gap in the viewport. I have tried adjusting the projection matrix and framebuffer, but it seems like I am doing something incorrect with glViewport. Thank you.

\$\endgroup\$
0
\$\begingroup\$

Your viewport is taken into account 2 times: before drawing the sprite and before rendering the framebuffer. I suggest keeping current glViewport(0, 0, 400, 225); as it is and adding one more glViewport right before drawing the framebuffer. In this seccond glViewport you can set up needed offset.

\$\endgroup\$
1
  • \$\begingroup\$ That worked brilliantly, thank you. Here is what I changed: 1. glViewport(0, 0, 400, 225); 2.. Bind framebuffer 3. Draw sprite 4. Unbind framebuffer 5. glViewport(100, 100, 400, 225); 6. Render framebuffer \$\endgroup\$ Jan 9 at 15:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.