mirror of
https://github.com/LearnOpenGL-CN/LearnOpenGL-CN.git
synced 2025-08-23 04:35:28 +08:00
Fix all the titles
This commit is contained in:
@@ -10,13 +10,13 @@
|
||||
|
||||
本节我们将会讨论如何在OpenGL中模拟一个摄像机,将会讨论FPS风格的可自由在3D场景中移动的摄像机。我们也会讨论键盘和鼠标输入,最终完成一个自定义的摄像机类。
|
||||
|
||||
### 摄像机/观察空间(Camera/View Space)
|
||||
## 摄像机/观察空间
|
||||
|
||||
当我们讨论摄像机/观察空间的时候,是我们在讨论以摄像机的透视图作为场景原点时场景中所有可见顶点坐标。观察矩阵把所有的世界坐标变换到观察坐标,这些新坐标是相对于摄像机的位置和方向的。定义一个摄像机,我们需要一个摄像机在世界空间中的位置、观察的方向、一个指向它的右测的向量以及一个指向它上方的向量。细心的读者可能已经注意到我们实际上创建了一个三个单位轴相互垂直的、以摄像机的位置为原点的坐标系。
|
||||
当我们讨论摄像机/观察空间(Camera/View Space)的时候,是我们在讨论以摄像机的透视图作为场景原点时场景中所有可见顶点坐标。观察矩阵把所有的世界坐标变换到观察坐标,这些新坐标是相对于摄像机的位置和方向的。定义一个摄像机,我们需要一个摄像机在世界空间中的位置、观察的方向、一个指向它的右测的向量以及一个指向它上方的向量。细心的读者可能已经注意到我们实际上创建了一个三个单位轴相互垂直的、以摄像机的位置为原点的坐标系。
|
||||
|
||||

|
||||
|
||||
#### 1. 摄像机位置
|
||||
### 1. 摄像机位置
|
||||
|
||||
获取摄像机位置很简单。摄像机位置简单来说就是世界空间中代表摄像机位置的向量。我们把摄像机位置设置为前面教程中的那个相同的位置:
|
||||
|
||||
@@ -28,7 +28,7 @@ glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
|
||||
|
||||
不要忘记正z轴是从屏幕指向你的,如果我们希望摄像机向后移动,我们就往z轴正方向移动。
|
||||
|
||||
#### 2. 摄像机方向
|
||||
### 2. 摄像机方向
|
||||
|
||||
下一个需要的向量是摄像机的方向,比如它指向哪个方向。现在我们让摄像机指向场景原点:(0, 0, 0)。用摄像机位置向量减去场景原点向量的结果就是摄像机指向向量。由于我们知道摄像机指向z轴负方向,我们希望方向向量指向摄像机的z轴正方向。如果我们改变相减的顺序,我们就会获得一个指向摄像机正z轴方向的向量(译注:注意看前面的那个图,所说的「方向向量/Direction Vector」是指向z的正方向的,而不是摄像机所注视的那个方向):
|
||||
|
||||
@@ -41,7 +41,7 @@ glm::vec3 cameraDirection = glm::normalize(cameraPos - cameraTarget);
|
||||
|
||||
方向向量(Direction Vector)并不是最好的名字,因为它正好指向从它到目标向量的相反方向。
|
||||
|
||||
#### 3. 右轴(Right axis)
|
||||
### 3. 右轴
|
||||
|
||||
我们需要的另一个向量是一个**右向量(Right Vector)**,它代表摄像机空间的x轴的正方向。为获取右向量我们需要先使用一个小技巧:定义一个**上向量(Up Vector)**。我们把上向量和第二步得到的摄像机方向向量进行叉乘。两个向量叉乘的结果就是同时垂直于两向量的向量,因此我们会得到指向x轴正方向的那个向量(如果我们交换两个向量的顺序就会得到相反的指向x轴负方向的向量):
|
||||
|
||||
@@ -50,7 +50,7 @@ glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||
glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection));
|
||||
```
|
||||
|
||||
#### 4. 上轴(Up axis)
|
||||
#### 4. 上轴
|
||||
|
||||
现在我们已经有了x轴向量和z轴向量,获取摄像机的正y轴相对简单;我们把右向量和方向向量(Direction Vector)进行叉乘:
|
||||
|
||||
@@ -60,7 +60,7 @@ glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight);
|
||||
|
||||
在叉乘和一些小技巧的帮助下,我们创建了所有观察/摄像机空间的向量。对于想学到更多数学原理的读者,提示一下,在线性代数中这个处理叫做[Gram-Schmidt(葛兰—施密特)正交](http://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process)。使用这些摄像机向量我们就可以创建一个**LookAt**矩阵了,它在创建摄像机的时候非常有用。
|
||||
|
||||
### Look At
|
||||
## Look At
|
||||
|
||||
使用矩阵的好处之一是如果你定义了一个坐标空间,里面有3个相互垂直的轴,你可以用这三个轴外加一个平移向量来创建一个矩阵,你可以用这个矩阵乘以任何向量来变换到那个坐标空间。这正是LookAt矩阵所做的,现在我们有了3个相互垂直的轴和一个定义摄像机空间的位置坐标,我们可以创建我们自己的LookAt矩阵了:
|
||||
|
||||
@@ -100,7 +100,7 @@ view = glm::lookAt(glm::vec3(camX, 0.0, camZ), glm::vec3(0.0, 0.0, 0.0), glm::ve
|
||||
|
||||
这一小段代码中,摄像机围绕场景转动。自己试试改变半径和位置/方向参数,看看LookAt矩阵是如何工作的。同时,这里有[源码](http://learnopengl.com/code_viewer.php?code=getting-started/camera_circle)、[顶点](http://learnopengl.com/code_viewer.php?code=getting-started/coordinate_systems&type=vertex)和[片段](http://learnopengl.com/code_viewer.php?code=getting-started/coordinate_systems&type=fragment)着色器。
|
||||
|
||||
## 自由移动
|
||||
# 自由移动
|
||||
|
||||
让摄像机绕着场景转很有趣,但是让我们自己移动摄像机更有趣!首先我们必须设置一个摄像机系统,在我们的程序前面定义一些摄像机变量很有用:
|
||||
|
||||
@@ -200,7 +200,7 @@ while(!glfwWindowShouldClose(window))
|
||||
|
||||
至此,你可以同时向多个方向移动了,并且当你按下按钮也会立刻运动了。如遇困难查看[源码](http://learnopengl.com/code_viewer.php?code=getting-started/camera_keyboard)。
|
||||
|
||||
### 移动速度
|
||||
## 移动速度
|
||||
|
||||
目前我们的移动速度是个常量。看起来不错,但是实际情况下根据处理器的能力不同,有的人在同一段时间内会比其他人绘制更多帧。也就是调用了更多次`do_movement`函数。每个人的运动速度就都不同了。当你要发布的你应用的时候,你必须确保在所有硬件上移动速度都一样。
|
||||
|
||||
@@ -240,15 +240,15 @@ void Do_Movement()
|
||||
现在我们有了一个在任何系统上移动速度都一样的摄像机。这里是源码。我们可以看到任何移动都会影响返回的`deltaTime`值。
|
||||
|
||||
|
||||
## 自由观看
|
||||
# 视角移动
|
||||
|
||||
只用键盘移动没什么意思。特别是我们还不能转向。是时候使用鼠标了!
|
||||
|
||||
为了能够改变方向,我们必须根据鼠标的输入改变`cameraFront`向量。然而,根据鼠标旋转改变方向向量有点复杂,需要更多的三角学知识。如果你对三角学知之甚少,别担心,你可以跳过这一部分,直接复制粘贴我们的代码;当你想了解更多的时候再回来看。
|
||||
|
||||
### 欧拉角
|
||||
## 欧拉角
|
||||
|
||||
欧拉角是表示3D空间中可以表示任何旋转的三个值,由莱昂哈德·欧拉在18世纪提出。有三种欧拉角:俯仰角(Pitch)、偏航角(Yaw)和滚转角(Roll),下面的图片展示了它们的含义:
|
||||
欧拉角(Euler Angle)是表示3D空间中可以表示任何旋转的三个值,由莱昂哈德·欧拉在18世纪提出。有三种欧拉角:俯仰角(Pitch)、偏航角(Yaw)和滚转角(Roll),下面的图片展示了它们的含义:
|
||||
|
||||

|
||||
|
||||
@@ -293,7 +293,7 @@ direction.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw));
|
||||
|
||||
这样我们就有了一个可以把俯仰角和偏航角转化为用来自由旋转的摄像机的3个维度的方向向量了。你可能会奇怪:我们怎么得到俯仰角和偏航角?
|
||||
|
||||
### 鼠标输入
|
||||
## 鼠标输入
|
||||
|
||||
偏航角和俯仰角是从鼠标移动获得的,鼠标水平移动影响偏航角,鼠标垂直移动影响俯仰角。它的思想是储存上一帧鼠标的位置,在当前帧中我们当前计算鼠标位置和上一帧的位置相差多少。如果差别越大那么俯仰角或偏航角就改变越大。
|
||||
|
||||
@@ -426,7 +426,7 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
|
||||
现在我们可以自由的在3D场景中移动了!如果你遇到困难,[这是](http://www.learnopengl.com/code_viewer.php?code=getting-started/camera_mouse)源码。
|
||||
|
||||
### 缩放
|
||||
## 缩放
|
||||
|
||||
我们还要往摄像机系统里加点东西,实现一个缩放接口。前面教程中我们说视野(Field of View或fov)定义了我们可以看到场景中多大的范围。当视野变小时可视区域就会减小,产生放大了的感觉。我们用鼠标滚轮来放大。和鼠标移动、键盘输入一样我们需要一个鼠标滚轮的回调函数:
|
||||
|
||||
@@ -467,7 +467,7 @@ glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
注意,使用欧拉角作为摄像机系统并不完美。你仍然可能遇到[万向节死锁](http://en.wikipedia.org/wiki/Gimbal_lock)。最好的摄像机系统是使用四元数的,后面会有讨论。
|
||||
|
||||
## 摄像机类
|
||||
# 摄像机类
|
||||
|
||||
接下来的教程我们会使用一个摄像机来浏览场景,从各个角度观察结果。然而由于一个摄像机会占教程的很大的篇幅,我们会从细节抽象出创建一个自己的摄像机对象。与着色器教程不同我们不会带你一步一步创建摄像机类,如果你想知道怎么工作的的话,只会给你提供一个(有完整注释的)源码。
|
||||
|
||||
|
Reference in New Issue
Block a user