Hi forum,
I am trying to implement the basic fbo technique where a cube is rendered to the texture first and unbind the frame buffer object , read the rendered texture and pass it through the shader and eventually render the cube to the default frame buffer - the window.
I should get a output where a image of the first cube we rendered in shown on each face of the second cube. But I am not getting it. I am getting the second cube only render on the default framebuffer. I am attaching the code snippet, Some hint would really be appreciated.
Thanks
// Include standard headers
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <vector>
#include "config.h"
GLFWwindow* window;
// Include GLM
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace glm;
int winWidth = 800;
int winHeight = 600;
float aspect = 0.0f;
GLuint program1;
GLuint program2;
GLuint vao;
GLuint position_buffer;
GLuint index_buffer;
GLuint fbo;
GLuint color_texture;
GLuint depth_texture;
GLint mv_location;
GLint proj_location;
GLuint mv_location2;
GLuint proj_location2;
//set the window background clearing color
static const GLfloat backgroundcolor[] = {0.0f,0.0f,0.0f,1.0f};
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void render(double time);
void startup();
int main( void )
{
// Initialise GLFW
if( !glfwInit() )
{
std::cerr << "Failed to initialize GLFW." << std::endl;
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_SAMPLES, 4);
//we want the opengl 4
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
//we do not want the old opengl
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Open a window and create its OpenGL context
window = glfwCreateWindow( winWidth, winHeight, "Blending Functions", NULL, NULL);
if( window == NULL )
{
fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 4.3 compatible. Try the 2.1 version of the tutorials.
" );
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
//make the current window context current
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwGetFramebufferSize(window,&winWidth,&winHeight);
framebuffer_size_callback(window,winWidth,winHeight);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "Failed to initialize GLEW
");
exit(EXIT_FAILURE);
}
while(glGetError() != GL_NO_ERROR) {}
//print out information aout the graphics driver
std::cout << std::endl;
std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << std::endl;
std::cout << "GLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
std::cout << "GLEW Verion: " << glewGetString(GLEW_VERSION) << std::endl;
std::cout << "OpenGL Vendor: " << glGetString(GL_VENDOR) << std::endl;
std::cout << "Renderer: " << glGetString(GL_RENDERER) << std::endl;
//load the texture and the shaders
startup();
do{
render(glfwGetTime());
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
glfwDestroyWindow(window);
// Close OpenGL window and terminate GLFW
glfwTerminate();
glDeleteVertexArrays(1, &vao);
glDeleteProgram(program1);
glDeleteProgram(program2);
glDeleteBuffers(1, &position_buffer);
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(1, &color_texture);
exit(EXIT_SUCCESS);
}
void render(double currentTime)
{
static const GLfloat green[] = { 0.0f, 0.1f, 0.0f, 1.0f };
static const GLfloat blue[] = { 0.0f, 0.0f, 0.3f, 1.0f };
static const GLfloat one = 1.0f;
glm::mat4 proj_matrix = glm::perspective(50.0f,
(float)winWidth / (float)winHeight,
0.1f,
1000.0f);
float f = (float)currentTime * 0.3f;
glm::mat4 mv_matrix = glm::translate(glm::mat4(1.0f),glm::vec3(0.0f, 0.0f, -4.0f)) *
glm::translate(glm::mat4(1.0f) , glm::vec3(sinf(2.1f * f) * 0.5f,
cosf(1.7f * f) * 0.5f,
sinf(1.3f * f) * cosf(1.5f * f) * 2.0f)) *
glm::rotate(glm::mat4(1.0),(float)currentTime * 45.0f, glm::vec3(0.0f, 1.0f, 0.0f)) *
glm::rotate(glm::mat4(1.0),(float)currentTime * 81.0f, glm::vec3(1.0f, 0.0f, 0.0f));
//bind to the framebuffer so that all the following rendering
//will be done on the depth and color buffers
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
//set the viewport and dimension of the framebuffer
glViewport(0, 0, 512, 512);
//clear the color buffer
glClearBufferfv(GL_COLOR, 0, green);
glClearBufferfv(GL_DEPTH, 0, &one);
glUseProgram(program1);
glUniformMatrix4fv(proj_location, 1, GL_FALSE, glm::value_ptr(proj_matrix));
glUniformMatrix4fv(mv_location, 1, GL_FALSE, glm::value_ptr(mv_matrix));
//the cube is rendered to the texture we attached before
glDrawArrays(GL_TRIANGLES, 0, 36);
//unbind the framebuffer, returning to the default framebuffer - the window
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, winWidth, winHeight);
glClearBufferfv(GL_COLOR, 0, blue);
glClearBufferfv(GL_DEPTH, 0, &one);
//render the cube again
//bind the texture we just rendered to for reading
glBindTexture(GL_TEXTURE_2D, color_texture);
//activate the program that will read from the texture
glUseProgram(program2);
glUniformMatrix4fv(proj_location2, 1, GL_FALSE, glm::value_ptr(proj_matrix));
glUniformMatrix4fv(mv_location2, 1, GL_FALSE, glm::value_ptr(mv_matrix));
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindTexture(GL_TEXTURE_2D, 0);
}
void startup()
{
static const char * vs_source[] =
{
"#version 410 core
"
"
"
"layout (location = 0) in vec4 position;
"
"layout (location = 1) in vec2 texcoord;
"
"
"
"out VS_OUT
"
"{
"
" vec4 color;
"
" vec2 texcoord;
"
"} vs_out;
"
"
"
"uniform mat4 mv_matrix;
"
"uniform mat4 proj_matrix;
"
"
"
"void main(void)
"
"{
"
" gl_Position = proj_matrix * mv_matrix * position;
"
" vs_out.color = position * 2.0 + vec4(0.5, 0.5, 0.5, 0.0);
"
" vs_out.texcoord = texcoord;
"
"}
"
};
static const char * fs_source1[] =
{
"#version 410 core
"
"
"
"in VS_OUT
"
"{
"
" vec4 color;
"
" vec2 texcoord;
"
"} fs_in;
"
"
"
"out vec4 color;
"
"
"
"void main(void)
"
"{
"
" color = sin(fs_in.color * vec4(40.0, 20.0, 30.0, 1.0)) * 0.5 + vec4(0.5);
"
"}
"
};
static const char * fs_source2[] =
{
"#version 420 core
"
"
"
"uniform sampler2D tex;
"
"
"
"out vec4 color;
"
"
"
"in VS_OUT
"
"{
"
" vec4 color;
"
" vec2 texcoord;
"
"} fs_in;
"
"
"
"void main(void)
"
"{
"
" color = mix(fs_in.color, texture(tex, fs_in.texcoord), 0.7);
"
"}
"
};
program1 = glCreateProgram();
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fs_source1, NULL);
glCompileShader(fs);
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, vs_source, NULL);
glCompileShader(vs);
glAttachShader(program1, vs);
glAttachShader(program1, fs);
glLinkProgram(program1);
glDeleteShader(vs);
glDeleteShader(fs);
program2 = glCreateProgram();
fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fs_source2, NULL);
glCompileShader(fs);
vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, vs_source, NULL);
glCompileShader(vs);
glAttachShader(program2, vs);
glAttachShader(program2, fs);
glLinkProgram(program2);
glDeleteShader(vs);
glDeleteShader(fs);
mv_location = glGetUniformLocation(program1, "mv_matrix");
proj_location = glGetUniformLocation(program1, "proj_matrix");
mv_location2 = glGetUniformLocation(program2, "mv_matrix");
proj_location2 = glGetUniformLocation(program2, "proj_matrix");
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
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
};
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,
};
glGenBuffers(1, &position_buffer);
glBindBuffer(GL_ARRAY_BUFFER, position_buffer);
glBufferData(GL_ARRAY_BUFFER,
sizeof(vertex_data),
vertex_data,
GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid *)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
sizeof(vertex_indices),
vertex_indices,
GL_STATIC_DRAW);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenTextures(1, &color_texture);
glBindTexture(GL_TEXTURE_2D, color_texture);
glTexImage2D(GL_TEXTURE_2D, //target
1, //level
GL_RGBA8, //internalformat
winWidth, //width
winHeight, //height
0, //border
GL_RGBA8, //format
GL_UNSIGNED_BYTE, //type
0); //pointer to data
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenTextures(1, &depth_texture);
glBindTexture(GL_TEXTURE_2D, depth_texture);
glTexImage2D(GL_TEXTURE_2D,1,GL_DEPTH_COMPONENT32F,winWidth,winHeight,0,GL_DEPTH_COMPONENT32F,GL_FLOAT,0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, color_texture, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_texture, 0);
static const GLenum draw_buffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, draw_buffers);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
float ratio = 1.0f;
if(height > 0)
ratio = (float)width / (float)height;
winWidth = width;
winHeight = height;
}