阴影映射中带有求和面积表的数值稳定性

时间:2011-04-13 11:00:28

标签: macos opengl glsl shadow

我在SAVSM设置中遇到精度损失的问题。

enter image description here

当你看到光线移动时效果非常惊人;有很多噪音,碎片一直在黑白分明。通过使用微分方程(因此忽略低于某个阈值的任何东西)可以稍微减少这一点,但是随着不正确的衰减,我们会得到更糟糕的效果(参见我的其他帖子)。

我正在使用GLSL 1.2,因为我在Mac上,所以我无法访问modf函数,以便在GPU Gems 3第8章中描述的两个通道之间分割精度。

我将GL_RGBA32F_ARB纹理与Framebuffer对象一起使用,然后ping两个纹理来生成一个求和区域表,我将其用于VSM算法。

Moments / Depth Shader为表创建基础

varying vec4 v_position;
varying float tDepth;


float g_DistributeFactor = 1024.0;  


void main()
{
    // Is this linear depth? I would say yes but one can't be utterly sure.
    // Could try a divide by the far plane?

    float depth = v_position.z / v_position.w ;
    depth = depth * 0.5 + 0.5;          //Don't forget to move away from unit cube ([-1,1]) to [0,1] coordinate system

    vec2 moments = vec2(depth, depth * depth);


    // Adjusting moments (this is sort of bias per pixel) using derivative
    float dx = dFdx(depth);
    float dy = dFdy(depth);
    moments.y += 0.25 * (dx*dx+dy*dy);

    // Subtract 0.5 off now so we can get this into our summed area table calc

    //moments -= 0.5;

    // Split the moments into rg and ba for EVEN MORE PRECISION

//  float FactorInv = 1.0 / g_DistributeFactor;

//  gl_FragColor = vec4(floor(moments.x) * FactorInv, fract(moments.x ) * g_DistributeFactor, 
//                  floor(moments.y)  * FactorInv, fract(moments.y)  * g_DistributeFactor);


    gl_FragColor = vec4(moments,0.0,0.0);
}

阴影贴图着色器

varying vec4 v_position;
varying float tDepth;


float g_DistributeFactor = 1024.0;  


void main()
{
    // Is this linear depth? I would say yes but one can't be utterly sure.
    // Could try a divide by the far plane?

    float depth = v_position.z / v_position.w ;
    depth = depth * 0.5 + 0.5;          //Don't forget to move away from unit cube ([-1,1]) to [0,1] coordinate system

    vec2 moments = vec2(depth, depth * depth);


    // Adjusting moments (this is sort of bias per pixel) using derivative
    float dx = dFdx(depth);
    float dy = dFdy(depth);
    moments.y += 0.25 * (dx*dx+dy*dy);

    // Subtract 0.5 off now so we can get this into our summed area table calc

    //moments -= 0.5;

    // Split the moments into rg and ba for EVEN MORE PRECISION

//  float FactorInv = 1.0 / g_DistributeFactor;

//  gl_FragColor = vec4(floor(moments.x) * FactorInv, fract(moments.x ) * g_DistributeFactor, 
//                  floor(moments.y)  * FactorInv, fract(moments.y)  * g_DistributeFactor);


    gl_FragColor = vec4(moments,0.0,0.0);
}

Summed表似乎确实有效。我知道这是因为我有一个函数可以从求和表转换回原始深度图,这两个图像看起来几乎相同。我也使用-0.5 + 0.5技巧以获得更高的精度但它似乎没有帮助

我的问题是这个,鉴于im只在一个只有GLSL 1.2的mac上,如何在两个通道上分割精度?如果我可以在求和表中使用这些额外的通道空间,那么这可能会起作用吗?我见过一些使用modf的东西,但我不能使用。

另外,人们建议使用32位整数缓冲区,但我不认为我在macbook pro上支持这些缓冲区。

0 个答案:

没有答案