Матрица вида и матрица проекции
Две матрицы превращают мир в картинку с конкретной камеры: матрица вида ставит камеру, матрица проекции создаёт перспективу.
Матрица вида (View) переводит мир в систему координат камеры; матрица проекции (Projection) отображает объём видимости в клип-пространство.
Зачем это знать
Без этих двух матриц объекты висели бы в абсолютных мировых координатах без всякой камеры и перспективы. Матрица вида отвечает на вопрос «откуда и куда смотрим», матрица проекции — «какой тип объектива» (перспектива или чертёжная ортография) и «что в кадре».
Матрица вида: look-at
Камера задаётся тремя векторами: где она стоит (eye), куда смотрит (target) и где у неё «верх» (up). Из них строят три оси камеры и собирают матрицу вида. Идея — поставить камеру в начало координат и развернуть мир так, будто смотрим вдоль оси Z.
Камера look-at:
up
^
| target
eye o--------> *
forward = target - eye
Перспективная и ортографическая проекция
Перспектива сжимает дальнее (реализм, игры от первого лица). Ортография сохраняет размеры независимо от глубины (чертежи, изометрические 2.5D-игры, UI).
Перспектива (frustum, усечённая пирамида):
\ /
\ / дальняя плоскость шире
\ /
\ /
\/ <- камера
Ортография (параллелепипед):
| |
| | размеры не зависят от глубины
| |
|________|
Сравним поведение проекций на простой модели: перспектива делит на глубину, ортография — нет.
def perspective(x, y, z, focal=2.0):
return (round(focal*x/z, 3), round(focal*y/z, 3))
def orthographic(x, y, z, scale=0.5):
return (round(x*scale, 3), round(y*scale, 3)) # z не влияет
print("Перспектива, z=2:", perspective(1, 1, 2))
print("Перспектива, z=8:", perspective(1, 1, 8))
print("Ортография, z=2: ", orthographic(1, 1, 2))
print("Ортография, z=8: ", orthographic(1, 1, 8))
Вывод:
Перспектива, z=2: (1.0, 1.0) Перспектива, z=8: (0.25, 0.25) Ортография, z=2: (0.5, 0.5) Ортография, z=8: (0.5, 0.5)
В перспективе дальний объект (z=8) сжался вчетверо, в ортографии остался того же размера — глубина проигнорирована.
Как работает под капотом
Перспективная проекция определяется углом обзора (field of view), соотношением сторон экрана (aspect) и ближней/дальней плоскостями отсечения (near/far). Она кладёт глубину в координату w, чтобы последующее деление дало перспективу. Объекты ближе near или дальше far отсекаются. Слишком большое отношение far/near вызывает z-fighting — мерцание из-за нехватки точности буфера глубины.
Частые ошибки
- Ставить near = 0 — это ломает математику проекции; near должен быть строго положительным.
- Огромный far при крошечном near — потеря точности глубины и мерцание поверхностей.
- Забыть aspect ratio — картинка растянется при несовпадении со сторонами экрана.
Итоги
- Матрица вида ставит камеру (eye, target, up) и переводит мир в её координаты.
- Перспектива сжимает дальнее, ортография сохраняет размеры.
- Проекция задаётся FOV, aspect, near и far.
- Плохие near/far дают потерю точности глубины (z-fighting).