OpenGL FBO render different textures in different texture targets - c++

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!

Related

Render depth as texture from framebuffer to displaying window

I am new to OpenGL. I want to read and save all the depth values from the rendered scene using framebuffers. I managed to set it up as a framebuffer attached to the depth component. But when I render the depth texture to the default framebuffer (displaying window) it only shows the color white, even though I linearized the depth value (tutorial followed from https://learnopengl.com/). I get a depth map when I access the depth value from gl_FragCoord.z in the default framebuffer fragment shader and the plot is also ok, but when sending depth as texture from a separate framebuffer to the default, the depth image is strong white.
The code that I wrote for this is given below:
Custom framebuffer vertex and fragment shader
const char* vertexShaderFBO =
"#version 330\n"
"layout (location = 0) in vec3 vp;"
"uniform mat4 camera;"
"uniform mat4 projection;"
"void main() {"
" gl_Position = camera * projection * vec4(vp.x, vp.y, vp.z, 1.0);"
"}";
const char* fragmentShaderFBO =
"#version 330\n"
"layout (location = 0) out float frag_depth;"
"float near = 0.1;"
"float far = 100;"
"float LinearizeDepth(float depth)"
"{"
" float z = depth * 2.0 - 1.0;"
" return (2.0 * near * far) / (far + near - z * (far - near));"
"}"
"void main() {"
" float linearDepth = LinearizeDepth(gl_FragCoord.z) / far;" // divided by far is just to visualize depth
" frag_depth = linearDepth ;"
"}";
Default framebuffer vertex and fragment shader
const char* vertexShader =
"#version 330\n"
"layout (location = 0) in vec3 vp;"
"uniform mat4 camera;"
"uniform mat4 projection;"
"void main() {"
" gl_Position = camera * projection * vec4(vp.x, vp.y, vp.z, 1.0);"
"}";
const char* fragmentShader =
"#version 330\n"
"out vec4 frag_colour;"
"uniform sampler2D depthSampler;"
"in vec2 texCoords;"
"void main() {"
" float depthVal = texture(depthSampler, texCoords).r;"
" frag_colour = vec4(vec3(depthVal), 1);"
"}";
Depth Texture
GLuint setDepthTexture()
{
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SCREEN_SIZE.x, SCREEN_SIZE.y, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
return texture;
}
Render OFF files
int renderOFF(Vertices* vertices, Faces* faces, Views* views)
{
// initializaion
...
...
glEnable(GL_DEPTH_TEST); // enable depth buffer
glDepthFunc(GL_LESS); // If pixel closer to camera then overwrite the existing pixel
...
...
// create framebuffer shader
GLuint shaderProgramFBO = createShader(vertexShaderFBO, fragmentShaderFBO);
// create renderer shader
GLuint shaderProgram = createShader(vertexShader, fragmentShader);
//set texture
GLuint depthTexture = setDepthTexture();
// set framebuffer
unsigned int fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// attach texture to framebuffer
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
std::cout << "Failed to bind framebuffer" << std::endl;
return -1;
}
// Use no color attachment
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(shaderProgram);
glUniform1i(glGetUniformLocation(shaderProgram, "depthSampler"), 0);
// set camera
...
...
while(!glfwWindowShouldClose(glfWwindow))
{
// check OpenGL error
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
std::cout << "OpenGL error: " << err << std::endl;
}
// bind to custom framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glClearColor(0, 0, 0, 1); // clear screen to black
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgramFBO);
...
glEnable(GL_DEPTH_TEST);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, faces->size, GL_UNSIGNED_INT, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// default framebuffer
glClearColor(0, 0, 0, 1); // clear screen to black
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
processKeyBoardInput(glfWwindow);
...
//glDisable(GL_DEPTH_TEST);
glBindVertexArray(vao);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, depthTexture);
glDrawElements(GL_TRIANGLES, faces->size, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(glfWwindow);
glfwPollEvents();
sleep(1);
}
glDeleteFramebuffers(1, &fbo);
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glfwTerminate();
return 0;
}
The resulted rendered image vs expected image results are given below
The fragment shader assigns the depth values in the range [near, far] to the color values in range [0.0, 1.0]. If all of the geometry is in an area close to 0.0, the rendering will appear almost black as 0.1 is rendered black and 100 is rendered white. Move the near and far plane of the viewing volume (viewing frustum) as close to the geometry as possible to take advantage of the entire range between 0.0 and 1.0.
Your fragment shader will work fine when the near plane is close to 0. As the near plane gets larger, you should use:
float linearDepth = LinearizeDepth(gl_FragCoord.z) / far;
float linearDepth = (LinearizeDepth(gl_FragCoord.z) - near) / (far - near);

OpenGL: Bind FBO's depth texture to a compute shader

I've been trying to render to an FBO and render two FBO's to the screen, but have been unsuccessfull to do a depth test at the merge of the two FBO's. I've tried merging the textures with an compute shader, but I am unable to read the values of the depth textures(all values are value 1, but depth test is working when I render to the FBO). Does anybody knows what I am doing wrong, or knows an other method to merge two FBO's?
This is how I create the FBO:
struct FBO {
uint color;
uint depth;
uint fbo;
};
FBO createFBO(int width, int height) {
FBO fbo;
fbo.color = createFBOTexture(width, height, false);
fbo.depth = createFBOTexture(width, height, true);
fbo.fbo = generateFramebuffer(fbo.color, fbo.depth);
return fbo;
}
uint createFBOTexture(int width, int height, bool isDepthBuffer) {
uint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
if (isDepthBuffer)
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
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);
int i = glGetError();
if (i)
std::cout << "Error while creating the FBO: " << gluErrorString(i) << '\n';
return texture;
}
uint generateFrameBuffer(uint color, uint depth)
{
int mipmapLevel = 0;
//Generate FBO
uint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
//Attatch textures to the FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, mipmapLevel);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, mipmapLevel);
//Error check
int i = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (i != GL_FRAMEBUFFER_COMPLETE)
std::cout << "ERROR: frambuffer is not ok, status: " << i << '\n';
else {
int i = glGetError();
if (i)
std::cout << "Error while creating the FBO: " << gluErrorString(i) << '\n';
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return fbo;
}
This is how I render to the FBO:
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glBindFramebuffer(GL_FRAMEBUFFER, fbo_pointcloud.fbo);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawPointCloud(); //Here I draw points with the depreciated fixed pipeline
glFlush();
I have tried to bind the textures with glBindTexture(all values read where 1):
void MergeFrames::merge(TextureLoading::FBO tex0, TextureLoading::FBO tex1, GLuint result, int width, int height)
{
glUseProgram(shader);
//Bind depth textures
glActiveTexture(GL_TEXTURE0+0);
glBindTexture(GL_TEXTURE_2D, tex0.depth);
glActiveTexture(GL_TEXTURE0+1);
glBindTexture(GL_TEXTURE_2D, tex1.depth);
//Bind color textures
glBindImageTexture(2, tex0.color, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
glBindImageTexture(3, tex1.color, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
glBindImageTexture(4, result, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
//Dispatch the shader
glDispatchCompute(ceilf(width / 16.0f), ceilf(height / 16.0f), 1);
}
The compute shader:
#version 430
uniform sampler2D depthTex0;
uniform sampler2D depthTex1;
uniform layout(rgba8) readonly image2D colorTex0;
uniform layout(rgba8) readonly image2D colorTex1;
uniform layout(rgba8) writeonly image2D mergedColor;
layout (local_size_x = 16, local_size_y = 16) in;
void main() {
ivec2 ID = ivec2(gl_GlobalInvocationID.xy);
ivec2 size = imageSize(colorTex0);
vec2 texCoords = vec2(float(ID.x)/float(size.x),float(ID.y)/float(size.y));
float depths[2];
vec4 colors[2];
depths[0] = texture2D(depthTex0, texCoords).x;
depths[1] = texture2D(depthTex1, texCoords).x;
colors[0] = imageLoad(colorTex0, ID);
colors[1] = imageLoad(colorTex1, ID);
int i = int(depths[1] > depths[0]);
imageStore(mergedColor, ID, colors[i]);
}
I have tried to bind the textures with glBindTexture(all values read where 0):
void MergeFrames::merge(TextureLoading::FBO tex0, TextureLoading::FBO tex1, GLuint result, int width, int height)
{
glUseProgram(shader);
glBindImageTexture(0, tex0.color, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
glBindImageTexture(1, tex1.color, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
glBindImageTexture(2, tex0.depth, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R16);
glBindImageTexture(3, tex1.depth, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R16);
glBindImageTexture(4, result, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
glDispatchCompute(ceilf(width / 16.0f), ceilf(height / 16.0f), 1);
}
The compute shader:
#version 430
uniform layout(rgba8) readonly image2D colorTex0;
uniform layout(rgba8) readonly image2D colorTex1;
uniform layout(r16) readonly image2D depthTex0;
uniform layout(r16) readonly image2D depthTex1;
uniform layout(rgba8) writeonly image2D mergedColor;
layout (local_size_x = 16, local_size_y = 16) in;
void main() {
ivec2 ID = ivec2(gl_GlobalInvocationID.xy);
float depths[2];
vec4 colors[2];
colors[0] = imageLoad(colorTex0, ID);
depths[0] = imageLoad(depthTex0, ID).x;
colors[1] = imageLoad(colorTex1, ID);
depths[1] = imageLoad(depthTex1, ID).x;
int i = int(depths[1] < depths[0]);
imageStore(mergedColor, ID, colors[i]);
}
And this is how I bind the indices (the indices are differt in the version where I use sampler2D instead of image2D):
MergeFrames::MergeFrames()
{
shader = OpenGL::compileComputeShader("MergeFrames.comp");
glUseProgram(shader);
glUniform1i(glGetUniformLocation(shader, "colorTex0"), 0);
glUniform1i(glGetUniformLocation(shader, "colorTex1"), 1);
glUniform1i(glGetUniformLocation(shader, "depthTex0"), 2);
glUniform1i(glGetUniformLocation(shader, "depthTex1"), 3);
glUniform1i(glGetUniformLocation(shader, "mergedColor"), 4);
}
I got the code working, by copying the data from depth texture to a texture with format GL_RED after rendering .

Framebuffer depth-artifacts

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.

OpenGL 3.0: Cannot use framebuffer object in shader (black)

I want to draw a scene to a framebuffer object and later use the texture of that in another shader. For testing purposes I would just like to actually output the framebuffer object's textur. However, the corresponding part (a rectangle) is just completely black. So I'm wondering whether either the rendering to the fbo does not work or the access to that.
Here are the important code parts:
Called before rendering to the FBO:
void TextureRenderer::bind() {
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
// glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0, 0, mWidth, mHeight);
}
This is the plane on which the FBO should be displayed. The first texture "mTextureId" is another texture I've loaded from a TGA file and displaying that works just fine. However, the second "mReflectionTextureId" is the one from the VBO and this is the one which I cannot access (or it really is black because there was an error before).
void WaterPlane::render(const Transform& trans) {
mat4 projection = trans.projection;
mat4 view = trans.view;
mat4 model = mat4::identitiy();
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
mShader->bind();
// lets activate the textures now
glEnable(GL_TEXTURE_2D);
// bumpmap texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTextureId);
// set the texture
mShader->seti("waterBumpTextureSampler", 0);
// rendered reflection texture (has been rendered previously with the help of Framebuffer object for reflection)
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, mReflectionTextureId);
// set reflection texture
mShader->seti("renderedReflection", 1);
mShader->setMatrix("matProjection", projection, GL_TRUE);
mShader->setMatrix("matView", view, GL_TRUE);
mShader->setMatrix("matModel", model, GL_TRUE);
mShader->setf("vecTextureShift", mTextureShift);
mVboWaterPlane->render();
mShader->release();
glDisable(GL_TEXTURE_2D);
glPopClientAttrib();
glPopAttrib();
}
Finally, the water.fs shader:
#version 130
in vec4 VertPosition;
in vec4 VertNormal;
in vec4 VertColor;
in vec4 VertTexture;
uniform vec3 lightPos;
uniform sampler2D waterBumpTextureSampler;
uniform sampler2D renderedReflection; // reflection on the water
void main()
{
// completely black
gl_FragColor = texture( renderedReflection, VertTexture.xz);
// if this is actually commented in the bumpmap texture will be shown nicely
// gl_FragColor = texture( waterBumpTextureSampler, VertTexture.xz);
}
So in general displaying textures work, however displaying the texture from the framebuffer object does not (or the rendering to it previously to that did not work).
Screenshot:
EDIT:
The initialization code of the FBO:
void TextureRenderer::init() {
glGenFramebuffers(1, &mFramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
// The texture we're going to render to
glGenTextures(1, &mRenderedTextureId);
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, mRenderedTextureId);
cout << "TextureRenderer: creating with id " << mFramebufferName << " and tex id " << mRenderedTextureId << endl;
// Give an empty image to OpenGL ( the last "0" )
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mWidth, mHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
// Poor filtering. Needed !
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);
// The depth buffer
// TODO this is probably not needed?!?!?!
glGenRenderbuffers(1, &mDepthRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, mDepthRenderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, mWidth, mHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthRenderBuffer);
// Set "renderedTexture" as our colour attachement #0
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mRenderedTextureId, 0);
// Set the list of draw buffers.
GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers
// Always check that our framebuffer is ok
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
cout << "Problem during creation of TextureRenderer" << endl;
throw std::runtime_error("Something Bad happened here");
}
unbind();
cout << "TextureRenderer: creating with id " << mFramebufferName << "...done" << endl;
}
The bind code (which is immediately called before rendering to the FBO):
void TextureRenderer::bind() {
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
// glPushAttrib(GL_VIEWPORT_BIT); // http://wiki.delphigl.com/index.php/Tutorial_Framebufferobject
glViewport(0, 0, mWidth, mHeight);
}
This is now solved. The problem simply was, that I was using wrong texture coordinates in the water.fs (fragment) shader. Below the corrected variant of water.fs. Note the difference in calculation of the coordinates that are given then to the texture(...) function.
in vec4 VertPosition;
in vec4 VertNormal;
in vec4 VertColor;
in vec4 VertTexture;
in vec4 VertTexturePS;
uniform vec3 lightPos;
uniform sampler2D waterBumpTextureSampler;
uniform sampler2D texReflection; // reflection on the water
void main()
{
vec2 originalTexCoord = VertTexturePS.xy / VertTexturePS.w * 0.5 + vec2(0.5);
gl_FragColor = texture( texReflection, originalTexCoord.xy);
}
VertTexturePS is just calculated in the water.vs by this:
VertTexturePS = matProjection * matView * matModel * vec4(Position.xyz, 1);

C++ OpenGL Nothing is rendering when attempting supersampling

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);
}