所以,我还有一个关于阴影贴图的问题。我正在尝试使用立方体贴图阴影实现点光源,并且几乎可以正常工作。
我将阴影渲染成 DEPTH_COMPONENT16 类型的立方体贴图。我进行了 6 次通过,使用与定向光和聚光灯完全相同的着色器。我没有任何颜色输出,只使用深度缓冲区。我认为这应该没问题,因为立方体贴图几乎只有 6 个聚光灯,我没有任何问题。
现在,当我尝试在我的光照着色器中采样阴影贴图时,我的问题就来了。我的渲染器被延迟了,所以我必须从深度重建所有位置。
当我从立方体贴图中采样时,我这样做:
// world space fragment to light
vec3 cubeNorm = normalize(w_pos - LB.position);
vec3 absNorm = abs(cubeNorm);
bool xy = absNorm.x > absNorm.y;
bool yz = absNorm.y > absNorm.z;
bool zx = absNorm.z > absNorm.x;
// which cube face will be sampled from
int index = 0;
if (xy && !zx) index = 0 + int(cubeNorm.x < 0.f);
if (yz && !xy) index = 2 + int(cubeNorm.y < 0.f);
if (zx && !yz) index = 4 + int(cubeNorm.z < 0.f);
// point in light space with small normal offset
vec4 sc = LB.matArr[index] * vec4(w_pos+w_surf*0.06f, 1.f);
vec4 shadcrd = vec4(cubeNorm, sc.z / sc.w * 0.5f + 0.5f);
// normals in view space
float bias = get_bias(v_surf, dirToPoint);
float vis = sample_shadow(shadcrd, bias, texShad);
get_bias 函数:
float get_bias(vec3 _normal, vec3 _lightDir) {
float lightDot = dot(_normal, -_lightDir);
float magicTan = sqrt(1.f - lightDot * lightDot) / lightDot;
return clamp(0.006f * magicTan, 0.f, 0.03f);
}
sample_shadow 函数:
float sample_shadow(vec4 _sc, float _bias, samplerCubeShadow _tex) {
return texture(_tex, vec4(_sc.xyz, _sc.w-_bias));
}
而且,这就是我得到的。我禁用了距离滚降,以便更容易看到问题:
因此,偏置不能正常工作。调整 get_bias 函数以返回更大的值似乎没有帮助。消除粉刺的唯一方法似乎是增加一个巨大的恒定偏差,这显然不是一个选择。
为了比较,这里是一个聚光灯,在同一个地方以 90 度的视野渲染。着色器使用相同的 get_bias 函数,近/远平面相同(0.2/5.0):
没有偏见问题。我可以只使用 6 个聚光灯(没有圆边),但我宁愿使用立方体贴图。我究竟做错了什么?