Трассировка лучей OpenGL с использованием обратных преобразований - PullRequest
0 голосов
/ 25 ноября 2018

У меня есть конвейер, который использует матрицы модели, вида и проекции для рендеринга треугольной сетки.

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

Когда в вершинном шейдере только что была модель (без вида и проекции), у меня было

Vector4f ray_origin = model.inverse() * Vector4f(xworld, yworld, 0, 1);
Vector4f ray_direction = model.inverse() * Vector4f(0, 0, -1, 0);

, и все работало идеально.Однако я добавил матрицу вида и проекции, а затем изменил код на

Vector4f ray_origin = model.inverse() * view.inverse() *  projection.inverse() * Vector4f(xworld, yworld, 0, 1);
Vector4f ray_direction = model.inverse() * view.inverse() *  projection.inverse() * Vector4f(0, 0, -1, 0);

, и больше ничего не работает.Что я делаю не так?

1 Ответ

0 голосов
/ 25 ноября 2018

Если вы используете перспективную проекцию, то я рекомендую определять луч по точке в ближней плоскости и другой точке в дальней плоскости в нормализованном пространстве устройства.Координата z ближней плоскости равна -1, а координата z дальней плоскости 1. Координаты x и y должны быть позицией «щелчка» на экране в диапазоне [-1, 1] Координата нижней части.слева (-1, -1), а координата в верхнем правом углу (1, 1).Координаты окна или мыши могут быть отображены линейно в координаты x и y NDC:

float x_ndc = 2.0 * mouse_x/window_width - 1.0;
flaot y_ndc = 1.0 - 2.0 * mouse_y/window_height; // flipped

Vector4f p_near_ndc = Vector4f(x_ndc, y_ndc, -1, 1); // z near = -1
Vector4f p_far_ndc  = Vector4f(x_ndc, y_ndc,  1, 1); // z far = 1

Точка в нормализованном пространстве устройства может быть преобразована в пространство модели с помощью матрицы обратной проекции, затем матрицы обратного просмотра инаконец, матрица обратной модели:

Vector4f p_near_h = model.inverse() * view.inverse() *  projection.inverse() * p_near_ndc;
Vector4f p_far_h  = model.inverse() * view.inverse() *  projection.inverse() * p_far_ndc;

После этого точка представляет собой Однородные координаты , которые можно преобразовать с помощью Перспективного деления в Декартовкоордината :

Vector3f p0 = p_near_h.head<3>() / p_near_h.w();
Vector3f p1 = p_far_h.head<3>()  / p_far_h.w();

"Луч" в пространстве модели, определенный точкой r и нормализованным направлением d, наконец, равен:

Vector3f r = p0;
Vector3f d = (p1 - p0).normalized()
...