2016-09-02 1 views
1

Я пытался в течение некоторого времени получить пиксель экрана (предоставленный отложенным шейдером HLSL) для преобразования в светлое пространство. Результаты были для меня неожиданными, так как мой световой рендеринг, похоже, разбивает буфер глубины.DirectX Converting Pixel World Position to Shadow Map Position Дает странные, плетеные результаты

Важно отметить, что камера сцены (или глаз) и свет отображаются с начала в том же положении.

Во-первых, я извлекаю мировой позиции пикселя, используя код ниже:

float3 eye = Eye; 
float4 position = { 
    IN.texCoord.x * 2 - 1, 
    (1 - IN.texCoord.y) * 2 - 1, 
    zbuffer.r, 
    1 
}; 
float4 hposition = mul(position, EyeViewProjectionInverse); 
position = float4(hposition.xyz/hposition.w, hposition.w); 
float3 eyeDirection = normalize(eye - position.xyz); 

Результат кажется правильным, как делает положение XYZ в RGB соответственно дает это (по-видимому, правильный) результат:

Correctly rendered XYZ

Красный компонент, кажется, правильно выводит X, когда он перемещается вправо, а синий показывает движение Z вперед. Коэффициент Y также выглядит правильно, так как земля немного ниже оси Y.

Далее (и, конечно, я не схожу с ума), я решил выпустить исходный буфер глубины. Обычно я сохраняю буфер глубины в Texture2D под названием DepthMap, переданный шейдеру в качестве входного сигнала. В этом случае, однако, я стараюсь, чтобы отменить преобразование пикселя путем смещения его обратно в правильное положение, и умножением его на вид-проекционной матрицы глаза:

float4 cpos = mul(position, EyeViewProjection); 
cpos.xyz = cpos.xyz/cpos.w; 
cpos.x = cpos.x * 0.5f + 0.5f; 
cpos.y = 1 - (cpos.y * 0.5f + 0.5f); 
float camera_depth = pow(DepthMap.Sample(Sampler, cpos.xy).r, 100); // Power 100 just to visualize the map since scales are really tiny 
return float4(camera_depth, camera_depth, camera_depth, 1); 

Это дает правильный результат, который выглядит так же (хотя я 'не на 100% уверены в значении Z). Кроме того, обратите внимание, что я сделал результаты экспоненциальным лучше визуализировать информацию о глубине (это не сделано при попытке живых сравнений):

Reinterpreting XYZ back to ZBuffer space

Итак, теоретически, я могу использовать один и тот же код, чтобы преобразовать этот пиксельный мир положение в светлое пространство путем умножения на матрицу зрения-проекции света. Верный? Вот что я пробовал:

float4 lpos = mul(position, ShadowLightViewProjection[0]); 
lpos.xyz = lpos.xyz/lpos.w; 
lpos.x = lpos.x * 0.5f + 0.5f; 
lpos.y = 1 - (lpos.y * 0.5f + 0.5f); 
float shadow_map_depth = pow(ShadowLightMap[0].Sample(Sampler, lpos.xy).r, 100); // Power 100 just to visualize the map since scales are really tiny 
return float4(shadow_map_depth, shadow_map_depth, shadow_map_depth, 1); 

И вот результат:

Broken light space

И еще, чтобы показать лучше, как это отображение в мире:

Broken light space #2

Я не» Не понимаю, что здесь происходит. Похоже, что это может иметь какое-то отношение к матрице проекции, но я не так хорошо разбираюсь в математике, чтобы точно знать, что происходит. Это определенно не ширина/высота световой карты, так как я пробовал несколько размеров карт, а матрица проецирования рассчитывалась с использованием FOV и пропорций, никогда не вводивших ширину/высоту.

Наконец, вот некоторые C++ код, показывающий, как вычисляется матрица моей точки зрения (используется как для глаз и света):

const auto ys = std::tan((T)1.57079632679f - (fov/(T)2.0)); 
    const auto xs = ys/aspect; 
    const auto& zf = view_far; 
    const auto& zn = view_near; 
    const auto zfn = zf - zn; 

    row1(xs, 0, 0, 0); 
    row2(0, ys, 0, 0); 
    row3(0, 0, zf/zfn, 1); 
    row4(0, 0, -zn * zf/zfn, 0); 
    return *this; 

Я полностью в недоумении здесь. Любые рекомендации или рекомендации будут высоко оценены!

EDIT - Я также забыл упомянуть, что черепичное изображение перевернуто, как будто флип сломал его. Это странно для меня, так как это необходимо для правильного отображения текстуры.

ответ

1

Я сделал некоторые настройки и исправленные вещи здесь и там. В конечном счете, моей самой большой проблемой была неожиданно перенесенная матрица. Это немного сложнее в том, как матрица была перенесена, но вот почему все было перевернуто. Я также перешел на буферы глубины D32 (хотя я не уверен, что это помогло кому-либо) и удостоверился, что любые позиции, разделенные их W, затронут весь компонент (включая W).

Так код, как это: hposition.xyz = hposition.xyz/hposition.w стал этим: hposition = hposition/hposition.w

После всей этой настройки, он начинает выглядеть как карты теней.

Ох, а транспонированная матрица была ViewProjection света.

Смежные вопросы