Матрица проекции описывает отображение от трехмерных точек сцены к двухмерным точкам области просмотра. Матрица проекции преобразуется из пространства просмотра в пространство клипа. Координаты в пространстве клипа преобразуются в нормализованные координаты устройства (NDC) в диапазоне (-1, -1, -1) в (1, 1, 1) путем деления на компоненту w
координат клипа.
В ортогональной проекции координаты в пространстве вида линейно отображаются на координаты пространства клипа, а координаты пространства клипа равны нормализованным координатам устройства, поскольку компонент w
равен 1 (для декартовой входной координаты).
![orthographic projection](https://i.stack.imgur.com/o4siK.png)
Значения слева, справа, снизу, сверху, близко и далеко определяют поле. Вся геометрия, которая находится внутри объема окна, «видна» в окне просмотра.
Наконец, нормализованные координаты устройства линейно отображаются в окне просмотра.
Когда вы устанавливаете ортографическую проекцию следующим образом:
var m = mat4.ortho([], 0, viewportWidth, 0, viewportHeight, 0.1, 100.0);
, тогда прямоугольник с нижним левым (0, 0) и верхним правым (viewportWidth, viewportHeight) отображается в NDC из (- 1, -1 ) до (1, 1) .
Когда вы устанавливаете видовой экран следующим образом:
viewport: {x: 0, y: 0, width: window.innerWidth, height: window.innerHeight}
, тогда NDC отображаются в прямоугольник области просмотра с левым нижним (0, 0) и верхним правым (viewportWidth, viewportHeight) .
Это означает, что координаты вида в (0, 0, window.innerWidth, window.innerHeight) отображаются в прямоугольник области просмотра (0, 0, window.innerWidth, window. innerHeight) . Итак, вы рисуете в «оконных» (пиксельных) координатах.
Если у вас есть такая геометрия:
position: [[-1, -1], [1, 1], [-1, 1], [-1, -1], [1, -1], [1, 1] ]
{ offset: [0, 0], scale: [0.5, 0.5], color: [0.2, 0.2, 1, 1] }
тогда размер этой геометрии составляет 1 * 1 пиксель в области просмотра - прямоугольник от (- 1, -1) до (1, 1) , с шкала (0,5, 0,5) .
Увеличьте масштаб (например, scale: [100, 100]
), чтобы решить вашу проблему.
Кроме того, геометрия должна находиться между ближней и дальней плоскостями, чтобы быть внутри объема обзора.
В вашем случае координата z геометрии равна 0, как указано в вершинном шейдере:
gl_Position = projection * vec4(position.xy * scale, 0, 1);
Но ближняя плоскость равна 0,1, а дальняя - 100,0, как указано в ортографической проекции:
var m = mat4.ortho([], 0, viewportWidth, 0, viewportHeight, 0.1, 100.0);
Это приводит к тому, что геометрия ограничена ближней плоскостью, поскольку координата z меньше, чем ближняя плоскость.
Поменяйте ближний самолет, чтобы решить проблему:
var m = mat4.ortho([], 0, viewportWidth, 0, viewportHeight, -100.0, 100.0);
Матрица ортографической проекции выглядит следующим образом:
r = right, l = left, b = bottom, t = top, n = near, f = far
2/(r-l) 0 0 0
0 2/(t-b) 0 0
0 0 -2/(f-n) 0
-(r+l)/(r-l) -(t+b)/(t-b) -(f+n)/(f-n) 1
В соответствии с комментарием:
для mat4.ortho, левый верхний источник должен быть mat4.ortho([], 0, viewportWidth, viewportHeight, 0, -1, 1)
, но с такой проекцией на экране снова ничего не появляется.
Если top
равно 0, а bottom
- положительное значение, то из-за 2/(top-bottom)
ось y становится отрицательной.
Чтобы решить, вы можете инвертировать ось Y вручную:
var m = mat4.ortho([], 0, viewportWidth, -viewportHeight, 0, -1, 1);
В этом случае вам нужно инвертировать смещения, потому что в верхнем правом углу это (0, 0) , а в левом нижнем углу - (viewportWidth, -viewportHeight) .
, например
offset: [250, -250]
Если бы вы использовали
var m = mat4.ortho([], 0, viewportWidth, viewportHeight, 0, -1, 1);
тогда вам нужно инвертировать шкалы y.
, например
scale: [100, -100]