OpenGL阴影贴图未显示

时间:2017-07-05 13:47:12

标签: c++ opengl glsl shadow framebuffer

我正在尝试在我的项目中使用阴影贴图。我按照Learn OpenGL Tutorial上的教程进行了操作。出于某种原因,我无法看到阴影,只能看到片段着色器中照明代码的镜面反射。 Image from render

以下是我如何进行帧缓冲设置(frameBufferDepthMap是两个全局GLuint):

void createFrameBuffer()
{
    glGenFramebuffers(1, &frameBuffer);
    glGenTextures(1, &DepthMap);
    glBindTexture(GL_TEXTURE_2D, DepthMap);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
        SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 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_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, DepthMap, 0);
    glDrawBuffer(GL_NONE);
    glReadBuffer(GL_NONE);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

然后我继续设置几何

glGenVertexArrays(1, &shadowVertexAttribute);
glBindVertexArray(shadowVertexAttribute);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
//Texture Map
glUniform1i(glGetUniformLocation(sShaderProgram, "DepthMap"), 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, DepthMap);
//Normal Map
glUniform1i(glGetUniformLocation(sShaderProgram, "DiffuseMap"), 1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureMap);

glUniform3fv(glGetUniformLocation(sShaderProgram, "lightPos"), 1, glm::value_ptr(lightPos));

GLuint shadowVertBuffer;
GLuint shadowUVBuffer;
GLuint shadowNormalBuffer;
for (int i = 0; i < objmesh.size(); i++) {

    glGenBuffers(1, &shadowVertBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, shadowVertBuffer);
    glBufferData(GL_ARRAY_BUFFER, objmesh[i]->vertices.size() * sizeof(glm::vec3), &objmesh[i]->vertices[0], GL_STATIC_DRAW);
    GLuint svertexPos = glGetAttribLocation(sShaderProgram, "vertex_position");
    glVertexAttribPointer(svertexPos, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glGenBuffers(1, &shadowUVBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, shadowUVBuffer);
    glBufferData(GL_ARRAY_BUFFER, objmesh[i]->uvs.size() * sizeof(glm::vec2), &objmesh[i]->uvs[0], GL_STATIC_DRAW);
    GLuint svertexUV = glGetAttribLocation(sShaderProgram, "vertex_UV");
    glVertexAttribPointer(svertexUV, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glGenBuffers(1, &shadowNormalBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, shadowNormalBuffer);
    glBufferData(GL_ARRAY_BUFFER, objmesh[i]->normals.size() * sizeof(glm::vec3), &objmesh[i]->normals[0], GL_STATIC_DRAW);
    GLuint svertexNormal = glGetAttribLocation(sShaderProgram, "vertex_normal");
    glVertexAttribPointer(svertexNormal, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
}

最后,我渲染阴影(或至少尝试):

if (shadows == true) {
    glUseProgram(sShaderProgram);
    glBindVertexArray(shadowVertexAttribute);

    glm::mat4 lightProjection = glm::ortho(-3000.0f, 3000.0f, -3000.0f, 
        3000.0f, NEARPLANE, FARPLANE);
    glm::mat4 lightView = glm::lookAt(lightPos, glm::vec3(0.0),
        glm::vec3(0.0, 1.0, 0.0));
    glm::mat4 lightSpaceMatrix = lightProjection * lightView;
    glUniformMatrix4fv(glGetUniformLocation(sShaderProgram, "lightSpaceMatrix"), 
        1, GL_FALSE, glm::value_ptr(lightSpaceMatrix));

    glUniformMatrix4fv(glGetUniformLocation(sShaderProgram, "modelMatrix"),
        1, GL_FALSE, glm::value_ptr(mesh.modelMatrix));

    //rendering to depthmap
    glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
    glClear(GL_DEPTH_BUFFER_BIT);
GLuint texLocation = glGetUniformLocation(sShaderProgram, "DepthMap");
    glUniform1i(texLocation, 0);

    texLocation = glGetUniformLocation(sShaderProgram, "DiffuseMap");
    glUniform1i(texLocation, 1);

    glActiveTexture(GL_TEXTURE0 + 0);
    glBindTexture(GL_TEXTURE_2D, DepthMap);

    glActiveTexture(GL_TEXTURE0 + 1);
    glBindTexture(GL_TEXTURE_2D, textureMap);

    glDrawArrays(GL_TRIANGLES, 0, mesh.vertices.size());
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    setViewPort();

}

如果需要,这里还有Shadow Vertex和Shadow Fragment着色器。

顶点:

//Vertex Shader
#version 440

layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec2 vertex_UV;
layout(location = 2) in vec3 vertex_normal;

uniform mat4 modelMatrix;
uniform mat4 lightSpaceMatrix;

out vec3 outVertex;
out vec2 outTexCoords;
out vec3 outNormals;
out vec4 outVertexLightSpace;

layout(binding = 3 , std140) uniform uniformBlock
{
vec3 camPos;
mat4 world;
mat4 LookAt;
mat4 projection;
mat4 MVP;
};

layout(binding = 4 , std140) uniform materials
{
vec3 Diffuse;
vec3 Ambient;
vec3 Translucency;
//char texturePath[128];
float refraction;
vec3 Specular;
float PhongSpecular;
};
void main()
{
    outVertex = vec3(modelMatrix * vec4(vertex_position, 1.0));
    outTexCoords = vertex_UV;
    outNormals = transpose(inverse(mat3(modelMatrix))) * vertex_normal;
    outVertexLightSpace = lightSpaceMatrix * vec4(vertex_position, 1.0f);
    gl_Position = projection * LookAt * modelMatrix * vec4(vertex_position , 
1.0);
}

片段:

//Fragment Shader
#version 440
out vec4 fragment_color;

uniform sampler2D DepthMap;
uniform sampler2D DiffuseMap;
uniform vec3 lightPos;

in vec3 outVertex;
in vec2 outTexCoords;
in vec3 outNormals;
in vec4 outVertexLightSpace;

layout(binding = 3 , std140) uniform uniformBlock
{
vec3 camPos;
mat4 world;
mat4 LookAt;
mat4 projection;
mat4 MVP;
 };

float CalculateShadow(vec4 fragPos){
    vec3 projCoords = outVertexLightSpace.xyz / outVertexLightSpace.w;
    projCoords = projCoords * 0.5 + 0.5;
    float closestDepth = texture(DepthMap, projCoords.xy).r;
    float currentDepth = projCoords.z;
    float shadow;
    if(currentDepth > closestDepth) {
        shadow = 1.0;
    }
    else {
        shadow = 0.0;
    }

    return shadow;
}

void main()
{
    vec3 color = texture(DiffuseMap, outTexCoords).rgb;
    vec3 normal = normalize(outNormals);
    vec3 lightColor = vec3(1.0);
    vec3 ambient  = 0.4 * color;
    vec3 lightDir = normalize(lightPos - outVertex);
    float diff = max(dot(lightDir, normal), 0.0);
    vec3 diffuse = diff * lightColor;
    vec3 viewDir = normalize(camPos - outVertex);
    vec3 halfWayDir = normalize(lightDir + viewDir);
    float spec = pow(max(dot(normal, halfWayDir), 0.0), 64.0);
    vec3 specular = spec * lightColor;
    float shadowValue = CalculateShadow(outVertexLightSpace);
    vec3 lighting = (ambient + (1.0 - shadowValue) * (diffuse + specular)) * color;

    fragment_color = vec4(lighting, 1.0);

}

如果您有任何可能出错的指示,我会很高兴听到它们。感谢您提前得到的所有帮助:D

0 个答案:

没有答案