LookAt的实现 | Blurred code

LookAt的实现

2019/09/14

LastMod:2019/09/14

Categories: CG

一个物体要在OpenGL中被渲染出现,需要经过经典的MVP变换,主要是从物体坐标系,通过Model Matrix,变换到世界坐标系,然后通过View Matrix,也叫相机坐标系,转换为某个视角所看到的内容,最后通过projection Matrix,做仿射变换,最后还有一步OpenGL隐藏的剪裁步骤,裁减掉不在投影区域内的像素点。

流程图可以看1 流程图

其中,glm::lookat函数是glm库提供的一个工具函数,可以用来计算view matrix。给定三个特殊向量,包括相机的position向量,相机所看的物体的位置target向量以及整个世界坐标系的up向量,可以计算出view矩阵。

view矩阵

其中P是相机的位置向量,U是需要计算的,相机的up向量,R也是需要计算的,相机坐标系的右向量,D是最好计算的,D是direction向量,是从物体到相机的向量。 因此代码可以写成如下,

  //* a solution to glm::lookat
  auto look_at = [](glm::vec3 position, glm::vec3 target,
                           glm::vec3 worldup) -> glm ::mat4 {
    glm::vec3 zaxis = glm::normalize(position - target);    //direction vector
    glm::vec3 xaxis =                                       //right vector
        glm::normalize(glm::cross(glm::normalize(worldup), zaxis));     
    glm::vec3 yaxis = glm::cross(zaxis, xaxis);  // camera up vector

    glm::mat4 trans = glm::mat4(1.0f);
    trans[3][0] = -position.x;
    trans[3][1] = -position.y;
    trans[3][2] = -position.z;

    glm::mat4 rotation = glm::mat4(1.0f);
    rotation[0][0] = xaxis.x;
    rotation[1][0] = xaxis.y;
    rotation[2][0] = xaxis.z;

    rotation[0][1] = yaxis.x;
    rotation[1][1] = yaxis.y;
    rotation[2][1] = yaxis.z;

    rotation[0][2] = zaxis.x;
    rotation[1][2] = zaxis.y;
    rotation[2][2] = zaxis.z;

    return rotation * trans;
  };

  1. reference : https://learnopengl.com/Getting-started/Camera ↩︎