I ran the framebuffers example in this page -original code- (using glfw3 and glew in xcode 4.6 in osx 10.8), it worked fine, then I wanted to add multisampling (to avoid jagged edges on cube edges and on the floor, glfwWindowHint (GLFW_SAMPLES, 4) was enough when rendering directly to the back-buffer), found some answers directing to opengl.org, tried to use glTexImage2DMultisample but it displayed nothing (black screen). The framebuffer settings and rendering loop is:
// Create frame buffer
GLuint frameBuffer;
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
// Create texture to hold color buffer
GLuint texColorBuffer;
glGenTextures(1, &texColorBuffer);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texColorBuffer);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB, width, height, GL_FALSE);
/*
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
*/
//glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColorBuffer, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texColorBuffer, 0);
// Create Renderbuffer Object to hold depth and stencil buffers
GLuint rboDepthStencil;
glGenRenderbuffers(1, &rboDepthStencil);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepthStencil);
//glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glRenderbufferStorageMultisample (GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rboDepthStencil);
// ...
while (!window->shouldClose()) {
static int rot = 0;
// Bind our framebuffer and draw 3D scene (spinning cube)
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
auto err_res = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(err_res != GL_FRAMEBUFFER_COMPLETE) {
ERR("Incomplete frameBuffer:%X!", err_res);
goto end;
}
glBindVertexArray(vaoCube);
glEnable(GL_DEPTH_TEST);
glUseProgram(sceneShaderProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texKitten);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texPuppy);
// Clear the screen to white
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj));
// Draw cube
glEnable(GL_MULTISAMPLE);
glDrawArrays(GL_TRIANGLES, 0, 36);
glEnable(GL_STENCIL_TEST);
// Draw floor
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0xFF);
glDepthMask(GL_FALSE);
glClear(GL_STENCIL_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 36, 6);
// Draw cube reflection
glStencilFunc(GL_EQUAL, 1, 0xFF);
glStencilMask(0x00);
glDepthMask(GL_TRUE);
model = glm::scale(glm::translate(model, glm::vec3(0, 0, -1)), glm::vec3(1, 1, -1));
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));
glUniform3f(uniColor, 0.3f, 0.3f, 0.3f);
glDrawArrays(GL_TRIANGLES, 0, 36);
glUniform3f(uniColor, 1.0f, 1.0f, 1.0f);
glDisable(GL_STENCIL_TEST);
/*
// Bind default framebuffer and draw contents of our framebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
glBindVertexArray(vaoQuad);
glDisable(GL_DEPTH_TEST);
glUseProgram(screenShaderProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texColorBuffer);
glDrawArrays(GL_TRIANGLES, 0, 6);
*/
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // Make sure no FBO is set as the draw framebuffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBuffer); // Make sure your multisampled FBO is the read framebuffer
glDrawBuffer(GL_BACK); // Set the back buffer as the draw buffer
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
// Swap buffers
glfwSwapBuffers(window->getHandle());
glfwPollEvents();
}
glVersion: 3.2 NVIDIA-8.10.44 304.10.65f03
glRenderer: NVIDIA GeForce 9400M OpenGL Engine
The 'EXT' additions are probably unnecessary but I also tried to run without them before and the result was the same. What am I doing wrong?
EDIT: Now binding GL_TEXTURE_2D_MULTISAMPLE and getting GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE error!
If you checked your framebuffer object for completeness, you would probably have caught this by now... your depth/stencil buffer needs to be multisampled as well.
A framebuffer is considered multisample incomplete by both core and the EXT FBO extension if one attachment has a different number of samples than any other attachment. In your case, you have a color buffer attachment with 4 samples and a depth/stencil attachment with 1 sample.
Name
glCheckFramebufferStatus — check the completeness status of a framebuffer
Description
glCheckFramebufferStatus queries the completeness status of the framebuffer object currently bound to target. target must be GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER. GL_FRAMEBUFFER is equivalent to GL_DRAW_FRAMEBUFFER.
The return value is GL_FRAMEBUFFER_COMPLETE if the framebuffer bound to target is complete. Otherwise, the return value is determined as follows:
[...]
GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE is returned if the value of GL_RENDERBUFFER_SAMPLES is not the same for all attached renderbuffers; if the value of GL_TEXTURE_SAMPLES is the not same for all attached textures; or, if the attached images are a mix of renderbuffers and textures, the value of GL_RENDERBUFFER_SAMPLES does not match the value of GL_TEXTURE_SAMPLES.
To fix this, you need to allocate a multisampled depth/stencil attachment with 4 samples:
glRenderbufferStorageMultisample (GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, width, height);
By the way, since your implementation is >= 3.0, you do not need the EXT suffix on anything. All of the constants defined by the EXT extension are identical to ARB / core FBOs, but some of the EXT functions (such as glCheckFramebufferStatusEXT) have more restrictive behavior (requiring each attachment to have the same image dimensions, for instance).
Related
I have three different framebuffer objects for three different steps:
GLuint fbo1; // Step1: draw initial scene
GLuint fbo2; // Step2: apply lens effect shader
GLuint fbo3; // Step3: final smoothing
I want to draw my initial scene as a texture attached to fbo1.
Then apply a lens-shader on that and save it as a texture in fbo2.
Then apply a smoothing-shader on fbo2 and save it to fbo3.
The code in my main render function, uses a few helper functions, and is as follows:
// Step1
useFrameBuffer(fbo1, fbo1); // src , dest
DrawInitialScene();
// Step2
LensShader.use(); // a glsl shader program class
useFrameBuffer(fbo1, fbo2); // src , dest
drawQuadOnFbo(fbo2Texture);
// Step3
SmoothingShader.use(); // a glsl shader program class
useFrameBuffer(fbo2, fbo3); // src , dest
drawQuadOnFbo(fbo3Texture);
// Final Copy Step to OpenGL default FBO
int width = self.frame.size.width;
int height = self.frame.size.height;
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo3);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); //destination
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
The helper function useFrameBuffer(src, dest), simply sets the source framebuffer to read from and destination write framebuffer:
void useFrameBuffer (GLuint fboSrc , GLuint fboDest)
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboSrc);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboDest);
GLenum drawbufs[] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, drawbufs);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glViewport(0, 0, width, height); // width, height are private to class
}
To apply the shader on the output of fbo1 and fbo2, I am drawing a quad with a texture associated to the respective frame-buffers:
void drawQuadOnFbo(GLuint fboTexture) {
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // We're not using stencil buffer now
glBlendFunc(GL_ONE, GL_ONE);
glBindVertexArray(quadVAO);
glDisable(GL_DEPTH_TEST);
glBindTexture(GL_TEXTURE_2D, fboTexture);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
The Problem:
The problem is that output appears to be a combination of Step1 and Step3 only. Looks like the Step2 is completely missed out. You can see in the final copy step, I am copying the contents of fbo3 to the final OpenGL default fbo using:
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo3);
If I change this to fbo2, then I do see the results of applying Step2 (but then I don't have Step3).
So it looks like that both fbo2 and fbo3 are connected directly to the output of fbo1, but not connected to each other.
How can I fix that ??
Other Helper Functions:
I initialised my Framebuffers at the start of the application, outside the main render function using the method below:
GLuint initFrameBuffer( int width, int height, GLenum textureTarget) {
// 1. Create FBO
GLuint fbo;
glGenFramebuffers(1, &fbo);
// 2. Bind it
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// FrameBuffer Requirements
// (i). atleast 1 buffer (color, depth, stencil)
// (ii). atleast 1 color-attachment
// (iii). all attachments should be complete
// (iv). same no. of samples for each buffer
// 3. Texture Attachment
GLuint quadTex; // texture to be associated to this FBO
glActiveTexture(textureTarget);
glGenTextures(1, &quadTex);
glBindTexture(GL_TEXTURE_2D, quadTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// attach it as COLOR-ATTACHMENT 0
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, quadTex, 0);
// 4. RenderBuffer attachement
GLuint rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// attach it
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
// 5. Set Targets for fragment shader output
GLenum drawbufs[] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, drawbufs);
// 6. Check that the FrameBuffer is complete
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
NSLog(#"ERROR::FRAMEBUFFER:: Framebuffer is not complete!");
return fboObj;
}
// 7. revert to Default
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return fbo;
}
I need a fresh pair of eyes. While working on rewriting my engine, I stumbled upon this issue while writing the Deferred Rendering path. The framebuffer displays only if I don't use a depth attachment, which means that the rendering is faulty, but if I do, all the outputs are blank. I wrote a lot of graphics handling classes but I broke down the code here:
Initialization:
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
glClearColor(0, 0, 0, 1);
glViewport(0, 0, 1024, 768);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ShaderPreparation();
numBuffer = 3;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
numBuffers = numBuffer;
targetBuffer = 0;
textures = new unsigned int[numBuffers];
glGenTextures(numBuffers, textures);
This is done three times:
glBindTexture(GL_TEXTURE_2D, textures[targetBuffer]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, colorType, width, height, 0, colorFormat, colorDataType, NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + targetBuffer, GL_TEXTURE_2D, textures[targetBuffer], 0);
targetBuffer++;
Then I create the Depth Attachment:
glGenTextures(1, &renderBuffer);
glBindTexture(GL_TEXTURE_2D, renderBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, renderBuffer, 0);
EDIT 2: Forgot the last bit of the FBO:
GLenum *DrawBuffers = new GLenum[numBuffers];
for (size_t i = 0; i < numBuffers; i++)
DrawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
glDrawBuffers(numBuffers, DrawBuffers);
// Report errors
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "Framebuffer Error. Status 0x%x\n", status);
}
// Unbind
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
Finally, my drawing (all calculations for geometry shader happens before this):
geometryShader->Use();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
graphicsWrapper->render(Geometry);
int val[3] = { 0,1,2 };
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
deferredShader->Use();
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, textures[2]);
// I use this system so it's compatible with Uniform Buffer
// Objects and the rendering code of other graphics languages
deferredShader->PassData(&val);
deferredShader->SetInteger();
deferredShader->SetInteger();
deferredShader->SetInteger();
glClear(GL_COLOR_BUFFER_BIT);
vaoQuad->Bind();
graphicsWrapper->DrawVertexArray(4);
vaoQuad->Unbind();
Note that my code is much more object oriented than this, and I had to take a lot of this code out of context. My question is, why does attaching the depth attachment to the framebuffer cause the framebuffer to blank, while removing it works, and how do I fix it?
EDIT: I know that it's not a renderbuffer, I just called the depth texture that because it USED to be a renderbuffer, and I forgot to change the name.
When you don't have a depth buffer, every fragment will automatically pass the depth test. Now after you add a depth buffer, the depth test will be effective (assuming you enabled it). However, yo forgot to clear your depth buffer:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
You clear the default framebuffer's color and depth buffer (or another FBO, it that is bound at that time), but not the depth buffer of fbo here...
There is a high chance that you depth texture is initially all zeros. With default depth conventions, that means it is already the nearest value, so the depth test will likely fail for anything you draw.
I have code which is the equivalent of the following:
init code:
glCullFace(GL_FRONT_AND_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
//clear to pink
glClearColor(1.0f, 0.0f, 1.0f, 0.0f);
GLuint textureObject;
glGenTextures(1, &textureObject);
glBindTexture(GL_TEXTURE_2D, textureObject);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA,
GL_UNSIGNED_BTYE, NULL);
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
textureObject, 0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
assert(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)
== GL_FRAMEBUFFER_COMPLETE);
Object obj = CreateAFullscreenQuad(textureObject);
draw code:
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
glViewport(0, 0, 512, 512);
//clear to cyan
GLfloat clear[] = {0, 1, 1, 1};
glClearBufferfv(GL_COLOR, 0, clear);
SetUpPerspectiveAndCameraMatrix();
DrawSomeStuff();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glViewport(0, 0, window.width, window.height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SetUpPerspectiveAndCameraMatrix();
obj.Draw();
SwapBuffers();
glxinfo excerpt:
OpenGL vendor string: VMware, Inc.
OpenGL renderer string: Gallium 0.4 on llvmpipe (LLVM 3.4, 128 bits)
OpenGL version string: 2.1 Mesa 10.1.3
The problem is that the call to glClearBufferfv doesn't seem to clear the whole buffer. As you can see, it clears the triangular shape, but it doesn't touch the other areas. They are also not the glClearColor color (pink). If I use the regular glClear call, it does the same thing, but pink instead of cyan.
Turns out I created a feedback loop by drawing the fullscreen quad while the FBO was bound, drawing the contents of the buffer to itself. Apparently the effects of this end up being interspersed with the effects of glClear.
I am currently working on a application with (not yet implemented) post effects. So the 3D scene gets rendered in a buffer and then, another shader renders the buffer on the screen.
My problem is that the program uses my basic shader vor the 3d scene instead of the post effect shader in the second pass. Do you have an idea, what could be doing this?
My approach: I have a class which has two major functions:
- bindBuffer() sets the render Target to a buffer
- renderSSAO() renders the buffer to the screen and hopfuly one day will add an ambient occlusion effect. :)
BIND BUFFER FUNCTION
void SSAOShader::bindBuffer() {
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glViewport(0,0,windowWidth,windowHeight);
}
RENDER FUNCTION
void SSAOShader::renderSSAO(GLuint currentShader) {
// set shader
glUseProgram(shader);
//draw on Screen
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0,0,windowWidth,windowHeight);
// clear screen
glClearColor(0.4, 0.4, 0.4, 1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// bind texture, pass to shader
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, renderTexture);
glUniform1i(textureID, 0);
glBindVertexArray(vertexarray);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glUseProgram(currentShader);
}
Render Loop (the functions are from the ssaoShader-object)
while (!glfwWindowShouldClose(mainWindow)) {
ssaoShader->bindBuffer();
// clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw cool stuff
ssaoShader->renderSSAO(programID);
// Swap buffers
glfwSwapBuffers(mainWindow);
glUseProgram(programID);
}
So basically, the render target gets set to my buffer with bindBuffer();, then I draw objects with my basic (phong etc) shader, and the renderSSAO function changes the target to my screen. This function also changes the shader to my post-effects shader and changes it back to whatever it was before. programID is the shader-GLuint.
I know that the problem is the used shader since the result of all is that I only have a black screen with a quad-gon in the world origin. I can also move around like normal.
CONSTRUCTOR
SSAOShader::SSAOShader(float windowWidth, float windowHeight, GLuint currentShader) {
this->windowWidth = windowWidth;
this->windowHeight = windowHeight;
//shader
shader = LoadShaders("Passthrough.vertexshader", "SSAO.fragmentshader");
glUseProgram(shader);
textureID = glGetUniformLocation(shader, "renderTexture");
int status;
glGetProgramiv(shader, GL_COMPILE_STATUS, &status);
std::cout << (status == GL_TRUE) << std::endl;
GLfloat planeVertices[] = {
-1, -1,
1, -1,
-1, 1,
1, 1
};
// create vertex array
glGenVertexArrays(1, &vertexarray);
glBindVertexArray(vertexarray);
// create "uv" (vertex) buffer
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW);
// add vertecies to as attributes
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindVertexArray(0);
// ---- set up framebuffer ----
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glGenTextures(1, &renderTexture);
glBindTexture(GL_TEXTURE_2D, renderTexture);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, windowWidth, windowHeight, 0,GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenRenderbuffers(1, &depthrenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, windowWidth, windowHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderTexture, 0);
DrawBuffers[1] = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, DrawBuffers);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
exit(0); // bad luck
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//glUseProgram(currentShader);
}
VS2012 Project
https://studi.f4.htw-berlin.de/~s0539750/SSAOTest.zip
For who ever is mad enough to look at my code. ;)
I found the problem.
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderTexture, 0);
DrawBuffers[1] = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, DrawBuffers);
This part in the constructor changed my GLuint shader;. I don't know why exactly but the reason was that DrawBuffers is a fixed array with size 1. Obviously, accessing DrawBuffers[1] isn't the best idea of the day. ;)
My guess would be that either DarBuffers[1] was used for my "shader" GLuint or the problem was that glDrawBuffers never realy attached GL_COLOR_ATTACHMENT0 to my framebuffer. What is the case?
Thanks for all the help by the way, It helped alot. :)
This is the lovely image I keep seeing gDebugger as I attempt to implement shadow maps. For reference I'm using the tutorial at http://fabiensanglard.net/shadowmapping/index.php. I've tried a couple different things with varying results, mostly either an FBO that has flat depth values(no slight variance indicating weird depth ranges) or this awesome guy. I've tried a huge amount of different things but alas, sans complete FBO failure, I mostly come back to this. For reference, here is what gDebugger spits out as my actual depth buffer:
So, with all that in mind, here's my code. Shader code is withheld because I have yet to get something in my FBO that's worth processing.
Here's how I initialize the FBO/Depth tex:
int shadow_width = 1024;
int shadow_height = 1024;
// Try to use a texture depth component
glGenTextures(1, &depth_tex);
glBindTexture(GL_TEXTURE_2D, depth_tex);
// GL_LINEAR does not make sense for depth texture. However, next tutorial shows usage of GL_LINEAR and PCF
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Remove artefact on the edges of the shadowmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
// No need to force GL_DEPTH_COMPONENT24, drivers usually give you the max precision if available
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24,
shadow_width, shadow_height, 0, GL_DEPTH_COMPONENT,
GL_FLOAT, 0);
// attach the texture to FBO depth attachment point
glBindTexture(GL_TEXTURE_2D, 0);
// create a framebuffer object
glGenFramebuffers(1, &fbo_id);
glBindFramebuffer(GL_FRAMEBUFFER, fbo_id);
// Instruct openGL that we won't bind a color texture with the currently binded FBO
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D, depth_tex, 0);
// switch back to window-system-provided framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
And here's my render code:
glLoadIdentity();
float lpos[4] = {0,0,0,1};
float lpos3[4] = {5000,-500,5000,1};
glBindTexture(GL_TEXTURE_2D,0);
glBindFramebuffer(GL_FRAMEBUFFER,fbo_id);
glViewport(0, 0, 1024, 1024);
glClear(GL_DEPTH_BUFFER_BIT);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
setup_mats(lpos[0],lpos[1],lpos[2],lpos3[0],lpos3[1],lpos3[2]);
glCullFace(GL_FRONT);
mdlman.render_models(R_STENCIL);
mdlman.render_model(R_STENCIL,1);
set_tex_mat();
glBindFramebuffer(GL_FRAMEBUFFER,0);
glViewport( 0, 0, (GLsizei)800, (GLsizei)600 );
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
this->r_cam->return_LookAt();
gluPerspective(45,800/600,0.5f,2000.0f);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(&r_cam->getProjectionMatrix()[0][0]);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(&r_cam->getViewMatrix()[0][0]);
glCullFace(GL_BACK);
mdlman.render_models(R_NORM);
And here's how I draw objects for the FBO:
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER,models.at(mdlid).t_buff);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,models.at(mdlid).i_buff);
glNormalPointer(GL_FLOAT,sizeof(vert),BUFFER_OFFSET(sizeof(GLfloat)*2));
glVertexPointer(3, GL_FLOAT,sizeof(vert),BUFFER_OFFSET(sizeof(GLfloat)*5));
glDrawElements(GL_TRIANGLES,(models.at(mdlid).f_index.size())*3,GL_UNSIGNED_INT,0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
Some closing notes: the depth buffer image from gDebugger IS from the lights POV. My camera is quaternion based and uses matrices aligned with OGL for it's lookAt function(which is used to translate to light position/view.) I can provide the code for that if need be. Everything else is pretty much carbon-copied from the tutorial to make sure that I'm not doing or setting up something stupid.