In my simple renderer, I have 2 FBOs one that contains diffuse, normals, instance ID and depth in that order and one that I use store the ssao result. The textures I use for the first FBO are RGB8, RGBA16F, R32I and GL_DEPTH_COMPONENT32F for the depth. For the second FBO I use an R16F texture. My rendering process is to first render to everything I mentioned in the first FBO, then bind depth and normals textures for reading for the ssao pass and write to the second FBO. After that I bind the second FBO's texture for reading in my blur shader and bind the first FBO for writing. What I intend to do is to write the blurred ssao value to the alpha component of the Normals texture.

Here are where the problems start. First of all, I use shading language 3.3, which my graphics card does support. I manage ouputs in my shaders using layout(location = #). Now, the normals texture should be bound to color attachment 1, but when I use 1, it seems to write to my diffuse texture which should be in color attachment 0. When I instead use layout(location = 0), it gets correctly written to my normals texture. Besides this, my instance ID texture also gets resets after running the blur shader which is weird because if I use a float texture and write to it instanceID / nInstances, the texture doesn't get reset after the blur shader has ran.

Here is how I prepare my first FBO:

bool CGBuffer::Init(unsigned int WindowWidth, unsigned int WindowHeight){
    //Create FBO
    glGenFramebuffers(1, &m_fbo);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);

    //Create gbuffer and Depth Buffer Textures
    glGenTextures(GBUFF_NUM_TEXTURES, &m_textures[0]);
    glGenTextures(1, &m_depthTexture);
    //prepare gbuffer
    for(unsigned int i = 0; i < GBUFF_NUM_TEXTURES; i++){
        glBindTexture(GL_TEXTURE_2D, m_textures[i]);
        if(i == GBUFF_TEXTURE_TYPE_NORMAL) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, WindowWidth, WindowHeight, 0, GL_RGBA, GL_FLOAT, NULL);
        else if(i == GBUFF_TEXTURE_TYPE_DIFFUSE) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, WindowWidth, WindowHeight, 0, GL_RGB, GL_FLOAT, NULL);
        else if(i == GBUFF_TEXTURE_TYPE_ID) glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, WindowWidth, WindowHeight, 0, GL_RED_INTEGER, GL_INT, NULL);
            std::cout << "Error in FBO initialization" << std::endl;
            return false;
        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, m_textures[i], 0);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

    //prepare depth buffer
    glBindTexture(GL_TEXTURE_2D, m_depthTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, WindowWidth, WindowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexture, 0);

    glDrawBuffers(GBUFF_NUM_TEXTURES, DrawBuffers);

    GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

        std::cout << "FB error, status 0x" << std::hex << Status << std::endl;
        return false;

    //Restore default framebuffer
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    return true;

where I use an enum defined as,


Am I missing some kind of restriction? Does the color attachment of the FBO's textures somehow gets reset i.e. I'm using a re-size function which re-sizes the textures of the FBO but should I perhaps call glFramebufferTexture2D again too?

EDIT: Here is the shader in question:

#version 330 core

uniform sampler2D aoSampler;
uniform vec2 TEXEL_SIZE; // x = 1/res x, y = 1/res y
uniform bool use_blur;

noperspective in vec2 TexCoord;

layout(location = 0) out vec4 out_AO;

void main(void){
        float result = 0.0;
        for(int i = -1; i < 2; i++){
            for(int j = -1; j < 2; j++){
                vec2 offset = vec2(TEXEL_SIZE.x * i, TEXEL_SIZE.y * j);
                result += texture(aoSampler, TexCoord + offset).r; // -0.004 because the texture seems to be a bit displaced

        out_AO = vec4(vec3(0.0), result / 9);
    else out_AO = vec4(vec3(0.0), texture(aoSampler, TexCoord).r);

EDIT2: I decided to focus on the problem of the blur shader output needed to be set at layout(location = 0) for it to write to the correct color attachment. My framebuffer was set with two draw buffers, GL_COLOR_ATTACHMENT0 and GL_COLOR_ATTACHMENT1 as part of its state. Attachment 0 is a RGB8 and attachment 1 is a RGBA16F, my intention is to write in the alpha channel of attachment 1. Setting layout(location = 1) in the blur shader, gives me some weird and undesired results. I have tried several things to try and understand how things work.

If I add one more output in the blur shader, i.e. layout(location = 0) someOutput and set out_AO to layout(location = 1), it then works correctly too.

Also, from a different test I did, it seems that opengl is trying to write to all the active draw buffers.

It seems to me that for some reason, if more than one draw buffers are specified, all draw buffers need a location specified in the shader, i.e. if you only want one output you should activate only one draw buffer with the correct color attachment and set location to 0, regardless of the color attachment number.

It would be sufficient for now if someone could tell me the specifics of this behavior as I couldn't find something in the specification. Also, although I haven't done any extended tests, it seems that on an ATI card the behavior is different.

  • \$\begingroup\$ Why not show the shader in question? \$\endgroup\$ – Nicol Bolas Dec 3 '12 at 16:33
  • \$\begingroup\$ I didn't think it contains something really strange. I should mention I enable blending when using this shader so that the normals part of the texture doesn't become 0 (with glBlendFunc(GL_ONE, GL_ONE) ). \$\endgroup\$ – Grieverheart Dec 3 '12 at 18:03
  • \$\begingroup\$ This question appears to be off-topic because it is about debugging your code for you. \$\endgroup\$ – user1430 Jan 6 '14 at 16:15