OpenGL ShadowMap设置正确的矩阵

时间:2017-05-17 14:54:50

标签: c++ opengl shadow-mapping

我使用矢量作为光位置说(0.0f,0.0f,5.0f)和一个位于(0.0f,0.0f,-10.0f)的物体和一个平面。

lightSpaceProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 1.0f, 300.0f);
lightSpaceView= glm::lookAt(lightPosition, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
lightSpaceMatrix = lightSpaceProjection * lightSpaceView;

随着相机随处可见阴影,我想知道如何更新阴影贴图以渲染相机所在的正确空间阴影。

我计算了如图所示的光照空间矩阵,将其发送到顶点着色器,从光源视图渲染阴影贴图,然后再将其发送到普通顶点着色器,以计算哪个片段处于阴影中,

灯光定义

DirectLight sun;
sun.direction = glm::vec3(0.0f, 10.0f, 5.0f);
sun.lightSpaceProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 1.0f, 300.0f);
sun.lightSpaceView= glm::lookAt(sun.direction, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
scene.addLight("sun", sun);

这是渲染代码

    DirectLight& sun = dynamic_cast<DirectLight&>(this->getLight("sun", LIGHTTYPE_DIRECT));
    glm::mat4 lightSpaceMatrix = (sun.lightSpaceProjection * sun.lightSpaceView);
    glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
    glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
    glClear(GL_DEPTH_BUFFER_BIT);
    //glCullFace(GL_FRONT);

    typedef std::map<std::string, Model>::iterator model_it;
    depthShader.use();
    glUniformMatrix4fv(glGetUniformLocation(depthShader.getProgramID(), "lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix));
    for (model_it it = phongModels.begin(); it != phongModels.end(); it++) {
        ((Model&) it->second).drawDepth(depthShader);
    }
    //glCullFace(GL_BACK);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    // draw normal
    glViewport(0, 0, WIDTH, HEIGHT);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    typedef std::map<std::string, Model>::iterator model_it;
    phongShader.use();
    glUniformMatrix4fv(glGetUniformLocation(phongShader.getProgramID(), "lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix));
    this->drawPhongLights(phongShader);
    this->setViewUniforms(phongShader);
    for (model_it it = phongModels.begin(); it != phongModels.end(); it++) {
        glActiveTexture(GL_TEXTURE2);
        glUniform1i(glGetUniformLocation(phongShader.getProgramID(), "shadowMap"), 2);
        glBindTexture(GL_TEXTURE_2D, depthMap);
        ((Model&) it->second).drawPhong(phongShader, this->defCamera);
    }

深度顶点着色器是

#version 330 core

layout (location = 0) in vec3 position;
uniform mat4 lightSpaceMatrix;
uniform mat4 model;

void main(){
    gl_Position = lightSpaceMatrix * model * vec4(position, 1.0f);
}

,正常的顶点着色器是

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 2) in vec2 texCoord;
layout (location = 1) in vec3 normal;

out vec2 TexCoords;
out vec3 Normal;
out vec3 FragPos;
out vec3 LightPos;
out vec4 FragPosLightSpace;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform vec3 lightPos;
uniform mat4 lightSpaceMatrix;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);     
    TexCoords = vec2(texCoord.s,1.0-texCoord.t);
    Normal=normal;
    FragPos = vec3(view * model * vec4(position, 1.0f));
    LightPos = vec3(view * vec4(lightPos, 1.0));
    FragPosLightSpace = lightSpaceMatrix * vec4(FragPos, 1.0);
}

并在片段着色器中我通过此函数计算阴影

float directShadowCalculation(vec4 fragPosLightSpace,float bias){
    vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
    projCoords = projCoords * 0.5 + 0.5;
    float closestDepth = vec3(texture(shadowMap, projCoords.xy)).r;
    float currentDepth = projCoords.z;
    float shadow = 0.0;
    vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
    for(int x = -1; x <= 1; ++x){
        for(int y = -1; y <= 1; ++y){
            float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r; 
            shadow += currentDepth - bias > pcfDepth  ? 1.0 : 0.0;        
        }    
    }
    shadow /= 9.0;
    if(projCoords.z > 1.0)
        shadow = 0.0;    
    return shadow;
    }
然后

应用这个颜色

vec3 calcDirectLight(DirectLight light){
    vec3 color = vec3(texture(mat_diffuse, TexCoords));

    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize( light.direction  - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = light.diffuse * diff ;

    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);

    float spec =0.0;
    if(blinn){
        vec3 halfwayDir = normalize(lightDir + viewDir);
        spec = pow(max(dot(norm, halfwayDir), 0.0), 16.0);
    }
    else{
        vec3 reflectDir = reflect(-lightDir, norm);
        spec = pow(max(dot(viewDir, reflectDir), 0.0), 8.0);
    }

    //float spec = pow(max(dot(viewDir, reflectDir), 0.0), shininess);
    vec3 specular = spec * light.specular;
    float bias = max(0.05 * (1.0 - dot(norm, lightDir)), 0.005);
    float shadow = directShadowCalculation(FragPosLightSpace,bias);     
    vec3 result =light.intensity* (light.ambient+ ((1.0 - shadow) * (diffuse + specular)))*color;
    return result;
}

我不知道如何使用相机视图更新光线空间平截头体

解决方案: 错误是在顶点着色器中,这是正确的:

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 2) in vec2 texCoord;
layout (location = 1) in vec3 normal;

out vec2 TexCoords;
out vec3 Normal;
out vec3 FragPos;
out vec4 FragPosLightSpace;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform vec3 lightPos;
uniform mat4 lightSpaceMatrix;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);     
    TexCoords = vec2(texCoord.s,1.0-texCoord.t);
    Normal=transpose(inverse(mat3(model))) * normal;;
    FragPos = vec3( model * vec4(position, 1.0f));
    FragPosLightSpace = lightSpaceMatrix * vec4(FragPos, 1.0);
}

0 个答案:

没有答案