【Learn OpenGL 学习笔记】二 · 坐标与摄像机

坐标系统
摄像机

坐标系统

《Unity Shader入门精要》自学笔记(二)矩阵、空间以及获取变换矩阵思路的总结

乐乐大佬这本书真的很适合入门,不仅讲的清楚,图配的也很有助于理解

这两章基本没有什么新知识,基本是在复习之前的东西(我日怎么这么快两年就过去了)

glm::ortho(left, right, bot, top, near, far);
glm::perspective(glm::radians(FOV), (float)width/(float)height, near, far);

唯一不大明白的是,我的代码明明之前 2D 的时候要转置一下变换矩阵,但是进入 3D 引入 MVP 变换之后,反而不转置才能得到正确结果,不知道是哪里漏掉了什么

Z-Buffer

glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

摄像机

摄像机矩阵

文章中介绍了一种构造摄像机矩阵的方法,很巧妙,看起来和乐乐书中提到的两种构造摄像机矩阵的方法中的第一种是一个意思,当时还不明白到底是怎么做到的,现在才知道原来是借了个向量做 cross

由相机的Transform属性得到它3个坐标轴在世界空间中的表示,然后根据前面的方法得出观察变换矩阵

最后要记得乘个 S z S_z Sz = -1的矩阵缩放矩阵来给 z z z分量取个反

在这里插入图片描述
摄像机的三个轴分别为:摄像机拍摄方向反方向的 z 轴、指向摄像机右侧的 x 轴、指向摄像机头顶的 y 轴

glm::mat4 Camera::MyLookAt(glm::vec3 position, glm::vec3 target, glm::vec3 up) {
    
    
    // 1. Camera vector - z
    glm::vec3 camDir = glm::normalize(position - target);

    // 2. Right vector - x
    // 借了个 up(0.0, 1.0, 0.0) 向量用 Cross 得出 x 轴
    // 有一定局限,比如摄像机仰角不能超过 90° 或小于 -90 °
    glm::vec3 camRight = glm::normalize(glm::cross(glm::normalize(up), camDir));

    // 3. Camera up vector - y
    glm::vec3 camUp = glm::normalize(glm::cross(camDir, camRight));

    // 构建矩阵
    glm::mat4 rotationMat = glm::mat4(1.0f);
    glm::mat4 translateMat = glm::mat4(1.0f);

    // ** [col][row]
    rotationMat[0][0] = camRight.x;
    rotationMat[1][0] = camRight.y;
    rotationMat[2][0] = camRight.z;
    rotationMat[0][1] = camUp.x;
    rotationMat[1][1] = camUp.y;
    rotationMat[2][1] = camUp.z;
    rotationMat[0][2] = camDir.x;
    rotationMat[1][2] = camDir.y;
    rotationMat[2][2] = camDir.z;

    translateMat[3][0] = -position.x;
    translateMat[3][1] = -position.y;
    translateMat[3][2] = -position.z;

    // ** 先位移后旋转:构成旋转矩阵的向量需要依赖 position 求值
    return rotationMat * translateMat;
}

这矩阵排列竟然是先列后行

代码中可以直接调用 GLM 写好的 LookAt(camPos, camTarget, up)

鼠标移动旋转相机视角(欧拉角)

  1. 每帧获取鼠标 x 轴和 y 轴上的位移
  2. 计算出 Pitch 和 Yaw 的角度(注意角度的限制)
  3. 使用三角函数重新计算摄像机的方向向量
  4. 更新其余两轴

计算出 Pitch 和 Yaw 的角度

由于使用了(0.0, 1.0, 0.0)求得 x 轴,在俯仰角度超过 90° 或小于 -90° 时会出现翻转现象
所以需要做一个限制

if (Pitch > 89.0f) Pitch = 89.0f;
if (Pitch < -89.0f) Pitch = -89.0f;

使用三角函数重新计算摄像机的方向向量

需要注意的是,虽然摄像机是看向 z 轴的反方向,但 yaw 的旋转起始地依然是 x 轴正方向
如果误将起始地当成了 z 轴反方向,会出现错用 sin 和 cos 的情况
在这里插入图片描述
另外,由于 Pitch 的变化,导致 Yaw 的斜边也发生改变,就有了 * cos(pitch)

	// Front
    glm::vec3 front;
    // *** yaw starts from x-axis
    front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
    front.y = sin(glm::radians(Pitch));
    front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));

    Front = glm::normalize(front);

更新其余两轴

    // Right & Up
    Right = glm::normalize(glm::cross(Front, WorldUp));
    Up = glm::normalize(glm::cross(Right, Front));

鼠标滚轮缩放相机视野

修改 FOV,达到放大缩小的效果
感觉 45 - 90 的范围看着比较舒服

projectionMat = glm::perspective(glm::radians(camera.fov), SCR_WIDTH / SCR_HEIGHT, 0.1f, 100.0f);

猜你喜欢

转载自blog.csdn.net/weixin_44045614/article/details/128060109