如何使用立方体贴图阴影进行偏置

时间:2015-04-14 14:58:51

标签: opengl 3d shadow-mapping

所以,我还有阴影贴图的另一个问题。我正在尝试用立方体贴图阴影实现点光源,几乎让它工作。

我将阴影渲染到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));
}

而且,这就是我得到的。我已禁用距离滚动以使问题更易于查看:problem

因此,偏差不能正常工作。调整get_bias函数以返回更大的值似乎没有帮助。除去粉刺的唯一方法似乎是增加了一个巨大的恒定偏差,这显然不是一种选择。

为了比较,这里是一个聚光灯,在90度的fov相同的地方渲染。着色器使用相同的get_bias函数,近/远平面相同(0.2 / 5.0):noproblem

没有偏见问题。我可以使用6个聚光灯(没有圆角),但我宁愿使用立方体贴图。我做错了什么?

1 个答案:

答案 0 :(得分:0)

解决了它。 &#39; Twas一个简单的疏忽。这一行:

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

应该是正常偏移:

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

此外,还有一种方法可以在答案here中更深入地比较深度。它确实需要近和远的飞机。