6
$\begingroup$

I am doing exercises from the OpenGL SuperBible 6th Ed. I have managed to set up rendering into a framebuffer texture and then rendering from that texture to a cube.

But for some reason, when the texture gets applied to the cube, it is rendered incorrectly. I was expecting to see an entire rotating cube on a green background on each face of the main cube, but instead the faces have a texture applied as if split in half.

Here's a screenshot of my current situation:

enter image description here

I've spent a lot of time trying to fix this. I mean, the last 5 hours or so. I rewrote most of the code once and it fixed some of my previous erros, but now I'm stuck with this last part.

I used the SB sources as reference (https://github.com/openglsuperbible/sb6code/blob/master/src/basicfbo/basicfbo.cpp), but I can't find the reason why it looks like this.

I've also read this https://www.opengl.org/wiki/Framebuffer_Object_Examples but can't find a solution there.

What did I miss?

Here is my current code (the most important App class which does most of the work):

#include "config.h"

#include <GL/glew.h>
#include <GL/freeglut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "App.h"
#include "GLSLProgram.h"

void App::renderToFramebuffer() {
    float clearColor[] = { 0.0f, 0.5f, 0.0f, 1.0f };
    float one = 1.0f;

    m_rotation += 1.0f;

    glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);

    glViewport(0, 0, 512, 512);
    glClearBufferfv(GL_COLOR, 0, clearColor);
    glClearBufferfv(GL_DEPTH, 0, &one);

    glm::mat4 modelView = glm::translate(glm::mat4(), glm::vec3(-1.0f, -0.0f, -5.0f));
    glm::vec3 rotationY = glm::vec3(0.0f, 1.0f, 0.0f);
    modelView = glm::rotate(modelView, glm::radians(45.0f), rotationY);
    glm::vec3 rotationX = glm::vec3(1.0f, 0.0f, 0.0f);
    modelView = glm::rotate(modelView, glm::radians(m_rotation), rotationX);

    glm::mat4 projectionMatrix = glm::perspective(50.0f, 1.0f, 1.0f, 1000.0f);

    m_shaderNotTextured->start();
    m_shaderNotTextured->setMatrix(projectionMatrix, GL_PROJECTION_MATRIX);
    m_shaderNotTextured->setMatrix(modelView, GL_MODELVIEW_MATRIX);

    glDrawArrays(GL_TRIANGLES, 0, 36);

    m_shaderNotTextured->stop();

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void App::renderToScreen() {
    glBindVertexArray(m_VAO);

    glViewport(0, 0, SCREEN_X, SCREEN_Y);
    glClearBufferfv(GL_COLOR, 0, glm::value_ptr(m_clearColor));
    glClearBufferfv(GL_DEPTH, 0, &m_depthBufferDefault);

    glBindTexture(GL_TEXTURE_2D, m_TBO);

    glm::mat4 modelView = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.0f, -5.0f));
    glm::vec3 rotation = glm::vec3(0.0f, 1.0f, 0.0f);
    modelView = glm::rotate(modelView, glm::radians(45.0f), rotation);
    glm::vec3 rotationX = glm::vec3(1.0f, 0.0f, 0.0f);
    modelView = glm::rotate(modelView, glm::radians(45.0f), rotationX);

    m_shaderTextured->start();
    m_shaderTextured->setMatrix(m_projectionMatrix, GL_PROJECTION_MATRIX);
    m_shaderTextured->setMatrix(modelView, GL_MODELVIEW_MATRIX);

    glDrawArrays(GL_TRIANGLES, 0, 36);

    glBindTexture(GL_TEXTURE_2D, 0);

    m_shaderTextured->stop();
}

void App::render() {
    renderToFramebuffer();
    renderToScreen();
    glutSwapBuffers();
}

App::App() {
    glEnable(GL_TEXTURE_2D);

    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    m_clearColor = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
    m_depthBufferDefault = 1.0f;
    m_projectionMatrix = glm::perspective(50.0f, (float) SCREEN_X / (float) SCREEN_Y, 1.0f, 1000.0f);

    m_shaderNotTextured = new GLSLProgram();
    m_shaderNotTextured->addVertexShader("shaders/notex.vs.glsl");
    m_shaderNotTextured->addFragmentShader("shaders/notex.fs.glsl");
    m_shaderNotTextured->compile();

    m_shaderTextured = new GLSLProgram();
    m_shaderTextured->addVertexShader("shaders/tex.vs.glsl");
    m_shaderTextured->addFragmentShader("shaders/tex.fs.glsl");
    m_shaderTextured->compile();

    glGenVertexArrays(1, &m_VAO);
    glGenBuffers(NUM_BUFFERS, m_buffers);

    glGenTextures(1, &m_TBO);
    glGenTextures(1, &m_TDBO);

    glGenFramebuffers(1, &m_FBO);

    glBindVertexArray(m_VAO);

    glBindBuffer(GL_ARRAY_BUFFER, m_buffers[VBO]);
        static const GLfloat vertex_data[] =
        {
             // Position                 Tex Coord
            -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,
            -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,
             0.25f, -0.25f, -0.25f,      1.0f, 0.0f,

             0.25f, -0.25f, -0.25f,      1.0f, 0.0f,
             0.25f, -0.25f,  0.25f,      1.0f, 1.0f,
            -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,

             0.25f, -0.25f, -0.25f,      0.0f, 0.0f,
             0.25f,  0.25f, -0.25f,      1.0f, 0.0f,
             0.25f, -0.25f,  0.25f,      0.0f, 1.0f,

             0.25f,  0.25f, -0.25f,      1.0f, 0.0f,
             0.25f,  0.25f,  0.25f,      1.0f, 1.0f,
             0.25f, -0.25f,  0.25f,      0.0f, 1.0f,

             0.25f,  0.25f, -0.25f,      1.0f, 0.0f,
            -0.25f,  0.25f, -0.25f,      0.0f, 0.0f,
             0.25f,  0.25f,  0.25f,      1.0f, 1.0f,

            -0.25f,  0.25f, -0.25f,      0.0f, 0.0f,
            -0.25f,  0.25f,  0.25f,      0.0f, 1.0f,
             0.25f,  0.25f,  0.25f,      1.0f, 1.0f,

            -0.25f,  0.25f, -0.25f,      1.0f, 0.0f,
            -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,
            -0.25f,  0.25f,  0.25f,      1.0f, 1.0f,

            -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,
            -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,
            -0.25f,  0.25f,  0.25f,      1.0f, 1.0f,

            -0.25f,  0.25f, -0.25f,      0.0f, 1.0f,
             0.25f,  0.25f, -0.25f,      1.0f, 1.0f,
             0.25f, -0.25f, -0.25f,      1.0f, 0.0f,

             0.25f, -0.25f, -0.25f,      1.0f, 0.0f,
            -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,
            -0.25f,  0.25f, -0.25f,      0.0f, 1.0f,

            -0.25f, -0.25f,  0.25f,      0.0f, 0.0f,
             0.25f, -0.25f,  0.25f,      1.0f, 0.0f,
             0.25f,  0.25f,  0.25f,      1.0f, 1.0f,

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

        glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);

        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
        glEnableVertexAttribArray(0);

        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid *) (2 * sizeof(GLfloat)));
        glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);

        glBindTexture(GL_TEXTURE_2D, m_TBO);
            glTexStorage2D(GL_TEXTURE_2D, 9, GL_RGBA8, 512, 512);

            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        glBindTexture(GL_TEXTURE_2D, m_TDBO);
            glTexStorage2D(GL_TEXTURE_2D, 9, GL_DEPTH_COMPONENT32F, 512, 512);

        glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_TBO, 0);
        glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_TDBO, 0);

        GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };
        glDrawBuffers(1, drawBuffers);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[IBO]);

        static const GLushort vertex_indices[] =
        {
            0, 1, 2,
            2, 1, 3,
            2, 3, 4,
            4, 3, 5,
            4, 5, 6,
            6, 5, 7,
            6, 7, 0,
            0, 7, 1,
            6, 0, 2,
            2, 4, 6,
            7, 5, 3,
            7, 3, 1
        };

        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_indices), vertex_indices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

}

App::~App() {
    delete m_shaderNotTextured;
    delete m_shaderTextured;
    glDeleteBuffers(NUM_BUFFERS, m_buffers);
}


void App::update() {

}

Also, I have no idea why in SB6 code they are creating an array of indices and then not using it. I copied the part of the code with vertex data, initialized everything and then realized the indices aren't used. But I didn't remove them yet.

Edit: and here is the framebuffer cube colored to show more of how it is being displayed (you may notice how on most faces the texture is applied in halves):

the cube when colored

Edit2: and this is what I get when I don't bind the framebuffer and instead draw to screen after changing cubes to quads - so the image texture is being drawn correctly to the FB:

enter image description here

I am thinking - maybe this has something to do with the size of the texture or the size of viewport when rendering? I'm still completely baffled by this...

$\endgroup$
  • 2
    $\begingroup$ You can (and probably should) include images straight in the post (which I've done for your post now). Just hit Ctrl+G while editing the post and drag your image file into the browser. That way it will be hosted on imgur (on a specific Stack Exchange subdomain), which is a lot less likely to be subject to link rot at some point in the future (plus, people don't have to follow a link to your image to see what the problem). $\endgroup$ – Martin Ender Mar 15 '16 at 15:37
  • $\begingroup$ @MartinBüttner oh, thanks! I didn't know that I can do that here :) $\endgroup$ – Paweł Pela Mar 15 '16 at 15:40
  • 2
    $\begingroup$ I'd suggest to proceed step by step: try to display the framebuffer (directly with a quad) to validate its content first. Also, it looks like the UV on your cube might be wrong, so you may want to display your cube with its texture coordinates (gl_FragColor = vec4(gl_TexCoord[0].xy, 0., 1.);). $\endgroup$ – Julien Guertault Mar 17 '16 at 3:01
  • 1
    $\begingroup$ Other debugging techniques: Use a non-FBO texture to see if it shows up as you'd expect. Make sure that your FBO is complete by calling glCheckFramebufferStatus $\endgroup$ – Mokosha Mar 25 '16 at 14:57
  • 1
    $\begingroup$ Assuming that the content of the FBO is correct, and based on your comment and the look of the cube on your screenshot, it sounds to me your texture coordinates are simply incorrect. You could use a regular texture as Mokosha suggests, and switch to FBO only after you have the cube textured correctly. $\endgroup$ – Julien Guertault Apr 3 '16 at 12:32

Your Answer

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

Browse other questions tagged or ask your own question.