Преобразование в НДЦ, вычисление и преобразование обратно в мировое пространство

У меня проблема с перемещением мировых координат в координаты ndc, чем вычислить что-то с помощью этого и переместить обратно в шейдер.

Код выглядит так:

vec3 testFunc(vec3 pos, vec3 dir){
    //pos and dir are in worldspace, convert to NDC
    vec4 NDC_dir = MVP * vec4(dir,0);
    vec4 NDC_pos = MVP * vec4(pos,1);
    NDC_dir /= NDC_dir.w;
    NDC_pos /= NDC_pos.w;

    //... do some caclulations => get newPos in NDC 

    //Transform newPos back to worldspace
    vec4 WS_newPos = inverse(MVP) * vec4(newPos,1);
    return WS_newPos.xyz / Ws_newPos.w;
}

Что я обнаружил при тестировании, так это то, что хотя NDC_dir.x и NDC_dir.y кажутся разумными, NDC_dir.w и NDC_dir.z всегда почти равны. Поэтому при делении на "w" значение z всегда равно 1. Я не думаю, что так оно и должно быть? (То же самое для NDC_pos).

С другой стороны, когда я преобразовываю "pos" в NDC и затем преобразовываю его обратно в Worldspace (без каких-либо вычислений), он, кажется, получает исходную точку, которая фактически означает, что преобразования верны.

Кто-нибудь может сказать мне, если я делаю что-то здесь не так, и если нет, то почему значение z всегда равно 1?

Обновление: это немного смущает. У меня было две проблемы: 1. Одна была проблемой направления, на которую указал @Арне. Другая была просто проблемой масштабирования на моей стороне. У меня был действительно маленький ближний клип и большой дальний клип. И поскольку значение является логарифмическим, я только что сделал два больших шага, чтобы понять, что значение z на самом деле действительно изменяется от -1 до 1.

1 ответ

Решение

При тестировании я обнаружил, что, хотя NDC_dir.x и NDC_dir.y кажутся разумными, NDC_dir.w и NDC_dir.z всегда почти равны. Поэтому при делении на "w" значение z всегда равно 1. Я не думаю, что так оно и должно быть? (То же самое для NDC_pos).

На самом деле да, так и должно быть. Если ваш вклад сформирован как {x,y,z,0} тогда это будет интерпретироваться как точка бесконечно далеко в направлении {x,y,z}. Поэтому компонент глубины всегда должен быть наиболее удаленным, если вообще виден. Кстати, бесконечно удаленная точка все еще остается инвариантной

Но вы должны знать, что точка бесконечно далеко, вероятно, не то, что вы хотите в NDC.

Вектор в трехмерном пространстве инвариантен к переводу, он просто остается тем же вектором, потому что у вектора есть только направление, а не позиция. Это не реально возможно в искаженном НДЦ.

Если вы хотите преобразовать вектор, вам лучше преобразовать две точки, а затем снова взять разницу в NDC. Но вы должны знать, что ваш результат зависит от позиции.

Другие вопросы по тегам