glm:: перспективное объяснение
Я пытаюсь понять, что следующий код:
glm::mat4 Projection = glm::perspective(35.0f, 1.0f, 0.1f, 100.0f);
создает ли она матрица проекции? Обрезает все, что не находится в представлении пользователя? Я не смог найти ничего о страница API, и единственное, что я мог найти в PDF на их сайте был такой:
gluPerspective:
glm::mat4 perspective(float fovy, float aspect, float zNear,
float zFar);
glm::dmat4 perspective(
double fovy, double aspect, double zNear,
double zFar);
From GLM_GTC_matrix_transform extension: <glm/gtc/matrix_transform.hpp>
но это не объясняет параметров. Может, я что-то пропустил.
2 ответов
он создает проекционную матрицу, т. е. матрицу, которая описывает набор линейных уравнений, преобразующих векторы из пространства глаз в пространство клипов. Матрицы на самом деле не черная магия. В случае OpenGL они оказываются расположением чисел 4 на 4:
X_x Y_x Z_x T_x
X_y Y_y Z_y T_y
X_z Y_z Z_z T_z
X_w Y_w Z_w W_w
вы можете умножить на 4-вектора на матрицу 4×4:
v' = M * v
v'_x = M_xx * v_x + M_yx * v_y + M_zx * v_z + M_tx * v_w
v'_y = M_xy * v_x + M_yy * v_y + M_zy * v_z + M_ty * v_w
v'_z = M_xz * v_x + M_yz * v_y + M_zz * v_z + M_tz * v_w
v'_w = M_xw * v_x + M_yw * v_y + M_zw * v_z + M_tw * v_w
после достижения пространства клипа (т. е. после шага проекции) примитивы обрезаются. Вершины в результате клипирования затем проходит перспективный раздел, то есть
v'_x = v_x / v_w
v'_y = v_y / v_w
v'_z = v_z / v_w
( v_w = 1 = v_w / v_w )
и это все. На самом деле во всех этих шагах преобразования нет ничего больше, чем обычное умножение матрицы-вектора.
Теперь классная вещь об этом заключается в том, что матрицы могут использоваться для описания относительного выравнивания системы координат в другой системе координат. Что делает перспективное преобразование, так это то, что оно позволяет вершинам z-значений "скользить" в их проецируемые w-значения. И по перспективному делению неединственность w вызовет "искажение" координат вершин. Вершины с малым z будут разделены на маленький w, таким образом, их координаты "взорвутся", тогда как вершины с большим z будут "сжаты", что и вызывает эффект перспективы.
это автономная версия c той же функции. Это примерно копия вставить версию оригинал.
# include <math.h>
# include <stdlib.h>
# include <string.h>
typedef struct s_mat {
float *array;
int width;
int height;
} t_mat;
t_mat *mat_new(int width, int height)
{
t_mat *to_return;
to_return = (t_mat*)malloc(sizeof(t_mat));
to_return->array = malloc(width * height * sizeof(float));
to_return->width = width;
to_return->height = height;
return (to_return);
}
void mat_zero(t_mat *dest)
{
bzero(dest->array, dest->width * dest->height * sizeof(float));
}
void mat_set(t_mat *m, int x, int y, float val)
{
if (m == NULL || x > m->width || y > m->height)
return ;
m->array[m->width * (y - 1) + (x - 1)] = val;
}
t_mat *mat_perspective(float angle, float ratio,
float near, float far)
{
t_mat *to_return;
float tan_half_angle;
to_return = mat_new(4, 4);
mat_zero(to_return);
tan_half_angle = tan(angle / 2);
mat_set(to_return, 1, 1, 1 / (ratio * tan_half_angle));
mat_set(to_return, 2, 2, 1 / (tan_half_angle));
mat_set(to_return, 3, 3, -(far + near) / (far - near));
mat_set(to_return, 4, 3, -1);
mat_set(to_return, 3, 4, -(2 * far * near) / (far - near));
return (to_return);
}