#macos #opengl #glsl #shadow
#macos #opengl #glsl #тень
Вопрос:
У меня возникла проблема с потерей точности в моей настройке SAVSM.
когда вы видите движущийся свет, эффект очень поразительный; возникает много шума, фрагменты постоянно становятся черно-белыми. Это может быть несколько уменьшено с помощью minvariance (таким образом, игнорируя все, что ниже определенного порога), но тогда мы получаем еще худшие эффекты с неправильным уменьшением (см. Мой другой пост).
Я использую GLSL 1.2, потому что я на Mac, поэтому у меня нет доступа к функции modf, чтобы разделить точность по двум каналам, как описано в GPU Gems 3, глава 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);
}
Шейдер shadowmap
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.
Комментарии:
1. Вы нашли хорошее решение для этого в конце? В настоящее время я нахожусь в начале своего путешествия по текстурам глубины суммированной области и уже сталкиваюсь с похожими проблемами.