34

次のコードが何をするのか理解しようとしています:

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

射影行列を作成しますか? ユーザーの視界にないものを切り取りますか? APIページで何も見つけることができませんでした。彼らのウェブサイトのpdfで見つけたのはこれだけでした:

gluパースペクティブ:

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>

しかし、それはパラメータを説明していません。多分私は何かを逃した。

4

2 に答える 2

31

射影行列、つまり、目空間からクリップ空間にベクトルを変換する一次方程式のセットを記述する行列を作成します。行列は実際には黒魔術ではありません。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 を持つ頂点は「圧迫」され、これが遠近効果を引き起こします。

于 2011-11-13T23:31:42.130 に答える
2

これは、同じ機能の AC スタンドアロン バージョンです。これは大まかにオリジナルのコピペ版です。

# 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);
}
于 2015-07-23T12:58:23.357 に答える