opengltexturesframebufferdeferred-rendering

Trying to render to several textures to implement deferred rendering. But all textures are equal


So I'm trying to implemtent deferred rendering in opengl. To do so I create a FBO which renders to 3 textures (one for position, one for normal, one for material info) however since I'm not finished the 3rd texture is instead just the final color of the fragment. And one last depth buffer to later implement shadows.

This textures then are passed to another shader (and with the default Frame Buffer) which calculates the final color of the pixel. However all 3 textures contain the same information which is the first output variable from the geometry pass shader.

#version 330
//Fragment shader from the lighting pass
in vec2 vTexCoord;

uniform sampler2D uPosTexture;
uniform sampler2D uNormalTexture;
uniform sampler2D uColorTexture;

out vec4 fFragColor;

void main()
{
    //All of the following lines output the same image
    vec3 color = texture(uNormalTexture, vTexCoord).rgb;
    //vec3 color = texture(uPosTexture, vTexCoord).rgb;
    //vec3 color = texture(uColorTexture, vTexCoord).rgb;

    fFragColor = vec4(color,1);
}

All 3 output this image:

All 3 output this image

And here is my geometry fragment shader:

#version 330

in vec3 vECPos; // S.R. Vista
in vec3 vECNorm; // S.R. Vista
in vec4 vShadowCoord;

layout (location = 0) out vec3 fPosition;
layout (location = 1) out vec3 fNormal;
layout (location = 2) out vec4 fFragColor;

uniform sampler2DShadow uShadowMap;
uniform int uTipoFiltro;

struct LightInfo {
    vec4 lightPos; // Posición de la luz (S.R. de la vista)
    vec3 intensity;
};
uniform LightInfo uLight;
struct MaterialInfo {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
};
uniform MaterialInfo uMaterial;


vec3 phongModelDiffAndSpec () 
{
    vec3 ldir = normalize(vec3(uLight.lightPos) - vECPos);
    vec3 view = normalize(vec3(-vECPos));
    vec3 r = reflect(-ldir,vECNorm);

    vec3 color = uLight.intensity * ( uMaterial.diffuse * max(dot(ldir,vECNorm), 0.0) +
                                  uMaterial.specular * pow(max(dot(r,view),0),uMaterial.shininess) );

    return clamp(color, 0.0, 1.0);
}


void main()
{

    vec3 ambient = uLight.intensity * uMaterial.ambient;
    vec3 diffAndSpec = phongModelDiffAndSpec();

    fPosition = vECPos;
    fNormal = normalize(vECNorm);
    fFragColor = vec4(ambient + diffAndSpec,1.0);
}

However it seems that only the first output variable is done because if I change this:

layout (location = 1) out vec3 fPosition;
layout (location = 2) out vec3 fNormal;
layout (location = 0) out vec4 fFragColor;

This shows:

This shows

Here are other important functions

bool init()
{
    glClearColor(0.93f, 0.93f, 0.93f, 0.0f);

    glEnable(GL_DEPTH_TEST);
    //glDepthFunc(GL_LESS);
    //glClearDepth(1.0f);

    //glShadeModel(GL_SMOOTH);

    //Create shaders
    createShader(geometryPassShader, "geometry.vert", "geometry.frag");
    setUniformGeometry();
    createShader(lightPassShader, "lighting.vert", "lighting.frag");
    setUniformLighting();

    initFBO();
    passTexturesToStdFBO();

    //Init objects
    numVertTeapot = initTeapot(5, glm::mat4(1.0f));
    numVertSphere = initSphere(1.0f, 20, 30);
    numVertPlane = initPlane(10.0f, 10.0f, 2, 2);
    numVertTorus = initTorus(0.5f, 0.25f, 20, 40);
    initQuad();

    return true;
}

void initFBO()
{
    //Crear 1 FBO
    glGenFramebuffers(1, &gBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);

    //Crear textura que guarda posicion
    glGenTextures(1, &gPositionTex);
    //glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, gPositionTex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, g_Width, g_Height, 0, GL_RGB, GL_FLOAT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    //Añadir la textura al FBO
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPositionTex, 0);

    //Crear textura que guarda normal
    glGenTextures(1, &gNormalTex);
    //glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, gNormalTex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, g_Width, g_Height, 0, GL_RGB, GL_FLOAT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    //Añadir textura al FBO
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormalTex, 0);

    //Crear textura que guarda informacion del material del "pixel"
    glGenTextures(1, &gMaterialTex);
    //glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, gMaterialTex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, g_Width, g_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gMaterialTex, 0);

    //Crear depth buffer
    glGenTextures(1, &depth_texture);
    glActiveTexture(GL_TEXTURE3);
    glBindTexture(GL_TEXTURE_2D, depth_texture);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, g_Width, g_Height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    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_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    //Indicamos que buffers (texturas) seran escritos con el output del fragment shader
    glDrawBuffers(3, attachments); //attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0);


    GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (result == GL_FRAMEBUFFER_COMPLETE)
        std::cout << "Frame buffer complete" << std::endl;
    else
        std::cout << "Frame buffer is not complete" << std::endl;

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void display()
{

    //glClear of this FBO is done inside drawFBO()
    glUseProgram(geometryPassShader);
    drawFBO();
    glUseProgram(0);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(lightPassShader);
    //passTexturesToStdFBO();
    drawQuad();
    glUseProgram(0);

    glutSwapBuffers();
}

void drawFBO()
{
    glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
    glViewport(0, 0, g_Width, g_Height);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    drawScene();

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void passTexturesToStdFBO()
{
    glBindBuffer(GL_FRAMEBUFFER, 0);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, gPositionTex);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, gNormalTex);
    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, gMaterialTex);
    glActiveTexture(GL_TEXTURE3);
    glBindTexture(GL_TEXTURE_2D, depth_texture);
}

void setUniformLighting()
{
    GLuint loc0 = glGetUniformLocation(lightPassShader, "uPosTexture");
    glUniform1i(loc0, 0);

    GLuint loc1 = glGetUniformLocation(lightPassShader, "uNormalTexture");
    glUniform1i(loc1, 1);

    GLuint loc2 = glGetUniformLocation(lightPassShader, "uColorTexture");
    glUniform1i(loc2, 2);
}

Solution

  • void setUniformLighting()
    {
        GLuint loc0 = glGetUniformLocation(lightPassShader, "uPosTexture");
        glUniform1i(loc0, 0);
    
        GLuint loc1 = glGetUniformLocation(lightPassShader, "uNormalTexture");
        glUniform1i(loc1, 1);
    
        GLuint loc2 = glGetUniformLocation(lightPassShader, "uColorTexture");
        glUniform1i(loc2, 2);
    }
    

    glUniform acts on the current program, as defined by glUseProgram. I see a distinct lack of calls to this function before you call setUniformLighting. So you need to do one of the following:

    1. Have the code that calls setUniformLighting call glUseProgram(lightPassShader) beforehand.
    2. Have setUniformLighting itself internally make that call.
    3. Use glProgramUniform, which acts on the program you specify, rather than the currently bound one. Note that this function require GL 4.1/ARB_separate_shader_object.