级联阴影映射查找决定/ gl_FragCoord.z

时间:2012-05-06 20:32:04

标签: opengl glsl

我已经在nvidia SDK中实现了Cascaded Shadow Mapping(http://developer.download.nvidia.com/SDK/10.5/Samples/cascaded_shadow_maps.zip)。但是我的查找似乎不起作用。

这是描绘我当前状态的图片:http://i.imgur.com/SCHDO.png

问题是,尽管我离它很远,但我最终会在第一次分裂时结束。如您所见,其他分裂甚至都没有考虑过。

我认为原因可能来自主引擎使用的不同投影矩阵。它与我提供的算法不同,但我也尝试将相同的矩阵传递给着色器并以这种方式计算:gl_Position = matProj * gl_ModelViewMatrix * gl_Vertex 这真的没有改变一件事。我最后只有一次分裂。

以下是我的着色器:

[顶点]

varying vec3 vecLight;
varying vec3 vecEye;
varying vec3 vecNormal;
varying vec4 vecPos;
varying vec4 fragCoord;
void main(void)
{
    vecPos = gl_Vertex;
    vecNormal = normalize(gl_NormalMatrix * gl_Normal);
    vecLight = normalize(gl_LightSource[0].position.xyz);
    vecEye = normalize(-vecPos.xyz);

    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = ftransform();
}

[片段](只是阴影部分)

vec4 getShadow()
{
    vec4 sm_coord_c = texmat_3*vecPos;
    float shadow = texture2D(smap_3, sm_coord_c.xy).x;
    float s = (shadow < sm_coord_c.z) ? 0.0 : 1.0;

    vec4 shadow_c = vec4(1.0, 1.0, 1.0, 1.0) * s;

    if(gl_FragCoord.z < vecFarbound.x)
    {
      vec4 sm_coord_c = texmat_0*vecPos;
      float shadow = texture2D(smap_0, sm_coord_c.xy).x;
      float s = (shadow < sm_coord_c.z) ? 0.0 : 1.0;

      shadow_c = vec4(0.7, 0.7, 1.0, 1.0) * s;
    }
    else if(gl_FragCoord.z < vecFarbound.y)
    {
      vec4 sm_coord_c = texmat_1*vecPos;
      float shadow = texture2D(smap_1, sm_coord_c.xy).x;
      float s = (shadow < sm_coord_c.z) ? 0.0 : 1.0;

      shadow_c = vec4(0.7, 1.0, 0.7, 1.0) * s;
    }
    else if(gl_FragCoord.z < vecFarbound.z)
    {
      vec4 sm_coord_c = texmat_2*vecPos;
      float shadow = texture2D(smap_2, sm_coord_c.xy).x;
      float s = (shadow < sm_coord_c.z) ? 0.0 : 1.0;

      shadow_c = vec4(1.0, 0.7, 0.7, 1.0) * s;
    }

    return shadow_c;
}

因此出于某种原因,无论我在哪个场景中,gl_FragCoord.z都小于vecFarbound.x。 (还要注意到最左边的阴影区域,这个增加了我移动相机越高,很快就会占据所有场景..)

我检查了vecFarbound值,它们与nvidia代码中的值类似,所以我假设我正确计算了它们。

有没有办法检查gl_FragCoord.z的值?

1 个答案:

答案 0 :(得分:1)

在我的旧csm实现中,我只是在相机空间中使用距离

float tempDist = 0.0;
tempDist = dot(EyePos.xyz, EyePos.xyz);
if (tempDist < split.x) ...
else if (tempDist < split.y) ...
...

我理解Thsi解决方案有点简单,我可以更好地控制分裂。当您使用Z值(在剪辑空间中)时,可能会出现一些z值不是线性的问题。

我建议在viewSpace中进行拆分测试,然后(如果有效)使用gl_FragCoord.z ..