OpenGL入门——摄像机

发布时间 2023-10-19 23:01:56作者: 一只小瓶子

上一节OpenGL入门——矩阵变换与坐标系统 - 一只小瓶子 - 博客园 (cnblogs.com)通过矩阵变换实现物体移动。OpenGL本身没有摄像机的概念,但是可以通过把场景中的所有物体往相反方向移动,来模拟摄像机的移动。下面介绍一下怎么通过这种方式在OpenGL中配置一个摄像机。

 

一、摄像机/观察空间

把摄像机类比为上一节的观察空间,以摄像机的视角作为场景原点:观察矩阵把所有世界坐标变换到观察坐标。

1. 摄像机位置:摄像机是在世界空间中的一个位置,如(0,0,2)

2. 摄像机方向向量(z轴正方向向量):摄像机观察的方向,即摄像机坐标(0,0,2)指向注视点(场景原点,如:世界坐标原点(0,0,0)),那么它的观察方向是(0,0,-2);但是屏幕的z轴是指向自己的,所以我们也希望摄像机的z轴正方向是与它的观察方向相反,所以指向摄像机z轴正方向的向量实际为(0,0,2),单位化为(0,0,1)

3.摄像机右轴(x轴正方向向量,该向量一定是世界坐标中水平面上的):先取个世界坐标的正向上向量(0,1,0)(注意这个向量不一定与摄像机方向垂直),然后用这个向上向量叉乘2的摄像机方向向量,得到一个与这两个向量都垂直的向量,即摄像机右轴(1,0,0)

4.摄像机上轴(y轴正方向向量):将2摄像机方向向量叉乘3摄像机右轴,可得到与这两个轴都垂直的向量,即摄像机上轴(0,1,0)

    glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 2.0f);//摄像机位置
    glm::vec3 cameraTarget = glm::vec3(0.0f, 0.0f, 0.0f);//摄像机注释点:世界坐标原点
    glm::vec3 cameraDirection = glm::normalize(cameraPos - cameraTarget);//摄像机方向(0,0,1)
    glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);//世界坐标系向上向量
    glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection));//摄像机右轴(1,0,0)
    glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight);//摄像机上轴(0,1,0)

示意图:

 注意:图3的灰色向量(0,1,0)是世界坐标的向上向量,并非图4的摄像机上周(绿色向量),该向量不一定与摄像机z轴垂直。

 

二、LookAt矩阵

LookAt矩阵是3个互相垂直的向量(如:观察空间坐标系统的3个轴R(右轴X)、U(上轴Y)、D(方向向量Z))乘以任意向量(如:观察空间位置P)得到的矩阵。任何坐标与这个矩阵相乘可将其变换到那个坐标空间(如:观察空间)中,LookAt矩阵就是这个作用。 

    glm::mat4 view = glm::mat4(1.0f);//观察矩阵
    view = glm::lookAt(glm::vec3(0.0f, 0.0f, 2.0f),//位置cameraPos
        glm::vec3(0.0f, 0.0f, 0.0f),//目标cameraTarget
        glm::vec3(0.0f, 1.0f, 0.0f));//世界坐标系的向上向量up

 

后面我们会介绍OpenGL怎么通过模拟摄像机场景实现物体的移动