跳转至

Camera

阅读信息

175 个字  2 分钟  本页总访问量:加载中...

原理

当相机在不同位置、不同角度观察时,渲染的图像不同。定义相机的位置为vec3 eye,相机观察的角度为vec3 gaze(gaze 从相机指向模型),相机向上的方向为vec3 up

对相机和模型同时变换,使变换后相机位于原点,向上为 Y,正方向为-Z。

变换分为两步,先将相机平移到原点,再旋转到上述位置。

第一步平移

矩阵\(T_{view}\),即对应 MVP 中的 Model:

\[ T_{view}= \begin{pmatrix} 1 & 0 & 0 & -x_{eye} \\ 0 & 1 & 0 & -y_{eye} \\ 0 & 0 & 1 & -z_{eye} \\ 0 & 0 & 0 & 1 \end{pmatrix} \]

第二步旋转

Y 对应 up,Z 对应-gaze,故 X 对应\(up\times -gaze=gaze\times up\)。将\((X,Y,Z)\)旋转到\((gaze\times up,up,-gaze)\)的矩阵\(R_{view}^{-1}\)为:

\[ R_{view}^{-1}=\begin{pmatrix} x_{gaze\times up} & x_{up} & x_{-gaze} & 0 \\ y_{gaze\times up} & y_{up} & y_{-gaze} & 0 \\ z_{gaze\times up } & z_{up} & z_{-gaze} & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} \]

由于旋转矩阵正交,第二步矩阵\(R_{view}\),即对应 MVP 中的 View:

\[ R_{view} = \begin{pmatrix} x_{gaze\times up} & y_{gaze\times up} & z_{gaze\times up} & 0 \\ x_{up} & y_{up} & z_{up} & 0 \\ x_{-gaze} & y_{-gaze} & z_{-gaze} & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} \]

实现

自定义相机参数

C++
1
2
3
vec3 eye = {2, 0, 3};
vec3 center = {0, 0, 0};
vec3 up = {0, 1, 0};

函数mv_mat生成MV变换的矩阵

C++
// MV变换
mat<4, 4> mv_mat(vec3 eye, vec3 center, vec3 up) {
    vec3 gaze = normalized(center - eye);
    vec3 z = -1 * gaze;
    vec3 x = normalized(cross(gaze, up));
    // vec3 y = up; // 要求gaze和up正交
    vec3 y = cross(z, x);

    // 平移
    mat<4, 4> T = identity<4>();
    T[0][3] = -eye.x;
    T[1][3] = -eye.y;
    T[2][3] = -eye.z;

    // 旋转
    mat<4, 4> R = identity<4>();
    for (int i = 0; i < 3; i++) {
        R[0][i] = x[i];
        R[1][i] = y[i];
        R[2][i] = z[i];
    }

    // 合成MV变换
    return R * T;
}

修改main中矩阵部分

C++
1
2
3
4
5
6
7
// 矩阵用于变换
// mat<4, 4> Model = model_mat();
// mat<4, 4> View = view_mat();
mat<4, 4> MV = mv_mat(eye, center, up);
mat<4, 4> Projection = projection_mat(near, far, l, r, b, t);
mat<4, 4> MVP = Projection * MV;
mat<4, 4> Viewport = viewport_mat(0, 0, width, height, 255);

结果:

head_camera