设法使Shadow Mapping在我的OpenGL渲染引擎中工作,但是它产生了一些我认为是“暗疮”的怪异伪像。但是,我正在使用shadow2DProj从阴影深度贴图获取阴影值,对我而言,这已被证明是使阴影完全显示的唯一方法。因此,在learnopengl的各种教程,opengl-tutorials和其他教程中浏览并没有产生任何帮助。想获得一些有关如何缓解此问题的建议。
这是我用来绘制阴影贴图的着色器:
#version 330 core
out vec4 FragColor;
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
vec3 attenuation;
};
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
in vec4 ShadowCoords;
uniform vec3 viewPos;
uniform sampler2D diffuseMap;
uniform sampler2D specularMap;
uniform sampler2DShadow shadowMap;
uniform Light lights[4];
uniform float shininess;
float calculateShadow(vec3 lightDir)
{
float shadowValue = shadow2DProj(shadowMap,ShadowCoords).r;
float shadow = shadowValue;
return shadow;
}
vec3 calculateAmbience(Light light,vec3 textureMap)
{
return light.ambient * textureMap;
}
void main()
{
vec4 tex = texture(diffuseMap,TexCoords);
if (tex.a < 0.5)
{
discard;
}
vec3 ambient = vec3(0.0);
vec3 diffuse = vec3(0.0);
vec3 specular = vec3(0.0);
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
for (int i = 0; i < 4; i++)
{
ambient = ambient + lights[i].ambient * tex.rgb;
vec3 lightDir = normalize(lights[i].position - FragPos);
float diff = max(dot(norm,lightDir),0.0);
diffuse = diffuse + (lights[i].diffuse * diff * tex.rgb);
vec3 reflectDir = reflect(-lightDir,norm);
float spec = pow(max(dot(viewDir,reflectDir),0.0),shininess);
specular = specular + (lights[i].specular * spec * tex.rgb);
float dist = length(lights[i].position - FragPos);
float attenuation = lights[i].attenuation.x + (lights[i].attenuation.y * dist) + (lights[i].attenuation.z * (dist * dist));
if (attenuation > 0.0)
{
ambient *= 1.0 / attenuation;
diffuse *= 1.0 / attenuation;
specular *= 1.0 / attenuation;
}
}
float shadow = calculateShadow(normalize(lights[0].position - FragPos));
vec3 result = (ambient + (shadow) * (diffuse + specular));
FragColor = vec4(result,1.0);
}
这是我得到的结果。注意立方体顶部的怪异条纹:
阅读有关暗疮的描述,这似乎是相同的现象(来源:https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping)。
根据那篇文章,我需要检查ShadowCoord深度值(减去偏置常数)是否低于从阴影贴图读取的阴影值。如果是这样,我们就有阴影。现在...问题来了。由于我使用shadow2DProj而不是texture()从阴影贴图中获取阴影值(毫无疑问,是通过一些复杂的魔术),因此我无法将该文章的代码“移植”到我的着色器中并使其正常工作。这是我尝试过的:
float calculateShadow(vec3 lightDir)
{
float closestDepth = shadow2DProj(shadowMap,ShadowCoords).r;
float bias = 0.005;
float currentDepth = ShadowCoords.z;
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
return shadow;
}
但是这根本不会产生阴影,因为“阴影”浮点数始终从深度和偏差检查中分配为1.0。我必须承认,与texture(...)。r相比,我不完全了解我使用shadow2DProj(...)。r会得到什么,但这肯定是完全不同的。