Как использовать смещение с тенями кубической карты

Итак, у меня есть еще одна проблема с отображением теней. Я пытаюсь реализовать точечные источники света с тенями кубической карты, и это почти работает.

Я визуализирую тени в кубическую карту типа DEPTH_COMPONENT16. Я делаю 6 проходов, используя те же шейдеры, что и для направленного и точечного освещения. У меня нет цветовых выходов, и я просто использую буфер глубины. Я полагаю, что это должно быть хорошо, так как кубическая карта состоит всего из 6 прожекторов, с которыми у меня нет проблем.

Теперь моя проблема возникает, когда я пытаюсь использовать карту теней в своем шейдере освещения. Мой рендерер отложен, поэтому я должен реконструировать все позиции по глубине.

Когда я делаю выборку из кубической карты, я делаю это:

// world space fragment to light
vec3 cubeNorm = normalize(w_pos - LB.position);
vec3 absNorm = abs(cubeNorm);
bool xy = absNorm.x > absNorm.y;
bool yz = absNorm.y > absNorm.z;
bool zx = absNorm.z > absNorm.x;
// which cube face will be sampled from
int index = 0; 
if (xy && !zx) index = 0 + int(cubeNorm.x < 0.f);
if (yz && !xy) index = 2 + int(cubeNorm.y < 0.f);
if (zx && !yz) index = 4 + int(cubeNorm.z < 0.f);
// point in light space with small normal offset
vec4 sc = LB.matArr[index] * vec4(w_pos+w_surf*0.06f, 1.f); 
vec4 shadcrd = vec4(cubeNorm, sc.z / sc.w * 0.5f + 0.5f);
// normals in view space
float bias = get_bias(v_surf, dirToPoint);
float vis = sample_shadow(shadcrd, bias, texShad);

Функция get_bias:

float get_bias(vec3 _normal, vec3 _lightDir) {
    float lightDot = dot(_normal, -_lightDir);
    float magicTan = sqrt(1.f - lightDot * lightDot) / lightDot;
    return clamp(0.006f * magicTan, 0.f, 0.03f);
}

Функция sample_shadow:

float sample_shadow(vec4 _sc, float _bias, samplerCubeShadow _tex) {
    return texture(_tex, vec4(_sc.xyz, _sc.w-_bias));
}

И вот что я получаю. Я отключил уменьшение расстояния, чтобы проблему было легче увидеть: problem

Таким образом, смещение не работает должным образом. Настройка функции get_bias для возврата больших значений, похоже, не помогает. Кажется, единственное, что устраняет прыщи, — это добавление огромного постоянного смещения, что, очевидно, не вариант.

Для сравнения, вот прожектор, сделанный в том же месте с углом обзора 90 градусов. Шейдер использует ту же функцию get_bias, а ближняя/дальняя плоскости одинаковы (0.2/5.0): noproblem

Нет проблем с предвзятостью. Я мог бы просто использовать 6 прожекторов (без закругленных краев), но я бы предпочел использовать кубическую карту. Что я делаю неправильно?


person Jagoly    schedule 14.04.2015    source источник


Ответы (1)


Решил это. Это была простая оплошность. Линия:

vec3 cubeNorm = normalize(w_pos - LB.position);

должно было быть нормальное смещение:

vec3 cubeNorm = normalize((w_pos+w_surf*0.06f) - LB.position);

Кроме того, есть лучший способ сравнить глубину в ответе здесь. Однако для этого требуются ближний и дальний самолеты.

person Jagoly    schedule 16.04.2015