Чтобы сделать это преобразование, вы должны сначала занять свои позиции в пространстве модели и преобразовать их в пространство клипа. Это делается с помощью умножения матриц. Я буду использовать код в стиле GLSL, чтобы было понятно, что я делаю:
vec4 clipSpacePos = projectionMatrix * (viewMatrix * vec4(point3D, 1.0));
Обратите внимание, как я преобразовываю ваш трехмерный вектор в четырехмерный вектор перед умножением. Это необходимо, потому что матрицы имеют размер 4x4, и вы не можете умножить матрицу 4x4 на трехмерный вектор. Вам нужен четвертый компонент.
Следующим шагом является преобразование этой позиции из пространства клипа в нормализованное пространство координат устройства (пространство NDC). Пространство NDC находится в диапазоне [-1, 1] по всем трем осям. Это делается путем деления первых трех координат на четвертые:
vec3 ndcSpacePos = clipSpacePos.xyz / clipSpacePos.w;
Очевидно, что если clipSpacePos.w
равно нулю, у вас есть проблема, поэтому вы должны проверить это заранее. Если это ноль, то это означает, что объект находится в плоскости проекции; это глубина пространства просмотра равна нулю. И такие вершины автоматически обрезаются OpenGL.
Следующим шагом является преобразование из этого пространства [-1, 1] в координаты относительно окна. Это требует использования значений, которые вы передали glViewport
. Первые два параметра - это смещение от нижнего левого угла окна (vec2 viewOffset
), а вторые два параметра - это ширина / высота области просмотра (vec2 viewSize
). Учитывая это, позиция оконного пространства:
vec2 windowSpacePos = ((ndcSpacePos.xy + 1.0) / 2.0) * viewSize + viewOffset;
И это так далеко, как вы идете. Помните: пространство окна OpenGL относится к внизу слева окна, а не к верхнему левому углу.