Числовая стабильность с таблицами суммированных площадей в теневом отображении - PullRequest
2 голосов
/ 13 апреля 2011

У меня проблема с потерей точности в моей настройке SAVSM.

enter image description here

, когда вы видите, что свет, движущийся вокруг эффекта, очень поразителен;там много шума с фрагментами, которые становятся черно-белыми все время.Это может быть несколько уменьшено при использовании minvariance (таким образом игнорируя что-либо ниже определенного порога), но тогда мы получим еще худшие эффекты с неправильным падением (см. Мой другой пост).

Я использую GLSL 1.2, потому что я нахожусь наMac, поэтому у меня нет доступа к функции modf, чтобы разделить точность по двум каналам, как описано в Gem 3 GPU, глава 8.

Я использую текстуры GL_RGBA32F_ARB с объектом Framebuffer и пинг-понг двух текстур для генерациитаблица суммированных площадей, которую я использую с алгоритмом VSM.

Момент / Глубинный шейдер, чтобы создать основу для таблиц

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);
}

Суммированные таблицы, кажется, работают.Я знаю это, потому что у меня есть функция, которая преобразует обратно из суммированной таблицы в исходную карту глубины, и два изображения выглядят практически одинаково.Я также использую трюк -0,5 + 0,5 для получения большей точности, но, похоже, это не помогает

Мой вопрос такой, учитывая, что я на Mac, который имеет только GLSL 1.2, как я могу разделитьточность по двум каналам?Если бы я мог использовать эти дополнительные каналы для места в суммированной таблице, тогда, возможно, это сработало бы?Я видел некоторые вещи, которые используют modf, но которые мне недоступны.

Кроме того, люди предложили 32-битные целочисленные буферы, но я не думаю, что у меня есть поддержка для них на моем MacBook Pro.

...