OpenGL LookAt、Camera摄像机

该博客详细介绍了OpenGL中的LookAt函数,用于构建摄像机的视图矩阵。通过摄像机的位置、观察目标和向上方向,解释了如何确定摄像机的前向、右向和上向量,进而构建摄像机的移动和视角旋转。还涉及到欧拉角的概念,并给出了使用欧拉角控制摄像机视角的代码示例。
摘要由CSDN通过智能技术生成

摄像机/观察空间

程序执行效果

程序效果

摄像机代码

// 摄像机
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
ourShader.setMat4("view", view);

实际上就是得到一个View Matrix,这样就可以传送给shader program用于计算从本地坐标系向投影坐标系、剪裁坐标系进行转换。

glm::lookAt(eye, center, up)

eye实际上就是摄像机的位置
center就是摄像机的方向
up就是上轴

eye -> cameraPos
center -> cameraPos + cameraFront
up -> cameraUp

摄像机的位置很好理解,就是3D空间中的一个点P(Vector3{x, y, z})
那么方向的量就是A(Vector3{x, y, z})到B(Vector3{x, y, z})指向(tail, head指向) [下面的代码叫方向向量不恰当,因为是相反的]
我们将两个点的空间坐标通过向量的标准化求得方向(空间的点不是向量,和长度一样是标量):

1、cameraPos:
vec3(0.0, 0.0, 3.0);

2、cameraFront:
vec3(0.0, 0.0, -1.0); // z 轴相反的方向为摄像机向前

3、cameraPos - cameraFront:
v1 = vec3(x: 0.0, y: 0.0, z: 3.0) , v2 = vec3(x: 0.0, y: 0.0, z: -1.0)
(v1) + (-v2) = (0.0, 0.0, 3.0 + -0.0, -0.0, 1.0)
(0.0, 0.0, 4.0)
如果是相加的话:
cameraPos - cameraFront = (0.0, 0.0, 2.0)

4、cameraDirection = glm::normalize(cameraPos + cameraFront) // 也可以不用这样,直接将cameraPos + cameraFront作为方向
模等于0的向量成为0向量,模等于1的向量叫做单位向量。注意零向量的方向是任意的。由一个向量v求与它同方向的单位向量过程称为标准化(normalization),这个单位向量成为标准化向量(normalized vector)。
公式:
vector normalize = v|v| (v≠0)
carmeraDirection = (0.0, 0.0, 1.0)

5、cameraUp
右轴:
我们需要的另一个向量是一个右向量(Right Vector),它代表摄像机空间的x轴的正方向。为获取右向量我们需要先使用一个小技巧:先定义一个上向量(Up Vector)。接下来把上向量和第二步得到的方向向量进行叉乘。两个向量叉乘的结果会同时垂直于两向量,因此我们会得到指向x轴正方向的那个向量(如果我们交换两个向量叉乘的顺序就会得到相反的指向x轴负方向的向量):
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection));
现在我们已经有了x轴向量和z轴向量,获取一个指向摄像机的正y轴向量就相对简单了:我们把右向量和方向向量进行叉乘:
glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight);

cameraUp = cross(cameraDirection, cross(up, cameraDirection))
OpenGL中的`lookAt()`函数主要用于设置观察点、目标点以及视点方向,它是一个非常重要的三维变换函数,常用于创建相机视角。通过指定这三个关键点,可以生成一组矩阵(通常是正交投影矩阵和平行投影矩阵),进而控制摄像机的位置、角度及视野范围。 **基本语法**: ```cpp gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); ``` 这里的参数分别代表: - `eyeX`, `eyeY`, `eyeZ`: 观察点 (camera) 的位置坐标; - `centerX`, `centerY`, `centerZ`: 目标点的位置坐标; - `upX`, `upY`, `upZ`: 表示向上向量,即垂直于观察者视线的一个单位向量,默认值为 (0, 1, 0),通常用于确定垂直于屏幕的方向。 `lookAt()` 函数通过这些参数构建出一个透视或正交视图矩阵,这个矩阵随后会被传递给其他渲染函数如`glMultMatrix()`,用于将场景数据转换到当前视图空间内进行绘制。通过调整观察点、目标点以及向上向量,用户可以动态地改变视角,实现三维图形的全方位展示。 **使用示例**: ```cpp // 创建 OpenGL 环境并初始化上下文... glMatrixMode(GL_MODELVIEW); // 设置模型视图模式 glLoadIdentity(); // 初始化视图矩阵为单位矩阵 // 设置观察点为中心,目标点为正前方,向上向量为默认值 gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0); // 绘制场景... glutSwapBuffers(); ``` 在这个例子中,摄像头位于坐标轴原点上方5单位的地方,朝向原点,并且垂直向量默认指向屏幕顶部。 --- ## 相关问题 - OpenGL lookAt 1. **如何自定义向上向量?** - 可以直接在`lookAt()`函数中修改第三个参数组`upX`, `upY`, `upZ`的值来自定义向上向量,这会影响到相机视角在水平面内的定向。 2. **如何仅更改观察点而不移动目标点?** - 修改`eyeX`, `eyeY`, `eyeZ`即可实现观察点的移动,而保持`centerX`, `centerY`, `centerZ`不变,则目标点不会跟着动。 3. **`lookAt()`函数和`perspective()`函数有何区别?** - `lookAt()`主要用于设定相机的位置、目标点以及视野的方向,它是构建视图矩阵的一部分;`perspective()`则用于创建透视投影矩阵,结合视图矩阵一同完成从世界坐标系到屏幕坐标系的转换过程。两者共同作用决定了最终图像的呈现效果。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值