65.9K
CodeProject 正在变化。 阅读更多。
Home

“相机”以及投影和视图变换(公共领域几何实用程序库)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (3投票s)

2015年5月10日

公共领域

9分钟阅读

viewsIcon

15966

描述了 3D 图形中常用的投影和视图变换,例如透视和正交变换。

引言

本页介绍在使用我的 几何工具库 时指定 3D 图形中投影和视图变换的约定,并解释了常用的图形管线如何变换顶点以帮助绘制三角形、线条和其他图形图元。

最新版本库的源代码可在 [几何工具库项目页面](https://github.com/peteroupc/html3dutil) 获取。

目录

变换概述

大多数现代 3D 渲染引擎都使用以下变换:

  • 世界矩阵将对象的自身坐标转换为世界空间,这是场景中每个对象共享的坐标系。本页不讨论世界矩阵。
  • 视图矩阵将世界空间中的坐标转换为眼睛空间
  • 投影矩阵将眼睛空间中的坐标转换为剪辑空间。如果我们使用“相机”的概念,投影矩阵就像设置相机的焦点和镜头,而视图矩阵就像设置其位置和方向。

正如本页 稍后解释的,这些变换和矩阵仅是为了方便渲染引擎;所有图形管线都期望的是要绘制内容的剪辑空间坐标。管线使用这些坐标及其转换后的窗口坐标在屏幕上进行渲染。

投影变换

投影矩阵将眼睛空间中的坐标转换为剪辑空间

3D 图形中常用的两种投影是透视投影和正交投影,下面将进行介绍。(其他类型的投影,如斜投影和等轴投影,在此不作介绍。)

透视投影

透视投影使 3D 场景具有深度感。在此投影中,近处的物体看起来比相同大小的远处物体更大,使投影类似于我们的眼睛看待世界的方式。

**Two rows of spheres, and a drawing of a perspective view volume.**

**Two rows of spheres, and a side drawing of a perspective view volume.**

3D 场景包含在一个所谓的视锥体中,只有包含在视锥体中的物体才会可见。上图显示了透视视锥体的外观。在此视锥体中,一些绘制的球体不可见,而另一些则可见。

视锥体由六个裁剪平面的六个侧面界定。

  • 近裁剪平面和远裁剪平面放置在距离相机一定距离处。例如,如果近裁剪平面距离 3 个单位,远裁剪平面距离 5 个单位,则视锥体将仅包含距离相机 3 到 5 个单位之间的物体。(严格来说,近裁剪平面不是必需的,但实际上是必需的,以使数学计算正确。)
  • 左、右、上、下裁剪平面构成了视锥体的其他四个侧面。

进一步注意:

  • 上下裁剪平面之间的夹角是投影的视场角。此角度类似于相机的光圈。垂直视场角越大,垂直可见范围就越大。
  • 在透视投影中,视锥体将类似于一个顶部被截断的“金字塔”(一个截头锥体)。近裁剪平面位于被截断的顶部,远裁剪平面位于底部。

透视投影将 3D 坐标转换为剪辑空间中的 4 元素向量。然而,这并不是全部,因为通常情况下,世界空间中平行的线在透视投影中不会显得平行,因此需要额外的数学计算来实现透视效果。这将在 稍后解释

以下方法定义了透视投影。

MathUtil.mat4perspective(fov, aspect, near, far)

此方法返回一个 4x4 矩阵,该矩阵根据视场角和纵横比调整坐标系以实现透视投影,并相应地设置场景的投影矩阵。

  • fov - 垂直视场角(以度为单位)
  • aspect - 场景的纵横比
  • near, far - 从相机到近裁剪平面和远裁剪平面的距离

MathUtil.mat4frustum(left, right, bottom, top, near, far)

此方法返回一个 4x4 矩阵,该矩阵基于边界视锥体的六个裁剪平面的位置来调整坐标系以实现透视投影。它们的位置选择使得结果是透视投影。

  • left, right, bottom, top - 左、右、下、上裁剪平面在近裁剪平面处相交的位置。
  • near, far - 从相机到近裁剪平面和远裁剪平面的距离。

正交投影

正交投影是指左右裁剪平面相互平行,上下裁剪平面相互平行。这导致近裁剪平面和远裁剪平面具有相同的大小,与透视投影不同,并且相同大小的物体不会随着与“相机”的距离而改变大小。

以下方法生成正交投影:

MathUtil.mat4ortho(left, right, bottom, top, near, far)

此方法返回一个 4x4 矩阵,该矩阵调整坐标系以实现正交投影。

  • left - 3D 视图的最左边坐标
  • right - 3D 视图的最右边坐标
  • bottom - 3D 视图的最上边坐标
  • top - 3D 视图的最下边坐标
  • near, far - 从相机到近裁剪平面和远裁剪平面的距离。任一值都可以为负。

MathUtil.mat4ortho2d(left, right, bottom, top)

此方法返回一个 4x4 矩阵,该矩阵调整坐标系以实现二维正交投影。这是一个便捷的方法,对于显示二维视图很有用。mat4ortho2d 方法调用 mat4ortho 并将 nearfar 分别设置为 -11。选择这些值使得 Z 坐标 0 特别适合此投影。

  • left, right, bottom, top - 与 mat4ortho 中的相同。

MathUtil.mat4orthoAspect(left, right, bottom, top, near, far, aspect)

此方法返回一个 4x4 矩阵,该矩阵调整坐标系以实现正交投影,以便在视锥体纵横比和场景纵横比不同时,视图不会被拉伸或压缩。

  • left, right, bottom, top, near, far - 与 setOrtho 中的相同
  • aspect - 视口纵横比

视图变换

视图矩阵将场景中每个对象共享的世界空间坐标转换为眼睛空间(也称为相机空间视图空间)中的坐标,其中“相机”位于坐标系中心:(0, 0, 0)。视图矩阵本质上是旋转相机并将其移动到世界空间中的给定位置。具体来说:

  • 相机旋转以看向场景中的某个对象或位置。这由下面 mat4lookat() 方法中的 lookingAt 参数表示。
  • 相机放置在场景中的某个位置。这由 mat4lookat() 方法中的 eye 参数表示。它也代表上面透视投影中的“眼睛位置”。
  • 相机自行滚动,可能将其侧向或倒置。这由 mat4lookat() 方法中的 up 参数指导。例如,将相机倒置会交换上下裁剪平面的位置,从而使场景视图颠倒。

MathUtil.mat4lookat(eye, lookingAt, up)

此方法允许您根据相机的 P.O.V. 和视图生成视图矩阵。

  • eye - 三个元素的数组(X、Y、Z),表示相机在世界空间中的位置。
  • lookingAt - 三个元素的数组(X、Y、Z),表示相机在世界空间中看向的位置。这是可选的。默认值为 [0, 0, 0]。
  • up - 三个元素的数组(X、Y、Z),表示从相机中心到顶部的向量。这是可选的。默认值为 [0, 1, 0]。

图形系统中的顶点坐标

眼睛空间相机空间世界空间的概念,以及与它们相关的矩阵(如投影视图模型-视图世界矩阵)的使用,仅仅是约定,在许多 3D 图形库中是为了方便而存在的。

当常用的图形管线(不属于相关的 3D 图形库)绘制三角形、线条或点时,它真正期望的是该图元顶点在剪辑空间中的位置。所谓的顶点着色器使用其接收的输入将这些位置传递给图形管线。尽管顶点着色器可以使用投影、视图和世界矩阵来帮助管线找到顶点的剪辑空间坐标,但它不必这样做,并且可以使用不同的范例来实现此目的。例如,可以将已经处于剪辑空间中的顶点坐标传递给顶点着色器,然后它仅输出这些坐标而不进行转换。

顾名思义,剪辑空间坐标用于将图元裁剪到屏幕。每个剪辑空间顶点都处于齐次坐标中,由 X、Y、Z 和 W 坐标组成,其中 X、Y 和 Z 是乘以 W 的。例如,H3DU.MathUtil.mat4perspective 返回的透视矩阵将 W 转换为眼睛空间中的负 Z 坐标,也就是说,它会随着到“眼睛”或“相机”的距离的增加而增加。

为了考虑透视效果,将剪辑空间的 X、Y 和 Z 坐标除以剪辑空间的 W,然后转换为窗口坐标,这大致对应于屏幕像素。窗口坐标的范围将与当前视口相同。视口是矩形,其大小和位置通常以像素表示。

对于 mat4perspective 返回的透视矩阵,将 X、Y 和 Z 坐标除以剪辑空间的 W 会产生这样的效果:随着 W 越来越大(距离“眼睛”或“相机”越来越远),X、Y 和 Z 坐标会越来越接近视图中心。这就是前面提到的透视效果:物体距离“相机”越远,看起来就越小。

其他页面

我在 CodeProject 上的以下页面也讨论了几何工具库,以前称为公共领域 HTML 3D 库:

© . All rights reserved.