尝试渲染到多个纹理以实现延迟渲染。但所有纹理都是平等的

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

所以我正在尝试在 opengl 中实现延迟渲染。为此,我创建了一个渲染到 3 个纹理的 FBO(一个用于位置,一个用于法线,一个用于 material 信息)但是由于我还没有完成,所以第三个纹理只是片段的最终颜色。最后一个深度缓冲区用于稍后实现阴影。

然后将此纹理传递给另一个着色器(并使用默认的帧缓冲区),该着色器计算像素的最终颜色。然而,所有 3 个纹理都包含相同的信息,这是几何通道着色器的第一个输出变量。

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

所有 3 个输出此图像:

这是我的几何片段着色器:

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

但是似乎只有第一个输出变量完成了,因为如果我改变这个:

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

这表明:

这是其他重要功能

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);
}
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 作用于 current 程序,由 glUseProgram 定义。在您调用 setUniformLighting 之前,我发现明显 缺少 调用此函数。因此,您需要执行以下操作之一:

  1. 有调用setUniformLighting的代码预先调用glUseProgram(lightPassShader)
  2. setUniformLighting 自己在内部进行调用。
  3. 使用glProgramUniform,作用于您指定的程序,而不是当前绑定的程序。请注意,此功能需要 GL 4.1/ARB_separate_shader_object.