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:
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):
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:
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...



gl_FragColor = vec4(gl_TexCoord[0].xy, 0., 1.);). – Julien Guertault Mar 17 '16 at 03:01glCheckFramebufferStatus– Mokosha Mar 25 '16 at 14:57