LookAt матрица при отбрасывании теней, параллельных восходящему вектору - PullRequest
1 голос
/ 19 октября 2019

Я следую учебным пособиям LearnOpenGL и возился с отбрасыванием теней. Пока все работает правильно, но есть эта очень специфическая проблема, когда я не могу отбрасывать тени от чисто вертикального направленного света. Давайте добавим немного кода. Моя космическая матрица освещения выглядит следующим образом:

glm::mat4 view = glm::lookAt(-direction, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
return glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -10.0f, 10.0f) * view;

направление - это вектор с направлением света, конечно же, в качестве направления. Все работает хорошо, пока этот вектор направления не будет установлен на (0, -1,0), потому что он параллелен вектору вверх (0,1,0). Чтобы построить матрицу lookAt, glm выполняет перекрестное произведение между вектором вверх и разницей между центром и глазом (так что в этом случае это в основном направление),но это перекрестное произведение не даст никакого результата, так как два вектора параллельны.

Зная все это, мой вопрос будет таким: как мой lookAt должен видеть матрицу, когда вектор вверх и направлениесвет идет параллельно?

Редактировать: Спасибо за ваш ответ, я изменил свой код на это:

if(abs(direction.x) < FLT_EPSILON && abs(direction.z) < FLT_EPSILON) 
view = glm::lookAt(-direction, glm::vec3(0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); 
else 
view = glm::lookAt(-direction, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); 
return glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -10.0f, 10.0f) * view; 

и теперь все работает отлично!

1 Ответ

1 голос
/ 19 октября 2019

Когда вектор вверх и линия визирования параллельны, тогда матрица вида не определена, потому что Перекрестное произведение равно (0, 0, 0).
Матрица вида является Ортогональная матрица , это означает, что каждая из трех осей перпендикулярна плоскости, которая образована двумя другими осями. Соответственно, угол между осями равен 90 °.
Матрица вида является обратной матрицей этой матрицы, которая определяет положение и ориентацию просмотра. Эта матрица определяется параметрами glm::lookAt. 2 оси a res, определяемой линией визирования и вектором вверх. 3-я ось рассчитывается по перекрестному произведению.

Все это означает, что вы должны указать матрицу по 2 Ортогональным направлениям. Если угол между векторами направления не является точно (90 °), то это корректируется с помощью glm::lookAt. Но алгоритм не может этого сделать, если векторы параллельны. Определите вектор линии визирования (направления) и вектор восходящего направления под углом 90 ° друг к другу. Если вы поворачиваете один из них, то вы должны повернуть другой вектор таким же образом.

например, давайте предположим, что у вас есть вектор направления (линия визирования) и вектор вверх:

direction: (0, 0, 1)
up       : (0, 1, 0)

Если вектор направления повернут на 90 °, вектор поворота также должен быть повернут на 90 °:

direction: (0, -1, 0)
up       : (0,  0, 1)
...