opengl – Get black bars with framebuffer and glViewport

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 (400×225) and place it in a 1280×720 window at the position 100×100 (from bottom-left);

  1. Load a 400×225 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 100×100, but it has also created a 100×100 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.