web-dev-qa-db-fra.com

glm :: explication de la perspective

J'essaie de comprendre ce que fait le code suivant:

glm::mat4 Projection = glm::perspective(35.0f, 1.0f, 0.1f, 100.0f);

Crée-t-il une matrice de projection ? Extrait tout ce qui ne se trouve pas dans la vue de l'utilisateur? Je n'ai rien trouvé sur la page API , et la seule chose que j'ai pu trouver dans le pdf sur leur site Web était la suivante:

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>

Mais cela n'explique pas les paramètres. Peut-être que j'ai raté quelque chose.

24
Trt Trt

Il crée une matrice de projection, c’est-à-dire la matrice qui décrit l’ensemble des équations linéaires qui transforment les vecteurs de l’espace oculaire en espaces de découpage. Les matrices ne sont vraiment pas de la magie noire. Dans le cas d’OpenGL, il s’agit d’un arrangement de nombres de 4 sur 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

Vous pouvez multiplier un vecteur 4 par une matrice 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

Après avoir atteint l'espace de clip (c'est-à-dire après l'étape de projection), les primitives sont écrêtées. Les sommets résultant du découpage subissent alors la division de perspective, c'est-à-dire.

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 )

Et c'est tout. Il n'y a vraiment rien de plus dans toutes ces étapes de transformation que la simple multiplication matrice-vecteur.

La chose intéressante à ce sujet est que les matrices peuvent être utilisées pour décrire l'alignement relatif d'un système de coordonnées dans un autre système de coordonnées. La transformation de perspective a pour effet de laisser les valeurs z des sommets "glisser" dans leurs valeurs w projetées. Et par la division de perspective, une non-unité w provoquera une "distorsion" des coordonnées du sommet. Les sommets avec un petit z seront divisés par un petit w, ainsi leurs coordonnées "exploseront", alors que les sommets avec un grand z seront "compressés", ce qui est à l'origine de l'effet de perspective.

22
datenwolf

Ceci est une version autonome de la même fonction. C'est à peu près une version copier/coller de l'original .

# 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);
}
2
Moebius