Как работают ближние / дальние плоскости отсечения в gluPerspective () / glm ::спектива ()?

У меня есть вопрос о том, как работает стандартная матрица проекции перспективы, из которой вы получаете gluPerspective() или же glm::perspective(), В частности, я задаюсь вопросом о ближних / дальних плоскостях отсечения.

У меня сложилось впечатление, что после преобразования точки с помощью матрицы перспективы объекты в ближней плоскости отсечения отображаются на значение Z, равное -1, а объекты вблизи дальней плоскости отсечения — на значение Z, равное 1.

Например, предположим, что у вас есть камера, расположенная в начале координат, смотрящая в направлении положительной оси Z, с плоскостью ближнего отсечения в 1,0 и плоскостью дальнего отсечения, установленной в 2,0. Тогда я ожидал бы, что вещи, имеющие «мировые» координаты Z между 1,0 и 2,0, будут преобразованы в проекционные координаты между -1,0 и 1,0.

Другими словами, я ожидал бы этот код C ++:

#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

using namespace glm;

void print_vec(vec4 pnt) {
std::cout << "(" << pnt.x << ", " << pnt.y << ", " << pnt.z << ")" << "\n";
}

int main() {
mat4x4 view = lookAt(
vec3(0.0f, 0.0f, 0.0f),   // eye at origin
vec3(0.0f, 0.0f, 1.0f),   // looking towards +Z
vec3(0.0f, 1.0f, 0.0f));  // up is +Y

mat4x4 projection = perspective(
radians(90.0f),  // field of view
1.0f,            // aspect ratio
1.0f,            // near clipping plane
2.0f);           // far clipping plane

// transformation matrix for world coordinates
mat4x4 vp = projection * view;

// points (0,0,1), (0,0,1.5) and (0,0,2) in homogeneous coordinates
print_vec(vp * vec4(0.0f, 0.0f, 1.0f, 1.0f));
print_vec(vp * vec4(0.0f, 0.0f, 1.5f, 1.0f));
print_vec(vp * vec4(0.0f, 0.0f, 2.0f, 1.0f));
}

распечатать это

(0, 0, -1)
(0, 0, 0)
(0, 0, 1)

Но это не так. Распечатывает это:

(0, 0, -1)
(0, 0, 0.5)
(0, 0, 2)

И я не понимаю почему. Ближайшая плоскость отсечения проецируется, как я и ожидал, но точка точно посередине между плоскостями при проецировании находится ближе к задней части, а точка на дальней плоскости отсечения полностью выходит за пределы диапазона [-1,1].

Я полагаю, что есть кое-какие базовые математические вещи, которые мне просто не хватает, поэтому я спрашиваю вас, молодцы.

(кстати, то, над чем я работаю, на самом деле написано на Rust, а не на C ++, но я переключился на C ++ для этого теста, просто чтобы убедиться, что в реализации Rust или что-то еще не было ошибки.)

1

Решение

Но это не так. Распечатывает это:

(0, 0, -1)
(0, 0, 0.5)
(0, 0, 2)

Это неправильно, потому что результат не имеет типа vec3, это Однородная координата типа vec4:

(0, 0, -1, 1)
(0, 0, 0.5, 1.5)
(0, 0, 2, 2)

Вы должны сделать Перспективный разрыв тогда вы получите ожидаемый результат:

(0/1,   0/1,   -1/1)
(0/1.5, 0/1.5,  0.5/1.5)
(0/2,   0/2,    2/2)
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]