glm::perspective explanation

前端 未结 2 683
梦谈多话
梦谈多话 2020-12-24 11:58

I am trying to understand what the following code does:

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

Does it create

相关标签:
2条回答
  • 2020-12-24 12:43

    This is a c standalone version of the same function. This is roughly a copy paste version of the 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);
    }
    
    0 讨论(0)
  • 2020-12-24 12:56

    It creates a projection matrix, i.e. the matrix that describes the set of linear equations that transforms vectors from eye space into clip space. Matrices really are not black magic. In the case of OpenGL they happen to be a 4-by-4 arrangement of numbers:

    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
    

    You can multply a 4-vector by a 4×4 matrix:

    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
    

    After reaching clip space (i.e. after the projection step), the primitives are clipped. The vertices resulting from the clipping are then undergoing the perspective divide, i.e.

    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 )
    

    And that's it. There's really nothing more going on in all those transformation steps than ordinary matrix-vector multiplication.

    Now the cool thing about this is, that matrices can be used to describe the relative alignment of a coordinate system within another coordinate system. What the perspective transform does is, that it let's the vertices z-values "slip" into their projected w-values as well. And by the perspective divide a non-unity w will cause "distortion" of the vertex coordinates. Vertices with small z will be divided by a small w, thus their coordinates "blow" up, whereas vertices with large z will be "squeezed", which is what's causing the perspective effect.

    0 讨论(0)
提交回复
热议问题