0

所以,我还有一个关于阴影贴图的问题。我正在尝试使用立方体贴图阴影实现点光源,并且几乎可以正常工作。

我将阴影渲染成 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 个聚光灯(没有圆边),但我宁愿使用立方体贴图。我究竟做错了什么?

4

1 回答 1

0

解决了。这是一个简单的疏忽。该行:

vec3 cubeNorm = normalize(w_pos - LB.position);

应该是正常的偏移量:

vec3 cubeNorm = normalize((w_pos+w_surf*0.06f) - LB.position);

此外,还有一种更好的方法可以在此处的答案中获得比较的深度。不过,它确实需要近平面和远平面。

于 2015-04-16T08:50:43.300 回答