我试图将指数阴影贴图(ESM)实现到我的渲染引擎中,但是我遇到了一些问题:只有当指数乘数小于0时我才能看到一些阴影,并且图像变得很暗。
我已经在使用Variance Shadow Maps,所以我调整了我的代码以使用ESM。
我已经更改了用于计算阴影贴图的片段着色器,如下所示:
#version 150 core
uniform float Exponential; // Exponential multiplier term of the ESM equation
out float FragColor;
float map_01(float x, float v0, float v1)
{
return (x - v0) / (v1 - v0);
}
void main()
{
float depthDivisor = (1.0 / gl_FragCoord.z);
float mappedDivisor = map_01(depthDivisor, 0.1f, 20.0f); // Since my light is a directional light I force the near and far planes to 0.1 and 20.0
FragColor = exp(Exponential * mappedDivisor);
// VSM float depth = gl_FragCoord.z;
// VSM float dx = dFdx(depth);
// VSM float dy = dFdy(depth);
// VSM float moment2 = depth * depth + 0.25 * (dx * dx + dy * dy);
// VSM FragColor = vec4(depth, moment2, 0.0, 1.0);
}
我为阴影贴图保留了相同的顶点着色器:
in vec3 _position;
uniform mat4 ProjectionViewMatrix; // Projection-View matrix of the light
layout(std140) uniform MOD
{
mat4 AModelMatrix[20];
};
void main()
{
gl_Position = ProjectionViewMatrix * AModelMatrix[gl_InstanceID] * vec4(_position, 1.0);
}
我已经将我的定向光片段着色器更改为:
uniform mat4 InverseProjectionViewMatrix; // Inverse of the camera projection-view matrix
uniform float Exponential; // Exponential multiplier term of the ESM equation (same as shadow map fragment shader)
uniform mat4 ProjectionViewMatrix; // Light projection view matrix
void main()
{
vec3 genPos = vec3((gl_FragCoord.x * InverseScreenSize.x), (gl_FragCoord.y * InverseScreenSize.y), 0.0f);
genPos.z = texture(PrepassBuffer_DepthMap, genPos.xy).r;
vec4 clip = InverseProjectionViewMatrix * vec4(genPos * 2.0f - 1.0f, 1.0f);
vec3 pos = clip.xyz / clip.w;
vec4 shadowCoord = ProjectionViewMatrix * vec4(pos, 1.0f);
shadowCoord /= shadowCoord.w;
shadowCoord.xyz = shadowCoord.xyz * vec3(0.5f, 0.5f, 0.5f) + vec3(0.5f, 0.5f, 0.5f);
float occluder = texture(DILShadowMap, shadowCoord.xy).r;
float reciever = map_01(shadowCoord.z, 0.1f, 20.0f);
float shadowAmount = saturate(occluder * exp(-Exponential * reciever));
...
}
显示问题的几张图片。
这是我得到的完全相同的位置(基本上是相同的顶点着色器)的结果,但是使用方差阴影贴图方程式:
我从我发现的算法中发现的唯一内容是阴影贴图片段着色器和定向光片段着色器中的这两行:
// Shadow map fragment shader
float depthDivisor = (1.0 / gl_FragCoord.z); // <- changed gl_FragCoord.z (originally was gl_FragCoord.w)
// Directional light fragment shader
float reciever = map_01(shadowCoord.z, 0.1f, 20.0f); // <- changed shadowCoord.z (originally was shadowCoord.w)
我已经进行了这两项更改,因为W组件始终为1.0,当深度存储到Z组件中时使用W似乎不正确。