Возможно, следующий рисунок, показывающий взаимосвязь между различными пространствами поможет:
В зависимости, если вы используете фиксированную функцию трубопровод (вы, если вы звоните glMatrixMode()
, например), или с помощью шейдеров, операции идентичны - речь идет только о том, закодируете ли вы их непосредственно в шейдере, или конвейер OpenGL помогает в вашей работе.
Хотя есть неприятность в обсуждении вещей в терминах конвейера с фиксированной функцией, это делает разговор более простым, поэтому я начну с него.
В унаследованной OpenGL (то есть версии до OpenGL 3.1, или с использованием профилей совместимости), определяются две матричные стеки: модель-представление и проекции, а когда приложение начинает матрицу в верхней части каждой stack - это единичная матрица (1.0 по диагонали, 0.0 для всех остальных элементов). Если вы рисуете координаты в этом пространстве, вы фактически показываете в нормализованных координатах устройства (NDC), которые вырезают любые вершины вне диапазона [-1,1] как в X, Y, так и в Z. Поле просмотра преобразование (как установлено по телефону glViewport()
) - это то, что отображает НДЦ в координаты окна (ну, координаты видового экрана, действительно, но чаще всего окно просмотра и окна имеют одинаковый размер и местоположение), а значение глубины в диапазоне глубин (по умолчанию это [0,1]).
Теперь в большинстве приложений первое преобразование, которое указано, представляет собой проекционное преобразование , которое представлено в двух вариантах: орфографических и перспективных проекциях. Профильная проекция сохраняет углы и обычно используется в научных и технических приложениях, поскольку она не искажает относительные длины сегментов линии. В устаревшем OpenGL орфографические проекции указаны либо glOrtho
, либо gluOrtho2D
. Чаще всего используются перспективные преобразования, которые имитируют работу глаз (т. Е. Объекты далеко от глаза меньше, чем те, которые находятся близко), и указаны либо glFrustum
, либо gluPerspective
. Для перспективных проекций они определили просмотр усеченного конуса, который представляет собой усеченную пирамиду, закрепленную на месте глаз, которые указаны в координатах глаз. В координатах глаз «глаз» расположен в начале координат и смотрит вниз по оси -Z. Ваши вблизи и плоских плоскостях отсечения указаны как расстояния вдоль оси -Z. Если вы визуализируете координаты глаз, любая геометрия, заданная между плоскостями ближнего и дальнего отсечения, и внутренняя часть смотрового усечения не будет отбракована и будет преобразована, чтобы появиться в окне просмотра.Вот диаграмма перспективной проекции и ее отношение к плоскости изображения .
Глаз расположен на вершине смотрового усечения.
Последнее преобразование для обсуждения - это преобразование модели , которое отвечает за перемещение систем координат (а не объектов, более того, что в данный момент), так что они имеют хорошее положение относительно глаза и вид усеченный. Общие преобразования моделирования являются переводами, весами, поворотов и ножницы (которых нет встроенной поддержки в OpenGL).
Вообще говоря, 3D модели моделируются вокруг локальной системы координат (например, задавая координаты сферы с началом координат в центре). Моделирующие преобразования используются для перемещения «текущей» системы координат в новое место, так что, когда вы визуализируете локально-смоделированный объект, он позиционируется в нужном месте.
Не существует математической разницы между преобразованием моделирования и преобразованием просмотра. Как правило, трансформации моделирования используются для конкретных моделей и контролируются операциями glPushMatrix()
и glPopMatrix()
, которые, как правило, определяют преобразование просмотра и затрагивают все последующие операции моделирования.
Теперь, если вы делаете этот современный OpenGL (основные профили 3.1 и вперед), вы должны выполнять все эти операции логически самостоятельно (вы можете указать только одно преобразование, складывающее преобразования модели и проекции в однократная матрица умножается). Матрицы указываются обычно как шейдер uniforms
. Нет матричных стеков, разделения преобразований модели и проекции, и вам нужно правильно вычислить математику для эмуляции конвейера. (BTW, разделение перспективы и шаги преобразования видового экрана выполняются OpenGL после завершения вашего вершинного шейдера - вам не нужно делать математику [вы можете, это ничего не болит, если вы не сможете установить w до 1.0 в вашем выводе вершинного шейдера gl_Position
).
Ничего себе, это очень подробное и понятное описание. Мне эта тема понятна. Кстати, я использую шейдеры. – danijar
На самом деле, z-координата в NDC также находится в диапазоне [-1,1], и это преобразование вида, которое помещает его в диапазон [0,1], используя параметры 'glDepthRange'. Поэтому координаты окна не должны рассматриваться как 2D, но 3D. –
@AndreasHaferburg: На самом деле, вы оба правы. В D3D NDC фактически имеет диапазон Z [** 0 **, ** 1 **], что означает, что NDC не является технически кубом в D3D. GL использует [** - 1 **, ** 1 **] во всех направлениях для NDC (таким образом, это куб), но диапазон глубины по умолчанию (и он *** зажимается *** до этого диапазона) в GL - ** 0.0 ** -> ** 1.0 **. Учитывая вопрос о GL, я бы проигнорировал поведение D3D, но я даю радикальное преимущество в сомнении - *** может быть ** он думал о D3D? * –