c++opengltexturesfborender-to-texture

OpenGL FBO render different textures in different texture targets


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:

output 1

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:

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:

debugError

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.


Solution

  • 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!