source/24-hud-revisited.md

This commit is contained in:
Huangshize
2018-06-23 19:26:27 +08:00
parent de8392585b
commit 5567cc3907
2 changed files with 22 additions and 22 deletions

View File

@@ -1,24 +1,24 @@
# 镜头Camera # 摄像机Camera
在这个章节我们将学到如何渲染3D场景的画面这个能力就像一个镜头可以在3D世界穿梭然而实际上是用来说明他的一种编程语言。 在这个章节我们将学到如何渲染3D场景的画面这个能力就像一个摄像机可以在3D世界穿梭然而实际上是用来说明他的一种编程语言。
但是如果你尝试在OpenGL寻找中这些特定的镜头功能,你会发现这根本不是镜头,换句话说镜头一直是固定住的,以屏幕\(0, 0, 0\)的位置为中心点 但是如果你尝试在OpenGL寻找中这些特定的摄像机功能,你会发现这根本不是摄像机,换句话说摄像机一直是固定住的,以屏幕\(0, 0, 0\)的位置为中心点
之所以这样,我们应该模拟出一个镜头可以在三维度空间中移动的镜头。但是如何做到呢?但是镜头是不能移动的我们必须要移动全部的实体在我们的3D世界中。换句话说如果移动不了镜头我们得移动整个世界。 之所以这样,我们应该模拟出一个摄像机可以在三维度空间中移动的摄像机。但是如何做到呢?但是摄像机是不能移动的我们必须要移动全部的实体在我们的3D世界中。换句话说如果移动不了摄像机我们得移动整个世界。
因此假设我们沿着Z轴移动镜头从\(Cx, Cy, Cz\)到\(Cx, Cy, Cz+dz\),从而靠近在\(Ox, Oy, Oz\)放置的目标 因此假设我们沿着Z轴移动摄像机从\(Cx, Cy, Cz\)到\(Cx, Cy, Cz+dz\),从而靠近在\(Ox, Oy, Oz\)放置的目标
![镜头的运动](_static/08/camera_movement.png) ![摄像机的运动](_static/08/camera_movement.png)
我们将要做的是如何精确的移动镜头移动到相反的方向\(在我们的3D空间中的所有物体\)。想想看,其实就像物体在跑步机上跑步一样。 我们将要做的是如何精确的移动摄像机移动到相反的方向\(在我们的3D空间中的所有物体\)。想想看,其实就像物体在跑步机上跑步一样。
![实际的运动](_static/08/actual_movement.png) ![实际的运动](_static/08/actual_movement.png)
镜头可以沿着三个轴\(x, y and z\),也可以沿着他们旋转\(滚动, 俯视和偏斜"yaw"\). 摄像机可以沿着三个轴\(x, y and z\),也可以沿着他们旋转\(滚动, 俯视和偏斜"yaw"\).
![侧倾和偏斜](_static/08/roll_pitch_yaw.png) ![侧倾和偏斜](_static/08/roll_pitch_yaw.png)
所以从基本上我们必须做的就是让移动和旋转对于我们所设置的3D世界全部实体。我们应该怎么做捏答案是用另外一种转化方法把他变化所有在镜头运动方向上相反的顶点,从而根据镜头的旋转进而旋转他们。当然,这将要用另外一个矩阵,所谓的视图矩阵来完成。这个矩阵首先执行平移,然后沿着轴线进行旋转。 所以从基本上我们必须做的就是让移动和旋转对于我们所设置的3D世界全部实体。我们应该怎么做捏答案是用另外一种转化方法把他变化所有在摄像机运动方向上相反的顶点,从而根据摄像机的旋转进而旋转他们。当然,这将要用另外一个矩阵,所谓的视图矩阵来完成。这个矩阵首先执行平移,然后沿着轴线进行旋转。
让我们看看如何构造这个矩阵。如果你记得变化章节第6章的转换方程式这样的: 让我们看看如何构造这个矩阵。如果你记得变化章节第6章的转换方程式这样的:
@@ -28,13 +28,13 @@ $$Transf = \lbrack ProjMatrix \rbrack \cdot \lbrack TranslationMatrix \rbrack \c
$$Transf = \lbrack ProjMatrix \rbrack \cdot \lbrack ViewMatrix \rbrack \cdot \lbrack TranslationMatrix \rbrack \cdot \lbrack RotationMatrix \rbrack \cdot \lbrack ScaleMatrix \rbrack = \lbrack ProjMatrix \rbrack \cdot \lbrack ViewMatrix \rbrack \cdot \lbrack WorldMatrix \rbrack $$ $$Transf = \lbrack ProjMatrix \rbrack \cdot \lbrack ViewMatrix \rbrack \cdot \lbrack TranslationMatrix \rbrack \cdot \lbrack RotationMatrix \rbrack \cdot \lbrack ScaleMatrix \rbrack = \lbrack ProjMatrix \rbrack \cdot \lbrack ViewMatrix \rbrack \cdot \lbrack WorldMatrix \rbrack $$
现在有三个矩阵,我们应该思考一下这些矩阵的生命的周期。在我们的游戏运行的时候,投影矩阵不应该改变的太多,在情况最不好的时候,每个渲染都要调用才可能改变一次。如果镜头移动,则视图矩阵可以在每一次渲染改变一次。视图矩阵每`GameItem`项改变一次,所以每次渲染调用都会改变许多次。 现在有三个矩阵,我们应该思考一下这些矩阵的生命的周期。在我们的游戏运行的时候,投影矩阵不应该改变的太多,在情况最不好的时候,每个渲染都要调用才可能改变一次。如果摄像机移动,则视图矩阵可以在每一次渲染改变一次。视图矩阵每`GameItem`项改变一次,所以每次渲染调用都会改变许多次。
因此,如何把每一个矩阵推到顶点着色器呢?您可能会看到一些代码,使用三个统一的每一个矩阵,但原则上,最有效的方法是结合投影和视图矩阵,我们称之为`PV`矩阵,并推动`world``PV`矩阵到我们的着色器。通过这种方法,我们将有可以与世界坐标一起进行并且可以避免一些额外的运算。 因此,如何把每一个矩阵推到顶点着色器呢?您可能会看到一些代码,使用三个统一的每一个矩阵,但原则上,最有效的方法是结合投影和视图矩阵,我们称之为`PV`矩阵,并推动`world``PV`矩阵到我们的着色器。通过这种方法,我们将有可以与世界坐标一起进行并且可以避免一些额外的运算。
实际上,最方便的方法是将视图与世界矩阵相结合。为什么会这样?因为要记住整个镜头的概念就是戏法但要做的是推动整个世界来模拟世界的位移和只显示一小部分的3D世界。因此如果直接联合世界坐标一起工作这样可能会引起远离中心点的世界坐标系会遇到一些精度的问题。如果在所谓的镜头空间中工作利用点的性质,虽然远离世界的中心点,但也靠近镜头。可以将视图和世界矩阵相结合的矩阵通常被称为模型视图矩阵。 实际上,最方便的方法是将视图与世界矩阵相结合。为什么会这样?因为要记住整个摄像机的概念就是戏法但要做的是推动整个世界来模拟世界的位移和只显示一小部分的3D世界。因此如果直接联合世界坐标一起工作这样可能会引起远离中心点的世界坐标系会遇到一些精度的问题。如果在所谓的摄像机空间中工作利用点的性质,虽然远离世界的中心点,但也靠近摄像机。可以将视图和世界矩阵相结合的矩阵通常被称为模型视图矩阵。
让我们开始修改代码来支持镜头。首先,先创建一个新的类,称为`Camera`,它将确保持相机的位置与旋转的方向。该类将提供新位置或旋转方向\(`setPosition` or `setRotation`\)的方法,或在当前状态\(`movePosition` and `moveRotation`\)上用偏移量更新这些值。 让我们开始修改代码来支持摄像机。首先,先创建一个新的类,称为`Camera`,它将确保持相机的位置与旋转的方向。该类将提供新位置或旋转方向\(`setPosition` or `setRotation`\)的方法,或在当前状态\(`movePosition` and `moveRotation`\)上用偏移量更新这些值。
```java ```java
@@ -121,13 +121,13 @@ public Matrix4f getViewMatrix(Camera camera) {
} }
``` ```
正如你所看到的,我们首先需要做旋转,然后翻译。如果我们做相反的事情,我们不会沿着镜头位置旋转,而是沿着坐标原点旋转。请注意,在`Camera`类的`movePosition`方法中我们不只是简单地增加相机位置的偏移量。我们还考虑了沿Y轴的旋转偏航以便计算最终位置。如果我们只是通过偏移来增加相机的位置相机就不会朝着它的方向移动。 正如你所看到的,我们首先需要做旋转,然后翻译。如果我们做相反的事情,我们不会沿着摄像机位置旋转,而是沿着坐标原点旋转。请注意,在`Camera`类的`movePosition`方法中我们不只是简单地增加相机位置的偏移量。我们还考虑了沿Y轴的旋转偏航以便计算最终位置。如果我们只是通过偏移来增加相机的位置相机就不会朝着它的方向移动。
正如你所看到的,我们首先需要做旋转,然后翻译。如果我们做相反的事情,我们不会沿着镜头位置旋转,而是沿着坐标原点旋转。请注意,在“镜头”类的“移动位置”方法中我们不只是简单地增加相机位置的偏移量。我们还考虑了沿Y轴的旋转偏航以便计算最终位置。如果我们只是通过偏移来增加相机的位置相机就不会朝着它的方向移动。 正如你所看到的,我们首先需要做旋转,然后翻译。如果我们做相反的事情,我们不会沿着摄像机位置旋转,而是沿着坐标原点旋转。请注意,在“摄像机”类的“移动位置”方法中我们不只是简单地增加相机位置的偏移量。我们还考虑了沿Y轴的旋转偏航以便计算最终位置。如果我们只是通过偏移来增加相机的位置相机就不会朝着它的方向移动。
除了上面提到的,我们这里没有一个完全自由移动的镜头\(例如如果我们沿着X轴旋转当我们向前移动时镜头不会在空中向上或向下移动\)。这将在后面的章节中完成,因为这有点复杂。 除了上面提到的,我们这里没有一个完全自由移动的摄像机\(例如如果我们沿着X轴旋转当我们向前移动时摄像机不会在空中向上或向下移动\)。这将在后面的章节中完成,因为这有点复杂。
最后,我们将删除以前的方法`getWorldMatrix`,并添加一个新的名为`getModelViewMatrix`的方法。 最后,我们将删除以前的方法`getWorldMatrix`,并添加一个新的名为`getModelViewMatrix`的方法。
@@ -148,7 +148,7 @@ public Matrix4f getModelViewMatrix(GameItem gameItem, Matrix4f viewMatrix) {
这个`getModelViewMatrix`方法将在每个`GameItem`实例中调用,因此我们必须对视图矩阵的副本进行处理,因此在每次调用中都不会积累转换\(记住`Matrix4f`类不是不可变的\). 这个`getModelViewMatrix`方法将在每个`GameItem`实例中调用,因此我们必须对视图矩阵的副本进行处理,因此在每次调用中都不会积累转换\(记住`Matrix4f`类不是不可变的\).
`Renderer`类的`render`方法中,在投影矩阵更新之后,我们只需要根据镜头的更新视图矩阵的值,。 `Renderer`类的`render`方法中,在投影矩阵更新之后,我们只需要根据摄像机的更新视图矩阵的值,。
```java ```java
// Update projection Matrix // Update projection Matrix
@@ -169,14 +169,14 @@ for(GameItem gameItem : gameItems) {
} }
``` ```
就是这样对于基本代码支持镜头的概念。现在我们需要用它。这样可以改变输入处理和更新相机的方式。我们将设置以下控件: 就是这样对于基本代码支持摄像机的概念。现在我们需要用它。这样可以改变输入处理和更新相机的方式。我们将设置以下控件:
* 键“A”和“D”到移动镜头的左边和右边\(x axis\)。 * 键“A”和“D”到移动摄像机的左边和右边\(x axis\)。
* 键“W”和“S”到移动镜头的前面和后面\(z axis\)。 * 键“W”和“S”到移动摄像机的前面和后面\(z axis\)。
* 键“Z”和“X”到移动镜头的上面和下面的\(y axis\)。 * 键“Z”和“X”到移动摄像机的上面和下面的\(y axis\)。
当鼠标按下右键时我们可以使用鼠标位置沿X和Y轴旋转镜头 当鼠标按下右键时我们可以使用鼠标位置沿X和Y轴旋转摄像机
正如你所看到的,我们将首次使用鼠标。我们将创建一个名为`MouseInput`的新类,该类将封装鼠标访问的代码。 正如你所看到的,我们将首次使用鼠标。我们将创建一个名为`MouseInput`的新类,该类将封装鼠标访问的代码。
```java ```java

View File

@@ -1,4 +1,4 @@
#HUD 重温(HUD 重温)- NanoVG #HUD 重温 - NanoVG
在之前的章节中,解释了如何使用正交投影在场景的顶部渲染形状和纹理。 在本章中,我们将学习如何使用 [NanoVG](https://github.com/memononen/nanovg) 库来渲染反锯齿矢量图形以简单的方式构建更复杂的HUD。 在之前的章节中,解释了如何使用正交投影在场景的顶部渲染形状和纹理。 在本章中,我们将学习如何使用 [NanoVG](https://github.com/memononen/nanovg) 库来渲染反锯齿矢量图形以简单的方式构建更复杂的HUD。