尝试渲染到几个纹理以实现延迟渲染。但所有纹理都是相同的

时间:2017-01-13 19:26:34

标签: opengl textures framebuffer deferred-rendering

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

然后将此纹理传递给另一个着色器(并使用默认的帧缓冲区),该着色器计算像素的最终颜色。但是,所有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输出此图像:

All 3 output this image

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

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

这表明:

This shows

以下是其他重要功能

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

1 个答案:

答案 0 :(得分: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作用于当前程序,由glUseProgram定义。在您致电setUniformLighting之前,我看到了对此功能的明显缺少。因此,您需要执行以下操作之一:

  1. 预先拨打setUniformLighting致电glUseProgram(lightPassShader)的代码。
  2. setUniformLighting在内部拨打电话。
  3. 使用glProgramUniform,它对您指定的程序起作用,而不是当前绑定的程序。请注意,此功能需要GL 4.1 / ARB_separate_shader_object。