Системы координат и пространства
Вершина проходит несколько систем координат, прежде чем стать пикселем — каждая решает свою задачу.
Пространство (space) — система координат с собственным началом и осями, удобная для конкретного этапа рендеринга.
Зачем это знать
Один и тот же объект описывается по-разному в зависимости от точки зрения: относительно себя, относительно мира, относительно камеры. Перевод между пространствами — это умножение на матрицы, и именно из-за него возникают «модельная», «видовая» и «проекционная» матрицы. Путаница в пространствах — частый источник багов (объект не там, повёрнут не туда).
Цепочка пространств
Локальное (model space) вершины относительно центра объекта
| * матрица модели (Model)
v
Мировое (world space) объект размещён и повёрнут в сцене
| * матрица вида (View)
v
Видовое (view/camera space) всё относительно камеры (камера в начале)
| * матрица проекции (Projection)
v
Клип-пространство (clip) готово к отсечению и делению на w
| деление на w + viewport
v
Экранное (screen space) координаты пикселей
Зачем столько пространств
- Локальное: художник моделирует объект «вокруг нуля», не думая, где он окажется в сцене.
- Мировое: один и тот же меш можно поставить в сцену сто раз в разных местах — меняется только матрица модели.
- Видовое: удобно считать освещение и проекцию, когда камера в начале координат и смотрит вдоль оси.
- Клип и экран: железо отсекает невидимое и переводит в пиксели.
Перенос точки в мировое пространство
Самый простой переход — перенос (translation): прибавить позицию объекта к локальной координате вершины. Покажем на векторах.
# Вершина в локальном пространстве + позиция объекта в мире
def to_world(local, obj_pos):
return tuple(l + p for l, p in zip(local, obj_pos))
local_vertex = (0.0, 1.0, 0.0) # верхушка модели относительно её центра
object_position = (10.0, 0.0, -5.0) # где объект стоит в мире
world = to_world(local_vertex, object_position)
print("Локально:", local_vertex)
print("В мире: ", world)
Вывод:
Локально: (0.0, 1.0, 0.0) В мире: (10.0, 1.0, -5.0)
Верхушка модели, заданная относительно своего центра, оказалась в нужном месте сцены простым переносом. Полная матрица модели добавляет ещё поворот и масштаб — об этом в разделе про матрицы.
Как работает под капотом
На практике три матрицы (Model, View, Projection) перемножают в одну матрицу MVP и умножают на неё каждую вершину прямо в вершинном шейдере: gl_Position = MVP * vec4(position, 1.0). Камера в видовом пространстве считается стоящей в начале координат — на самом деле двигают весь мир в противоположную сторону, что эквивалентно движению камеры.
Частые ошибки
- Считать освещение в неправильном пространстве (например, мировые нормали против видовых позиций) — свет ляжет криво.
- Забыть порядок умножения матриц: он не коммутативен, P*V*M ≠ M*V*P.
- Путать «камера движется вперёд» и «мир движется назад» — в видовом пространстве это одно и то же.
Итоги
- Вершина проходит: локальное → мировое → видовое → клип → экранное пространство.
- Каждый переход — умножение на матрицу (Model, View, Projection).
- Локальное удобно для моделирования, видовое — для камеры и света.
- MVP-матрица объединяет три преобразования в одно умножение.