阴影贴图射线投射的自适应深度偏差

时间:2017-10-26 15:01:56

标签: opengl graphics glsl raytracing

我发现this paper处理如何在处理阴影贴图时计算完美偏差。

想法是:

  • 获取shadowMap采样时使用的纹素
  • 将纹理像素位置投射回eyeSpace(光线追踪)
  • 了解你的frament.z和交叉点之间的区别 片段的脸。

通过这种方式,您可以计算出错误,该错误可作为z战斗的适当偏见。

现在我正在努力实现它,但我尝试了一些麻烦: 我正在使用OrthoProjectionMatrix,所以我认为我不需要来回分开。

我很好,直到我计算与脸部的光线交叉点。 我有很多面孔未通过测试,我的偏见很重要。

这是我的片段着色器代码:

 float getBias(float depthFromTexture)
{
    vec3 n = lightFragNormal.xyz;
    //no need to divide by w, we got an ortho projection
    //we are in NDC [-1,1] we go to [0,1]
    //vec4 smTexCoord = 0.5 * shadowCoord + vec4(0.5, 0.5, 0.5, 0.0);
    vec4 smTexCoord = shadowCoord;
    //we are in [0,1] we go to texture_space [0,1]->[0,shadowMap.dimension]:[0,1024]
    //get the nearest index in the shadow map, the texel corresponding to our fragment we use floor (125.6,237.9) -> (125,237)
    vec2 delta      = vec2(xPixelOffset, yPixelOffset);
    vec2 textureDim = vec2(1/xPixelOffset, 1/yPixelOffset);
    vec2 index      = floor(smTexCoord.xy * textureDim);

    //we get the center of the current texel, we had 0.5 to put us in the middle (125,237) -> (125.5,237.5)
    //we go back to [0,1024] -> [0,1],    (125.5,237.5) -> (0.12, 0.23)
    vec2 nlsGridCenter = delta*(index + vec2(0.5f, 0.5f));

    // go back to NDC [0,1] -> [-1,1]
    vec2 lsGridCenter = 2.0 * nlsGridCenter - vec2(1.0);

    //compute lightSpace grid direction, multiply by the inverse projection matrice or
    vec4 lsGridCenter4 = inverse(lightProjectionMatrix) * vec4(lsGridCenter, -frustrumNear, 0);
    vec3 lsGridLineDir = vec3(normalize(lsGridCenter4));

    /** Plane ray intersection **/
    // Locate the potential occluder for the shading fragment
    //compute the distance t we need to continue in the gridDir direction, the point is "t" far
    float ls_t_hit = dot(n, lightFragmentCoord.xyz) / dot(n, lsGridLineDir);
    if(ls_t_hit<=0){
        return 0; // i got a lot of negativ values it shouldn t be the case
    }
    //compute the point p with the face
    vec3  ls_hit_p = ls_t_hit * lsGridLineDir;


    float intersectionDepth = lightProjectionMatrix * vec4(ls_hit_p, 1.0f).z / 2 + 0.5;
    float fragmentDepth     = lightProjectionMatrix * lightFragmentCoord.z / 2 + 0.5;
    float result = abs(intersectionDepth - fragmentDepth);

    return result;
}

我正在努力解决这条问题:

vec4 lsGridCenter4 = inverse(lightProjectionMatrix) * vec4(lsGridCenter, -frustrumNear, 0);

我不知道我是否正确:

vec4(lsGridCenter, -frustrumNear, 1);

当然还有平面交叉点

来自维基百科的

enter image description here 其中:

  • l =我的向量归一化方向
  • Po =属于该平面的点
  • l0 =向量的偏移量,我认为它是原点所以在眼睛空间应该是(0,0,0)我可能在这里错了
  • n =飞机的法线,我的片段在眼睛空间的法线

在我的代码中:

float ls_t_hit = dot(n, lightFragmentCoord.xyz) / dot(n, lsGridLineDir);

0 个答案:

没有答案