I'm attempting to have SSAA featured in my scene. Previously, I have setup the entire scene as an FBO, and it works fine (it renders perfectly on my screen). However as soon as I try to apply SSAA to it, the screen is always black, and I'm unsure why. I've followed a tutorial based on iOS but was fairly simple to copy to windows which can be found here
However as I said when trying a similar technique to that it doesnt work. I understand the theory/concept of SSAA but cannot seem to get it to work. Any help I'd really appreciate it as I can't find much material on it (it is mostly on MSAA or other A.A. techniques)
FBO Initialization
void InitSSAAFBO()
{
// Create the on-screen FBO.
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER,
fboColTex);
glGenRenderbuffers(1, &bigColour);
glBindRenderbuffer(GL_RENDERBUFFER, bigColour);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8,
windowWidth * supersamplingLevel, windowHeight * supersamplingLevel);
glGenRenderbuffers(1, &bigDepth);
glBindRenderbuffer(GL_RENDERBUFFER, bigDepth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24,
windowWidth * supersamplingLevel, windowHeight * supersamplingLevel);
glGenFramebuffers(1, &fboBig);
glBindFramebuffer(GL_FRAMEBUFFER, fboBig);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER,
bigColour);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER,
bigDepth);
// Create a texture object and associate it with the big FBO.
glGenTextures(1, &offscreenTexture);
glBindTexture(GL_TEXTURE_2D, offscreenTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_RGBA, windowWidth * supersamplingLevel, windowHeight * supersamplingLevel, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, offscreenTexture, 0);
GLenum demoFBOStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (demoFBOStatus != GL_FRAMEBUFFER_COMPLETE) {
fboOkay = false;
cout << "Could not successfully create framebuffer object to render texture!" << endl;
}
else {
fboOkay = true;
cout << "FBO successfully created" << endl;
}
// Unbind FBO for now! (Plug main framebuffer back in as rendering destination)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
Rendering
void display(void) {
//Bind Large FBO
glBindFramebuffer(GL_FRAMEBUFFER, fboBig);
glBindRenderbuffer(GL_RENDERBUFFER, bigColour);
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, windowWidth * supersamplingLevel, windowHeight * supersamplingLevel);
glEnable(GL_DEPTH_TEST);
DrawScene();
//Bind small/Onscreen FBO
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glBindRenderbuffer(GL_RENDERBUFFER, fboColTex);
glViewport(0, 0, windowWidth, windowHeight);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glUseProgram(fboShader);
glBindVertexArray(quadVAO);
glBindTexture(GL_TEXTURE_2D, offscreenTexture);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
glutSwapBuffers();
}
fboShader (Vertex Shader)
#version 330 core
layout (location = 0) in vec2 position;
layout (location = 1) in vec2 texCoords;
out vec2 TexCoords;
void main()
{
gl_Position = vec4(position.x, position.y, 0.0f, 1.0f);
TexCoords = texCoords;
}
fboShader (Fragment Shader)
#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D screenTexture;
void main()
{
color = texture(screenTexture, TexCoords);
}
Related
I'm trying to render to two different textures (GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1) inside my MSAA FBO, the initialization is:
// configure MSAA framebuffer
// --------------------------
glGenFramebuffers(1, &this->_MSAAid);
glBindFramebuffer(GL_FRAMEBUFFER, this->_MSAAid);
// create a multi-sampled color attachment texture
glGenTextures(1, &this->_textureMultisampleID);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, this->_textureMultisampleID);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB16F, _frameBufferSize.width, _frameBufferSize.height, GL_TRUE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, this->_textureMultisampleID, 0);
glGenTextures(1, &this->_textureObjectIDMultisampled);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, this->_textureObjectIDMultisampled);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB16F, _frameBufferSize.width, _frameBufferSize.height, GL_TRUE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, this->_textureObjectIDMultisampled, 0);
GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, drawBuffers);
// create an (also multi-sampled) render buffer object for depth and stencil attachments
glGenRenderbuffers(1, &this->_renderBufferObjectID);
glBindRenderbuffer(GL_RENDERBUFFER, this->_renderBufferObjectID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, _frameBufferSize.width, _frameBufferSize.height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, this->_renderBufferObjectID);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "ERROR::FRAMEBUFFER:: MSAA Framebuffer is not complete! Error: " << glCheckFramebufferStatus(GL_FRAMEBUFFER) << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
_frameBufferShader->use();
_frameBufferShader->setInt("screenTexture", 0);
then I want to copy the result inside another standard FBO, initialized like that:
// framebuffer configuration
// -------------------------
glGenFramebuffers(1, &this->_id);
glBindFramebuffer(GL_FRAMEBUFFER, this->_id);
// create a color attachment texture
glGenTextures(1, &this->_textureID);
glBindTexture(GL_TEXTURE_2D, this->_textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, _frameBufferSize.width, _frameBufferSize.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);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->_textureID, 0);
glGenTextures(1, &this->_textureObjectID);
glBindTexture(GL_TEXTURE_2D, this->_textureObjectID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, _frameBufferSize.width, _frameBufferSize.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);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, this->_textureObjectID, 0);
GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, drawBuffers);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
_frameBufferShader->use();
_frameBufferShader->setInt("screenTexture", 0);
FBO binding:
glBindFramebuffer(GL_FRAMEBUFFER, this->_MSAAid);
glViewport(0, 0, this->_frameBufferSize.width, this->_frameBufferSize.height);
glEnable(GL_DEPTH_TEST); // enable depth testing (is disabled for rendering screen-space quad)
glClearColor(refreshColor.coordinates.x, refreshColor.coordinates.y, refreshColor.coordinates.z, refreshColor.coordinates.w);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Rendering stuff...
After the rendering, I want to copy both the buffers to my normal FBO:
glBindFramebuffer(GL_READ_FRAMEBUFFER, this->_MSAAid);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, this->_id);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glBlitFramebuffer(0, 0, _frameBufferSize.width, _frameBufferSize.height, 0, 0, _frameBufferSize.width, _frameBufferSize.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, this->_MSAAid);
glReadBuffer(GL_COLOR_ATTACHMENT1);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, this->_id);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glBlitFramebuffer(0, 0, _frameBufferSize.width, _frameBufferSize.height, 0, 0, _frameBufferSize.width, _frameBufferSize.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
but for some reason what I get is that in both textures (GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1) the same content is written, basically, the two textures are the same, even if in my shader code I output the result into two different color attachments, here you can see my fragment shader:
#version 330 core
layout (location = 0) out vec4 fragColor;
layout (location = 1) out vec4 idColor;
in vec2 Frag_UV;
uniform sampler2D screenTexture;
void main()
{
float gamma = 2.2;
float exposure = 1.0;
vec4 color = texture(screenTexture, Frag_UV.st);
// HDR tonemapping
color.rgb = vec3(1.0) - exp(-color.rgb * exposure);
// gamma correction
color.rgb = pow(color.rgb, vec3(1.0 / gamma));
fragColor = vec4(color.rgb, 1.0);
idColor = vec4(0, 1, 0, 1.0);
}
here is the output:
What I wish to obtain in the Scene window is to display the texture with the color attachment 0 and in the Game window the texture with the color attachment 1!
Currently these two windows shows:
Scene Window: textureObjectID -> GL_COLOR_ATTACHMENT1
Game Window: textureID -> GL_COLOR_ATTACHMENT0
The result I want is to render a different texture based on the GL_COLOR_ATTACHMENT
also, I tried to debug everything with a glReadPixel(...) for attachment 0 and for attachment 1, and what I got is actually the same value of pixel for both textures:
This is the code I used for debugging:
glBindFramebuffer(GL_READ_FRAMEBUFFER, this->sceneFrameBuffer->ID);
glReadBuffer(GL_COLOR_ATTACHMENT0);
float pixelColor[4];
glReadPixels(Input::mouse.xPosition, Input::mouse.yPosition, 1, 1, GL_RGBA, GL_FLOAT, &pixelColor);
std::cout << "Pixel Color0: ( " << pixelColor[0] << ", " << pixelColor[1] << ", " << pixelColor[2] << ", " << pixelColor[3] << " )" << std::endl;
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, this->sceneFrameBuffer->ID);
glReadBuffer(GL_COLOR_ATTACHMENT1);
float pixelColors[4];
glReadPixels(Input::mouse.xPosition, Input::mouse.yPosition, 1, 1, GL_RGBA, GL_FLOAT, &pixelColors);
std::cout << "Pixel Color1: ( " << pixelColors[0] << ", " << pixelColors[1] << ", " << pixelColors[2] << ", " << pixelColors[3] << " )" << std::endl;
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
what am I missing? can't figure it out!
(I'm using Dear ImGui in order to display textures in the windows)
In order to give the idea of what I want to achieve, I found a video that does implement the idea I wish to implement.
I have two frame buffers, both are used for the rendering of the scene and not of the screen (as I was mistakenly thinking), so I had to specify the color attachment output inside the shader that I use for the rendering of the objects and not the shader I'm using for the rendering of the scene over my quad (the "screen quad").
Screen Fragment Shader:
#version 450 core
layout (location = 0) out vec4 fragColor;
in vec2 Frag_UV;
uniform sampler2D screenTexture;
void main()
{
float gamma = 2.2;
float exposure = 1.0;
vec4 color = texture(screenTexture, Frag_UV.st);
// HDR tonemapping
color.rgb = vec3(1.0) - exp(-color.rgb * exposure);
// gamma correction
color.rgb = pow(color.rgb, vec3(1.0 / gamma));
fragColor = vec4(color.rgb, 1.0);
}
Phong Fragment Shader that I'm using for the rendering of the Objects:
#version 450 core
layout (location = 0) out vec4 FragColor;
layout (location = 1) out vec4 idColor;
//Declaring stuff...
void main()
{
vec3 viewDir = normalize(viewPos - fs_in.FragPos);
vec3 result = vec3(0.0, 0.0, 0.0);
result += calcPointLight(material, pointLight, viewDir);
idColor = vec4(vID);
FragColor = vec4(result, 1.0);
}
Now I got everything rendered to my GL_COLOR_ATTACHMENT1, thanks to everyone who commented!
following scenario:
i'm creating an OpenGL texture and a framebuffer and associated objects
GLuint frameBuffer = 0, colorBuffer, depthBuffer;
glGenFramebuffers(1, &frameBuffer);
int maskRenderingWidth = 1 * settings.width, maskRenderingHeight = 1 * settings.height;
//define texture
glUseProgram(screenMaskRenderingProgramId);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, maskRenderingWidth, maskRenderingHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(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);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glUseProgram(offscreeenMaskRenderingProgramId);
//setup framebuffer stuff
glGenRenderbuffers(1, &colorBuffer);
glGenRenderbuffers(1, &depthBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, maskRenderingWidth, maskRenderingHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, maskRenderingWidth, maskRenderingHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, DrawBuffers);
I then render a polygon to that framebuffer which i put into a texture. Afterwards I draw another polygon but this time to the screen buffer. Finally I span a quad on the whole screen and pass the uv coords (0,0), (0,1), (1,1) and (1,0) and the previously created texture to it.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(textureLocation,0);
What i want to achieve is, if that texture has at some texture coords certain values i want to draw the corresponding texture values, otherwise i want the output on coord (u,v) to be
untouched.
if(textureProj(mask, uv_coords).a == 1) {
gl_FragColor = textureProj(mask, uv_coords);
}
After some trying i figured out that always everything from the texture is drawn. It seems my texture is somehow corrupt as isinf and isnan return true for textureProj(mask, uv_coords) for every uv_coord. How could that be possible and someone has an idea what might be broken here?
in vec4 uv_coords;
uniform sampler2D mask;
void main() {
vec4 c = textureProj(mask, uv_coords);
bvec4 inf = isinf(c);
if(inf.r == true && inf.g == true && inf.b == true && inf.a == true) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
});
This yields a completely white screen. Same applies for
inf = isnan(c)
Anyone has an idea whats going on here?
EDIT:
I forgot to mention that if I leave out the if clause in the fragment shader and just do
in vec4 uv_coords;
uniform sampler2D mask;
void main() {
vec4 c = textureProj(mask, uv_coords);
gl_FragColor = c; });
the texture is drawn properly. Makes it even more strange.
EDIT2:
ok, i've read that not setting gl_FragColor gives undefined behavior. so my approach will be to upload the two textures to that specific fragment shader and render everything in one pass
There's some Artifacts on my FrameBuffer Depth Texture I can't get rid off:
The Code used to init the FrameBuffer:
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenTextures(1, &color);
glBindTexture(GL_TEXTURE_2D, color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenTextures(1, &depth);
glBindTexture(GL_TEXTURE_2D, depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, color, 0);
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, depth, 0);
GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
glDrawBuffers(2, attachments);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
std::cout << "FBO FEHLER" << std::endl;
}
Code used to draw the FrameBuffer:
shader->bind();
// Bind Textures
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, color);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depth);
glUniform1i(shader->getUniform("tex"), 0);
glUniform1i(shader->getUniform("depth"), 1);
glUniformMatrix4fv(shader->getUniform("matrix"), 1, GL_FALSE, glm::value_ptr(ortho));
// Draw Call
glBindBuffer(GL_ARRAY_BUFFER,fbovbo);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 20, (void*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 20, (void*)12);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Unbind
shader->unbind();//*/
FragmentShader of the actual rendering:
#version 330 core
layout(location = 0) out vec4 out_color;
layout(location = 1) out vec4 out_depth;
in float temp;
void main(void){
out_color = vec4(1,0.0,0.0,1.0);
out_depth = vec4(gl_FragCoord.z);
}
FragmentShader of the FrameBuffer rendering:
#version 330 core
in vec2 fuv;
out vec4 color;
uniform sampler2D tex;
uniform sampler2D depth;
void main(){
vec4 d = texture2D(depth, fuv);
gl_FragDepth = d.a;
vec4 c = texture2D(tex,fuv);
if(c.a<0.1){
discard;
}
color = c;
//color = vec4(texture2D(depth, fuv).zzz,1.0);
//color.a = 0.8;
//color = vec4(1,0,0,0.5);
}
The red "Mesh" is behind the brown surface, but its borders still appear. thats the problem
The problem might come from the limited precision of the depth buffer. Basically, the range between near and farplane has to be represented by the depth-buffer. In your case, the depth-buffer has 8 bit, thus there are only 256 different depth values that can be represented. When two objects are closer together than this, they will be mapped to the same value in the depth buffer.
To overcome this, you can try to increase the precision of the depth buffer, for example, by using
glGenTextures(1, &depth);
glBindTexture(GL_TEXTURE_2D, depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_SHORT, NULL);
Side-note: I'm not sure why the depth texture has four channels. If you don't need them, I would change this to a one channel format.
I'm currently working in a deferred shading and I created a class which manages the FBOs and draw the buffers on the screen.
This is how it looks so far:
FBORender::FBORender(float screenWidth, float screenHeight) :
_screenWidth(screenWidth),
_screenHeight(screenHeight),
ProgramManager("defVertexShader.txt", "defFragShader.txt")
{
CreateProgram();
_vbo[0] = 0;
_vbo[1] = 0;
_vao = 0;
BuildQuad();
BuildVAO();
glGenFramebuffers(1, &_fbo);
glGenRenderbuffers(1, &_depthBuffer);
// Bind the depth buffer
glBindRenderbuffer(GL_RENDERBUFFER, _depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, (int)_screenWidth, (int)_screenHeight);
// Generate and bind the texture for diffuse
glGenTextures(1, &_diffuseBuffer);
glBindTexture(GL_TEXTURE_2D, _diffuseBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)_screenWidth, (int)_screenWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
// Generate and bind the texture for positions
glGenTextures(1, &_positionBuffer);
glBindTexture(GL_TEXTURE_2D, _positionBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, (int)_screenWidth, (int)_screenWidth, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
// Generate and bind the texture for normals
glGenTextures(1, &_normalBuffer);
glBindTexture(GL_TEXTURE_2D, _normalBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (int)_screenWidth, (int)_screenWidth, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
// Bind the FBO so that the next operations will be bound to it.
glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);
// Attach the textures to the FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _diffuseBuffer, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, _positionBuffer, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, _normalBuffer, 0);
GLenum fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (fboStatus != GL_FRAMEBUFFER_COMPLETE)
{
printf("DeferredLighting::Init: FrameBuffer incomplete: 0x%x\n", fboStatus);
exit(1);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
FBORender::~FBORender()
{
glDeleteTextures(1, &_normalBuffer);
glDeleteTextures(1, &_positionBuffer);
glDeleteTextures(1, &_diffuseBuffer);
glDeleteFramebuffers(1, &_fbo);
glDeleteVertexArrays(1, &_vao);
glDeleteBuffers(2, _vbo);
}
void FBORender::Start()
{
// Bind the FBO and set the viewport to the proper size
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo);
glViewport(0, 0, (int)_screenWidth, (int)_screenWidth);
// Clear the render targets
GLenum windowBuffClear[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, windowBuffClear);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLenum windowBuffOpaque[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, windowBuffOpaque);
}
void FBORender::Draw(const glm::mat4 &Projection, const glm::mat4 &ModelView)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_ModelViewProjection = Projection * ModelView;
_ModelView = ModelView;
glDisable(GL_DEPTH_TEST);
Bind();
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, _normalBuffer);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _positionBuffer);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _diffuseBuffer);
glBindVertexArray(_vao);
LoadUniformVariables();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
UnBind();
}
void FBORender::Stop()
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
void FBORender::BuildQuad()
{
_coordinates[0] = 1.0f;
_coordinates[1] = 1.0f;
_coordinates[2] = 0.0f;
_coordinates[3] = -1.0f;
_coordinates[4] = 1.0f;
_coordinates[5] = 0.0f;
_coordinates[6] = 1.0;
_coordinates[7] = -1.0f;
_coordinates[8] = 0.0f;
_coordinates[9] = -1.0f;
_coordinates[10] = -1.0f;
_coordinates[11] = 0.0f;
_uv[0] = 1.0f;
_uv[1] = 1.0f;
_uv[2] = 0.0f;
_uv[3] = 1.0f;
_uv[4] = 1.0f;
_uv[5] = 0.0f;
_uv[6] = 0.0f;
_uv[7] = 0.0f;
}
void FBORender::BuildVAO()
{
// Generate and bind the vertex array object
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
// Generate and bind the vertex buffer object
glGenBuffers(2, _vbo);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[0]);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), _coordinates, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[1]);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), _uv, GL_STATIC_DRAW);
LoadAttributeVariables();
glBindVertexArray(0);
}
void FBORender::LoadUniformVariables()
{
// OpenGL Matrices
GLuint ModelViewProjection_location = glGetUniformLocation(GetProgramID(), "mvMatrix");
glUniformMatrix4fv(ModelViewProjection_location, 1, GL_FALSE, glm::value_ptr(_ModelView));
// Texture buffers
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _diffuseBuffer);
GLint Diffuse_location = glGetUniformLocation(GetProgramID(), "tDiffuse");
glUniform1i(Diffuse_location, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _positionBuffer);
GLint Position_location = glGetUniformLocation(GetProgramID(), "tPosition");
glUniform1i(Position_location, 0);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, _normalBuffer);
GLint Normal_location = glGetUniformLocation(GetProgramID(), "tNormals");
glUniform1i(Normal_location, 0);
}
void FBORender::LoadAttributeVariables()
{
// Vertex Attributes
GLuint VertexPosition_location = glGetAttribLocation(GetProgramID(), "vPosition");
glEnableVertexAttribArray(VertexPosition_location);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[0]);
glVertexAttribPointer(VertexPosition_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
GLuint TextureCoord_Location = glGetAttribLocation(GetProgramID(), "uvCoord");
printf("%d \n", TextureCoord_Location);
glEnableVertexAttribArray(TextureCoord_Location);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[1]);
glVertexAttribPointer(TextureCoord_Location, 2, GL_FLOAT, GL_FALSE, 0, 0);
}
And those are my shaders:
#version 410 core
uniform mat4 mvMatrix;
in vec4 vPosition;
in vec2 uvCoord;
smooth out vec2 texCoord;
void main(void)
{
texCoord = uvCoord;
gl_Position = vPosition * mvMatrix;
}
#version 410 core
uniform sampler2D tDiffuse;
uniform sampler2D tPosition;
uniform sampler2D tNormals;
in vec2 texCoord;
out vec4 fragColor;
void main( void )
{
vec4 image = texture( tDiffuse, texCoord.st );
vec4 position = texture( tPosition, texCoord.st );
vec4 normal = texture( tNormals, texCoord.st );
fragColor.xyz = vec3(0.5f, 0.5f, 0.5f);
}
The problems is that when I try to set the attribute variables the one called uvCoord is not found. I think this may be due to an optimization, however, if that's so, what am I'm doing wrong or how should I do it? The uvCoord is used in the fragment shader.
The uvCoord is used in the fragment shader.
No it is not. Your output is a constant color. As a result, the texture fetches before are all eliminated by a decent compiler, as is the texCoord varying. This ultimately results in the elimination of the input attribute, which simply does not affect the output of the program in any way. This is allowed by the GL spec. Your attribute is just not considered active, but only active attributes have locations.
I've been trying to add SSAO (based on the tutorial here: http://john-chapman-graphics.blogspot.co.nz/2013/01/ssao-tutorial.html) to a project of mine and I've gotten stuck on rendering the depth correctly.
I have created a framebuffer texture to draw the depth to each frame. The texture itself looks correct when I draw it to a quad but I can't figure out how to correctly apply it to the whole scene.
Here's what the regular scene looks like:
And here's the applied depth texture:
Currently in my fragment shader I just use my regular texture coordinates (TexCoord0) to draw the depth texture. I'm guessing I need to change this but I don't have a clue what to change it to.
Here's the relevant fragment shader code:
#version 330 core
in vec2 TexCoord0;
smooth in vec3 vNormal;
smooth in vec3 vWorldPos;
in mat4 ProjectionMatrix;
uniform sampler2D uDepthTex;
layout(location = 0) out vec4 FragColor;
void main()
{
FragColor = texture(uDepthTex, TexCoord0);
}
I'm at a bit of a loss as to how to fix this. I've read a lot of sample code online which seems to use regular texture coordinates to draw the depth.
EDIT:
Here's my framebuffer setup code:
glGenFramebuffers(1, &ssaoFramebufferID);
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFramebufferID);
glGenTextures(1, &ssaoDepthTextureID);
glBindTexture(GL_TEXTURE_2D, ssaoDepthTextureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, ssaoDepthTextureID, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
And the depth pass code I call each frame before regular draw:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFramebufferID);
glViewport(0, 0, 1024, 1024);
depthShader.Bind();
depthShader.SetUniformMatrixfv("depthMVP", camera.GetViewMatrix() * Matrix4::Perspective(60, aspectRatio, 0.1f, 10.0f));
DrawScene(true);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, width, height);
My depth shaders, vertex:
#version 330 core
layout(location = 0) in vec3 Position;
uniform mat4 depthMVP;
void main() {
gl_Position = depthMVP * vec4(Position, 1.0);
}
fragment:
#version 330 core
layout(location = 0) out float fragmentdepth;
void main() {
fragmentdepth = gl_FragCoord.z;
}
EDIT2:
The glClear call where it currently is gives me a completely black texture. Putting it below the first glViewport call gives the depth image I displayed above though:
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFramebufferID);
glViewport(0, 0, 1024, 1024);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
I managed to get it working thanks to some help in the comments:
My code is now as follows, fragment shader:
#version 330 core
in vec2 TexCoord0;
smooth in vec3 vNormal;
smooth in vec3 vWorldPos;
in mat4 ProjectionMatrix;
uniform sampler2D uDepthTex;
uniform float uWidth;
uniform float uHeight;
layout(location = 0) out vec4 FragColor;
void main()
{
vec2 res = gl_FragCoord.xy / vec2(uWidth, uHeight);
FragColor = texture(uDepthTex, res);
}
Framebuffer creation:
glGenFramebuffers(1, &ssaoFramebufferID);
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFramebufferID);
glGenTextures(1, &ssaoDepthTextureID);
glBindTexture(GL_TEXTURE_2D, ssaoDepthTextureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1024, 768, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
Depth draw code:
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFramebufferID);
glViewport(0, 0, 1024, 768);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
depthShader.Bind();
glDisable(GL_ALPHA_TEST);
depthShader.SetUniformMatrixfv("depthMVP", Matrix4::Perspective(60, aspectRatio, 0.1f, 10.0f) * camera.GetViewMatrix());
DrawScene();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, width, height);
glEnable(GL_ALPHA_TEST);