Related
My current issues are;
I am unsure at which point I can render to the frame buffer, glBindFramebuffer(GL_FRAMEBUFFER, fbo); , I am assuming this is done after I have bound the frame buffer. (Where can I render to the framebuffer?)
I am unsure how I can get the texture I have rendered to use later as a texture. (How will I be accessing the texture after rendering to it?)
Here is my code so far;
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowPosition(100,100);
glutInitWindowSize(400,400);
glutCreateWindow("Main Window");
glutDisplayFunc(display);
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
//Draw stuff here?
GLuint tex;
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
GLuint rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) cout << "FB setup: Complete" << endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &fbo);
// use texture here?
// i.e. draw quad with texture, where is the texture?
glutMainLoop();
return 0;
}
You can render to the framebuffer as soon as it is bound and has all necessary textures and renderbuffers attached (i.e. it must be "complete").
You can use the texture as soon as you've finished rendering to the framebuffer and unbound it. Note that you cannot use a texture of a framebuffer while drawing into the same framebuffer.
As scicyb pointed out, you also can't delete the framebuffer while you're still using it. The texture is not part of the framebuffer, so you can use the texture after deleting the framebuffer, but you can't use the framebuffer after deleting the framebuffer. The framebuffer is used to draw things and the texture is where the pixels end up when you draw them.
I am trying to render from a multisampled framebuffer to a default frame buffer.
first i enable multisampling with these commands.
glfwWindowHint(GLFW_SAMPLES, 4);
glEnable(GL_MULTISAMPLE);
Than i create a multisampled buffer
unsigned int fboMsaaId, rboDepthId;
unsigned int MsaaTexture;
// Generate texture
glGenTextures(1, &MsaaTexture);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 800, 600, false);
// create a multisample buffer
glGenFramebuffers(1, &fboMsaaId);
glGenRenderbuffers(1, &rboDepthId);
glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepthId);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, 800, 600);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, MsaaTexture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,rboDepthId);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
In the render loop.
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw our triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboMsaaId);
glDrawBuffer(GL_BACK);
glBlitFramebuffer(0, 0, 800, 600, 0, 0, 800, 600, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glfwSwapBuffers(window);
glfwPollEvents();
}
If i render into the default framebuffer i am able to see the drawn object but when i blit from multisampled frame buffer to default frame buffer nothing is drawn on the screen.
What you want to do is make it so that the default framebuffer is not multisampled. That is, you want to blit from a multisampled framebuffer to a non-multisampled framebuffer.
Yes, it is legal to blit between two multisampled framebuffers, but this is only legal if they have the same sample count. And while you did request a 4-sampled default framebuffer, the default framebuffer is not entirely under your control. Implementations get to play fast-and-loose as to how many samples a default framebuffer gets.
So it's best to avoid this possibility altogether and use a non-multisampled default framebuffer.
I have been looking for OpenGL Multi Sample Anti Aliasing tutorials and I found many but I'll take 2.
They use a different way to do this. I have tested both ways and both work for my project so I can use any of them.
I use this to render my game engine scene to a texture.
This is the 1st way:
Create the FBO with MSAA
// create a texture object
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
// create a MSAA framebuffer object
// NOTE: All attachment images must have the same # of samples.
// Ohterwise, the framebuffer status will not be completed.
glGenFramebuffers(1, &fboMsaaId);
glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId);
// create a MSAA renderbuffer object to store color info
glGenRenderbuffers(1, &rboColorId);
glBindRenderbuffer(GL_RENDERBUFFER, rboColorId);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, MSAA_level, GL_RGB8, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// create a MSAA renderbuffer object to store depth info
// NOTE: A depth renderable image should be attached the FBO for depth test.
// If we don't attach a depth renderable image to the FBO, then
// the rendering output will be corrupted because of missing depth test.
// If you also need stencil test for your rendering, then you must
// attach additional image to the stencil attachement point, too.
glGenRenderbuffers(1, &rboDepthId);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepthId);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, MSAA_level, GL_DEPTH_COMPONENT, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// attach msaa RBOs to FBO attachment points
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboColorId);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepthId);
// create a normal (no MSAA) FBO to hold a render-to-texture
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glGenRenderbuffers(1, &rboId);
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// attach a texture to FBO color attachement point
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
// attach a rbo to FBO depth attachement point
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId);
//## disable color buffer if you don't attach any color buffer image,
//## for example, rendering the depth buffer only to a texture.
//## Otherwise, glCheckFramebufferStatus will not be complete.
//glDrawBuffer(GL_NONE);
//glReadBuffer(GL_NONE);
// check FBO status
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
return false;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
And when I need to draw the scene
glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId);
glViewport(0, 0, width, height);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawScene();
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboMsaaId);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId);
glBlitFramebuffer(0, 0, width, height, // src rect
0, 0, width, height, // dst rect
GL_COLOR_BUFFER_BIT, // buffer mask
GL_LINEAR); // scale filter
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, App->window->GetWidth(), App->window->GetHeight());
The 2nd way:
Create the FBO with MSAA
unsigned int framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
// create a multisampled color attachment texture
unsigned int textureColorBufferMultiSampled;
glGenTextures(1, &textureColorBufferMultiSampled);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureColorBufferMultiSampled);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB, SCR_WIDTH, SCR_HEIGHT, GL_TRUE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textureColorBufferMultiSampled, 0);
// create a (also multisampled) renderbuffer object for depth and stencil attachments
unsigned int rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// configure second post-processing framebuffer
unsigned int intermediateFBO;
glGenFramebuffers(1, &intermediateFBO);
glBindFramebuffer(GL_FRAMEBUFFER, intermediateFBO);
// create a color attachment texture
unsigned int screenTexture;
glGenTextures(1, &screenTexture);
glBindTexture(GL_TEXTURE_2D, screenTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, screenTexture, 0); // we only need a color buffer
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
cout << "ERROR::FRAMEBUFFER:: Intermediate framebuffer is not complete!" << endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
And when I need to draw the scene:
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glViewport(0, 0, width, height);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawScene();
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediateFBO);
glBlitFramebuffer(0, 0, SCR_WIDTH, SCR_HEIGHT, 0, 0, SCR_WIDTH, SCR_HEIGHT, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, App->window->GetWidth(), App->window->GetHeight());
Summarizing:
1st way: Create FBO, create RBO for color and RBO for depth and use glRenderbufferStorageMultisample(...) to specify the MSAA level. Then create other FBO with texture for color and RBO for depth.
2nd way: Create FBO, create Texture for color and RBO for depth and using glTexImage2DMultisample(...) for MSAA level in the texture. Then create other FBO and a texture.
What are the differences on using one way or other? Is one better than the other?
MSAA setup in your example is actually the same in both cases. The only difference between the two methods you depicted is - different FBO attachment type. In general, you will want to attach a texture and not render buffer when you later need to use the information from that FBO for further render passes. In such a case you would plug previous render pass FBO's texture attachment into texture unit, and sample from it in the next pass shader program. Shadow mapping is one of such cases.
I have a very specific OpenGL setup where the 3D geometry in the scene does not render. There is some depth-related state in the OpenGL context that illudes me.
This is in a production engine at work where we added shared context support with multiple window contexts. We are doing the rendering to a framebuffer object owned by the shared context, then blitting the color attachment renderbuffer to a window using a different context.
The clear color is showing in the resulting blit to the window, but not the 3D scene geometry itself, so we know the framebuffer and renderbuffer objects are at least partially correct.
To illustrate, I refactored a sample from the LearnOpenGL website to illustrate my bug. It shows up there as well, so I am clear this is something I am missing.
Here is the GitHub project where I made three commits to a working framebuffer sample so that it rendered to the framebuffer using a shared context and then blits the result: Framebuffer Shared Context Experiment
Here is most of the source code that produces the buggy result. I snipped a few sections that went unchanged.
// glfw dummy window creation
// --------------------
GLFWwindow* dummy = NULL;
#if USE_SHARED_CONTEXT
dummy = glfwCreateWindow(1, 1, "Dummy", NULL, NULL);
if (dummy == NULL)
{
std::cout << "Failed to create dummy GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(dummy);
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, dummy);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwShowWindow(window);
#if !USE_SHARED_CONTEXT
glfwMakeContextCurrent(window);
#endif
// <snip creation of shared resources>
// <snip creation of un-shared vertex array>
// framebuffer configuration
// -------------------------
unsigned int framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
#if 1
// create a color attachment render buffer
unsigned int Colorbuffer;
glGenRenderbuffers(1, &Colorbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, Colorbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer.
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, Colorbuffer); // now actually attach it
#else
// create a color attachment texture
unsigned int textureColorbuffer;
glGenTextures(1, &textureColorbuffer);
glBindTexture(GL_TEXTURE_2D, textureColorbuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorbuffer, 0);
#endif
// create a renderbuffer object for depth and stencil attachment (we won't be sampling these)
unsigned int rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer.
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // now actually attach it
// now that we actually created the framebuffer and added all attachments we want to check if it is actually complete now
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// <snip timing and input>
#if USE_SHARED_CONTEXT
// use shared context because that is what is holding our framebuffer and vao.
// -----
glfwMakeContextCurrent(dummy);
#endif
// render
// ------
// bind to framebuffer and draw scene as we normally would to color texture
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glEnable(GL_DEPTH_TEST); // enable depth testing (is disabled for rendering screen-space quad)
// make sure we clear the framebuffer's content
glClearColor(1.0f, 0.1f, 0.1f, 1.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// following render is unchanged
shader.use();
glm::mat4 model;
glm::mat4 view = camera.GetViewMatrix();
glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
shader.setMat4("view", view);
shader.setMat4("projection", projection);
// cubes
glBindVertexArray(cubeVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, cubeTexture);
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
shader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
model = glm::mat4();
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
shader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
// floor
glBindVertexArray(planeVAO);
glBindTexture(GL_TEXTURE_2D, floorTexture);
shader.setMat4("model", glm::mat4());
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
#if 1
#if USE_SHARED_CONTEXT
// use window context for presentation via blit.
// -----
glfwMakeContextCurrent(window);
// temorary framebuffer for visible window since framebuffers are not shared
// -------------------------
unsigned int readFramebuffer;
glGenFramebuffers(1, &readFramebuffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, Colorbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, SCR_WIDTH, SCR_HEIGHT);
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, Colorbuffer);
#endif
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, SCR_WIDTH, SCR_HEIGHT, 0, 0, SCR_WIDTH, SCR_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
#if USE_SHARED_CONTEXT
glDeleteFramebuffers(1, &readFramebuffer);
#endif
#else
// now bind back to default framebuffer and draw a quad plane with the attached framebuffer color texture
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST); // disable depth test so screen-space quad isn't discarded due to depth test.
// clear all relevant buffers
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways)
glClear(GL_COLOR_BUFFER_BIT);
screenShader.use();
glBindVertexArray(quadVAO);
glBindTexture(GL_TEXTURE_2D, textureColorbuffer); // use the color attachment texture as the texture of the quad plane
glDrawArrays(GL_TRIANGLES, 0, 6);
#endif
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// <snip epilog>
You can toggle the USE_SHARED_CONTEXT compile-time switch to remove the little bit of code that renders using a shared context.
I was missing a call to glViewport for the shared render context.
The value of the Viewport was defaulted to (0, 0) -> (width, height) for the context used by the visible window. The shared render context had been defaulted to (0, 0) -> (1, 1) because I used a width and height of 1 for the non-visible GLFW window.
I am at my wits end trying to implement framebuffer objects in OpenGL and C++.
Basically, I have a class that handles the functionality of framebuffer objects. However, after render to the framebuffer and then using the framebuffer as a texture, the only thing that draws is the blue from the command glClearColor.
Looking at this code, did i miss something?
void FrameBuffer::initFrameBufferDepthBuffer(void) {
glGenRenderbuffers(1, &fbo_depth); // Generate one render buffer and store the ID in fbo_depth
glBindRenderbuffer(GL_RENDERBUFFER, fbo_depth); // Bind the fbo_depth render buffer
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, window_width, window_height); // Set the render buffer storage to be a depth component, with a width and height of the window
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo_depth); // Set the render buffer of this buffer to the depth buffer
bool status = glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
if(!status){
std::cout << "Error during depth buffer\n";
}
glBindRenderbuffer(GL_RENDERBUFFER, 0); // Unbind the render buffer
}
void FrameBuffer::initFrameBufferTexture(void) {
glGenTextures(1, &fbo_texture); // Generate one texture
glBindTexture(GL_TEXTURE_2D, fbo_texture); // Bind the texture fbo_texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, window_width, window_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); // Create a standard texture with the width and height of our window
// Setup the basic texture parameters
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,getTexture(), 0);
// Unbind the texture
glBindTexture(GL_TEXTURE_2D, 0);
bool status = glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;;
if(!status){
std::cout << "Error during texture buffer\n";
}
}
void FrameBuffer::create(void) {
glGenFramebuffers(1, &fbo); // Generate one frame buffer and store the ID in fbo
glBindFramebuffer(GL_FRAMEBUFFER, fbo); // Bind our frame buffer
initFrameBufferDepthBuffer(); // Initialize our frame buffer depth buffer
initFrameBufferTexture(); // Initialize our frame buffer texture
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_texture, 0); // Attach the texture fbo_texture to the color buffer in our frame buffer
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo_depth); // Attach the depth buffer fbo_depth to our frame buffer
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); // Check that status of our generated frame buffer
if (status != GL_FRAMEBUFFER_COMPLETE) // If the frame buffer does not report back as complete
{
std::cout << "Couldn't create frame buffer" << std::endl; // Output an error to the console
exit(0); // Exit the application
}
glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind our frame buffer
}
void FrameBuffer::bindTexture() {
glBindTexture(GL_TEXTURE_2D, fbo_texture); // Bind our frame buffer texture
}
void FrameBuffer::unbindTexture() {
glBindTexture(GL_TEXTURE_2D, 0); // Bind our frame buffer texture
}
void FrameBuffer::bind() {
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
}
void FrameBuffer::unbind() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void FrameBuffer::startUse() {
bind();
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT); // Push our glEnable and glViewport states
glViewport(0, 0, window_width, window_height); // Set the size of the frame buffer view port
glMatrixMode( GL_PROJECTION ); //Switch to setting the camera perspective
float ratio = (GLfloat)window_width/(GLfloat)window_height; //Set the camera perspective
glLoadIdentity(); //reset the camera
gluPerspective( 60.0f, ratio, 0.1f, 100.0f );
glMatrixMode(GL_MODELVIEW);
glClearColor (0.0f, 0.0f, 1.0f, 1.0f); // Set the clear colour
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the depth and colour buffers
glLoadIdentity();
}
void FrameBuffer::stopUse() {
glPopAttrib(); // Restore our glEnable and glViewport states
unbind();
}
void FrameBuffer::destroy() {
glDeleteFramebuffers(1,&this->fbo);
glDeleteTextures(1,&fbo_texture);
glDeleteRenderbuffers(1,&fbo_depth);
}
unsigned int FrameBuffer::getTexture() {
return fbo_texture;
}
After posting the question is recognized that I did not enable texture using
the following command:
glEnable ( GL_TEXTURE_2D )
This fix the problem. I hope this code benefits others.