Real-Time Rendering 第一章
Chapter 1 简介 Introduction
实时渲染涉及在计算机上快速制作图像。它是计算机图形中交互性最高的区域。一个图像出现在屏幕上,观看者做出动作或反应,这种反馈会影响接下来生成的内容。这种反应和渲染的循环以足够快的速度发生,以至于观众不会看到单个图像,而是沉浸在一个动态过程中。
图像的显示速率以每秒帧数 (FPS) 或赫兹 (Hz) 为单位。每秒一帧,几乎没有交互感;用户痛苦地等待到每个新图像的到来。在大约 6 FPS 时,交互感开始增强。视频游戏的目标是 30、60、72 或更高的 FPS;在这些速度下,用户专注于行动和反应。
电影放映机以 24 FPS 的速度显示帧,但使用快门系统将每帧显示两到四次以避免闪烁。此刷新率与显示率分开,以赫兹 (Hz) 表示。一个每帧显示3次的快门具有 72 赫兹的刷新率。 LCD 显示器还将刷新率与显示率分开。
以 24 FPS 的速度观看屏幕上显示的图像可能是可以接受的,但更高的速率对于最大限度地缩短响应时间很重要。仅 15 毫秒的时间延迟就会减慢并干扰交互 [1849]。例如,用于虚拟现实的头戴式显示器通常需要 90 FPS 以最大限度地减少延迟。
实时渲染不仅仅是交互性。如果速度是唯一的标准,那么任何快速响应用户命令并在屏幕上绘制任何内容的应用程序都符合条件。实时渲染通常意味着生成三维图像。
交互性和对三维空间的某种连接感是实时渲染的充分条件,但第三个元素已成为其定义的一部分:图形加速硬件。许多人认为 1996 年推出的 3Dfx Voodoo 1 卡是消费级 3D 图形的真正开始 [408]。随着这个市场的飞速发展,现在每台电脑、平板电脑和手机都内置了图形处理器。图 1.1 和图 1.2 显示了一些通过硬件加速实现实时渲染的优秀示例。
图 1.1。 Forza Motorsport 7 的镜头。(图片由 Turn 10 Studios 提供,Microsoft。)
图 1.2。 《巫师3》中渲染的Beauclair城市。(CD PROJEKT®、The Witcher③是CD PROJEKT Capital Group的注册商标。巫师游戏© CD PROJEKT SA由CD PROJEKT SA开发版权所有。巫师游戏根据散文改编Andrzej Sapkowski 的所有其他版权和商标均为其各自所有者的财产。)
图形硬件的进步推动了交互式计算机图形领域研究的爆炸式增长。我们将专注于提供提高速度和改善图像质量的方法,同时描述加速算法和图形 API 的特性和局限性。我们无法深入涵盖每个主题,因此我们的目标是展示关键概念和术语,解释该领域最强大和实用的算法,并提供指向获取更多信息的最佳位置的指针。我们希望我们为您提供理解该领域的工具的尝试被证明是值得您在本书上花费的时间和精力。
1.1 内容概览 Contents Overview
下面是对前面章节的简要概述。
第2章 , 图形渲染管道。实时渲染的核心是获取场景描述并将其转换为我们可以看到的内容的一组步骤。
第3章 , 图形处理单元。现代 GPU 使用固定功能和可编程单元的组合来实现渲染管道的各个阶段。
第 4 章 , 变换。变换是操纵对象的位置、方向、大小和形状以及相机的位置和视图的基本工具。
第5章 , 着色基础知识。讨论开始于材料和灯光的定义及其在实现所需表面外观(无论是逼真的还是风格化的)中的用途。介绍了其他与外观相关的主题,例如通过使用抗锯齿、透明度和伽马校正提供更高的图像质量。
第6章 , 纹理。实时渲染最强大的工具之一是能够在表面上快速访问和显示图像。此过程称为纹理化,并且有多种应用方法。
第7章 ,阴影。为场景添加阴影可以增加真实感和理解力。介绍了用于快速计算阴影的更流行的算法。
第8章 ,光和颜色。在我们执行基于物理的渲染之前,我们首先需要了解如何量化光线和颜色。在我们的物理渲染过程完成后,我们需要将结果数量转换为显示值,考虑屏幕和观看环境的属性。本章涵盖了这两个主题。
第9章 , 基于物理的着色。我们从头开始了解基于物理的着色模型。本章从潜在的物理现象开始,涵盖各种渲染材质的模型,并以将材质混合在一起并对其进行过滤以避免混叠和保持表面外观的方法结束。
第10章 , 局部照明。探索了描绘更精细光源的算法。表面着色考虑到光是由具有特征形状的物理对象发出的。
第11章 , 全局照明。模拟光与场景之间多次交互的算法进一步增加了图像的真实感。我们讨论了环境和方向遮挡以及在漫反射和镜面反射表面上渲染全局照明效果的方法,以及一些有前途的统一方法。
第12章 , 图像空间效果。图形硬件擅长以快速的速度执行图像处理。首先讨论图像过滤和重投影技术,然后我们调查几种流行的后期处理效果:镜头光晕、运动模糊和景深。
第13章 , 超越多边形。三角形并不总是描述对象的最快或最现实的方式。基于使用图像、点云、体素和其他样本集的替代表示各有其优点。
第14章 ,体积和半透明渲染。这里的重点是体积材料表示及其与光源的相互作用的理论和实践。模拟的现象范围从大规模大气效应到细头发纤维内的光散射。
第15章 , 非真实感渲染。尝试使场景看起来逼真只是渲染场景的一种方式。调查了其他风格,例如卡通阴影和水彩效果。还讨论了行和文本生成技术。
第16章 , 多边形技术。几何数据来自广泛的来源,有时需要修改才能快速良好地呈现。介绍了多边形数据表示和压缩的许多方面。
第17章 、曲线和曲面。更复杂的表面表示提供了一些优势,例如能够在质量和渲染速度之间进行权衡、更紧凑的表示和平滑的表面生成。
第18章,管道优化。一旦应用程序运行并使用高效算法,就可以使用各种优化技术使其更快。找到瓶颈并决定如何解决它是这里的主题。还讨论了多处理。
第19章 , 加速算法。完成后,让它快速进行。涵盖了各种形式的剔除和细节渲染级别。
第20章 ,高效着色。场景中的大量灯光会显着降低性能。在已知表面碎片可见之前完全遮蔽它们是浪费周期的另一个来源。我们探索了多种方法来解决这些和其他形式的着色效率低下问题。
第21章 ,虚拟和增强现实。这些领域具有以快速和一致的速度有效地生成逼真图像的特殊挑战和技术。
第22章 , 交叉测试方法。相交测试对于渲染、用户交互和碰撞检测很重要。此处提供了针对常见几何相交测试的各种最有效算法的深入介绍。
第23章 ,图形硬件。这里的重点是颜色深度、帧缓冲区和基本架构类型等组件。提供了代表性 GPU 的案例研究。
第24章 , 未来。猜一猜(我们猜)。
由于篇幅限制,我们在 realtimerendering.com 上制作了一个关于碰撞检测的免费章节,以及关于线性代数和三角学的附录。
1.2 符号和定义 Notation and Definitions
首先,我们将解释本书中使用的数学符号。有关本节和本书中使用的许多术语的更详尽解释,请访问 realtimerendering.com 获取我们的线性代数附录。
1.2.1 数学符号 Mathematical Notation
表 1.1 总结了我们将使用的大部分数学符号。此处将详细介绍其中的一些概念。
需要注意的是,表中的规则有一些例外,主要是使用在文献中已经非常明确建立的符号来表示着色方程(shading equations),例如\(L\)表示辐射度(radiance), \(E\)表示辐照度(irradiance),\(\sigma_{s}\)表示散射系数(scattering coefficient)。
角度(angles)和标量(scalars)取自 \(R\),即它们是实数。向量(vectors)和点(points)用粗体小写字母表示,这些分量(Components)被写作
也就是列向量格式(column vector),这是计算机图形世界中常用的格式。有些地方我们用\(\left(v_{x}, v_{y}, v_{z}\right)^{T}\)代替形式上更正确的,\(\left(v_{x}, v_{y}, v_{z}\right)^{T}\)因为前者更容易阅读。
类型(Type) | 符号(Notation) | 例子(Examples) |
---|---|---|
角度(angle) | 小写希腊文(lowercase | \(\alpha_{i}, \phi, \rho, \eta, \gamma_{242}, \theta\) |
标量(scalar) | 小写斜体(lowercase | \(a, b, t, u_{k}, v, w_{i j}\) |
向量或点(vector or point) | 小写粗体(lowercase bold) | \(\mathbf{a}, \mathbf{u}, \mathbf{v}_{s}, \mathbf{h}(\rho), \mathbf{h}_{z}\) |
矩阵(matrix) | 大写粗体(capital bold) | \(\mathbf{T}(t), \mathbf{X}, \mathbf{R}_{x}(\rho)\) |
平面(plane) | \(\mathbf{v}=\left(v_{x} v_{y} v_{z} 0\right)^{T}\): 一个向量+一个标量 | \(\pi: \mathbf{n} \cdot \mathbf{x}+d=0\) \(\pi_{1}: \mathbf{n}_{1} \cdot \mathbf{x}+d_{1}=0\) |
三角形(triangle) | 三个点(\(\mathbf{v}=\left(v_{x} v_{y} v_{z} 0\right)^{T}\) 3 points) | \(\Delta \mathbf{v}_{0} \mathbf{v}_{1} \mathbf{v}_{2}, \Delta \mathbf{c b a}\) |
线段(line segment) | 两个点 | \(\mathbf{u v}, \mathbf{a}_{i} \mathbf{b}_{j}\) |
几何实体(geometric entity) | 大写斜体(capital italic) | \(A_{O B B}, T, B_{A A B B}\) |
表1.1. 本书使用的数学符号总结
这里使用齐次表示法(homogeneous notation),坐标值由四个值表示 \(\mathbf{v}=\left(v_{x} v_{y} v_{z} v_{w}\right)^{T}\),向量是,\(\mathbf{v}=\left(v_{x} v_{y} v_{z} 0\right)^{T}\)点是 。有\(\mathbf{v}=\left(v_{x} v_{y} v_{z} 1\right)^{T}\)时候我们只用三维向量和点,有时候我们只用三维向量和点,但我们会尝试避免产生歧义。对于矩阵运算,向量和点使用相同的符号是极有利的。更多信息请参见 第4章 有关转换(Transform)的部分。在某些算法中,使用数字索引而不是 会更\(x, y, z\)方便,例如。向量和\(\mathbf{v}=\left(v_{0} v_{1} v_{2}\right)^{T}\)点的所有这些规则也适用于二维向量。在这种情况下,我们只需简单地跳过三维向量的最后一个分量即可。
矩阵(Matrix)值得多说几句。常用的矩阵大小为 2×2、3×3 和 4×4。我们将复习一下书写3×3矩阵\(M\)的方式,并且很容易将此过程扩展到其他大小的矩阵。$\mathbf{M} $的(标量)元素表示为 \(m_{i j}\),\(0 \leq(i, j) \leq 2\) ,其中 \(i\) 表示行 (row), \(j\) 表示列 (column),如公式 \(1.1\) 所示:
对于 \(3 \times 3\) 矩阵,公式 \(1.2\) 中使用了以下符号,用于从矩阵 $\mathbf{M} $分离向量: \(m_{, j}\) 表示第 \(j\) 列向量, \(m_{i}\) 表示第 \(i\) 行向量 (以列向量形式)。与向量和点一样,也可以使用 \(x, y, z\) (有时用 \(w\) ) 对列向量进行索引,如果这样更方便的话:
平面记为 \(\pi: \mathbf{n} \cdot \mathbf{x}+d=0\) 其中包含其数学公式、平面法线 \(\mathbf{n}\) 和标量 \(d\) 。法线是描述平面面向哪个方向的向量。更一般地 (例如对弯曲 表面),法线描述了表面上特定点的指向方向。对于一个平面来说,同一法线恰好适用于该平面的所有点。 \(\pi\) 是平面的常用数学符号。 平面 \(\pi\) 将空间划分为正半空间 \(\mathbf{n} \cdot \mathbf{x}+d>0\) 和负半空间 \(\mathbf{n} \cdot \mathbf{x}+d<0\) 。所有其他点都位于该平面上。
三角形可以由三个点 \(v_{0}, v_{1}\) 和 \(v_{2}\) 定义,并由 \(\Delta \mathbf{v}_{0} \mathbf{v}_{1} \mathbf{v}_{2}\) 表示。
表1.2 一些数学运算符的符号
运算符(Operator) | 描述(Description) | |
---|---|---|
1: | \(.\) | 点积(dot product) |
2: | \(\times\) | 叉积(cross product) |
3: | \(\mathbf{v}^{T}\) | 向量\(v\)的转置 |
4: | \(\perp\) | 单目垂直点积运算符(the unary, perp dot product operator) |
5: | $ | \cdot |
6: | $ | \cdot |
7: | \(|\cdot|\) | 范数(模和长度是它的特例)(length (or norm) of argument) |
8: | \(x^{+}\) | \(x\)最小值限制为0(clamping x to 0) |
9: | \(x^{\mp}\) | \(x\)值限制在0和1之间(clamping x between 0 and 1) |
10: | \(n !\) | 阶乘(factorial) |
11: | \(\left(\begin{array}{l}n \\ k\end{array}\right)\) | 二项式系数(binomial coeffiffifficients) |
表1.2 列出了一些其他的数学运算符及其表示法。点乘(dot),叉乘(cross),行列式(determinant)和长度运算符(length operators)在 realtimerendering.com 上可下载的线性代数附录中进行了说明。转置运算符(transpose operator)将列向量转换为行向量,反之亦然。因此,可以将列向量缩写为 \(\mathbf{v}=\left(v_{x} v_{y} v_{z}\right)^{T}\) 。Graphics Gems IV [735]中引入的运算符4 \((\perp)\) 是二维向量上的单目运算符, 使郂算符作用于向量 \(\mathbf{v}=\left(v_{x} v_{y}\right)^{T}\) 可以得出垂直于 \(\mathbf{v}\) 的向量,即 \(\mathbf{v} \perp=\left(-v_{y} v_{x}\right)^{T}\) 。我们使用 \(|a|\) 表示标量 \(a\) 的绝对值,而 \(|\mathbf{A}|\) 表示矩 阵 \(\mathbf{A}\) 的行列式。有时,我们也使用 \(|\mathbf{A}|=|\mathbf{a} \mathbf{b} \mathbf{c}|=d e t( \mathbf{a}, \mathbf{b}, \mathbf{c})\) ,其中 \(\mathbf{a}, \mathbf{b}\) 和 \(\mathbf{c}\) 是矩阵 \(\mathbf{A}\) 的列向量
运算符8 \(\left(x^{+}\right)\)和 \(9\left(x^{\mp}\right)\) 是限制 (clamping) 运算符,通常用于着色计算中。运算符8 \(\left(x^{+}\right)\)将负值限制为 0 :
运算符 \(9\left(x^{\mp}\right)\) 将值限制在0和1之间:
第 10 个运算符,阶乘,定义如下,注意 \(0 !=1\) :
如公式1.6 所示,定义第11个运算符,即二项式因子:
表1.3 一些特殊数学函数的符号
函数(Function) | 描述(Description) | |
---|---|---|
1: | \(\operatorname{atan} 2(y, x)\) | 二值反正切(two-value arctangent) |
2: | \(\log (n)\) | n 的自然对数(natural logarithm of n) |
进一步地,我们将平面 \(x=0 , y=0\) 和 \(z=0\) 称为坐标平面(coordinate planes)或轴对齐平面 (axis-aligned planes)。 \(\mathbf{e}_{x}=\left(\begin{array}{lll}1 & 0 & 0\end{array}\right)^{T}, \mathbf{e}_{y}=\left(\begin{array}{lll}0 & 1 & 0\end{array}\right)^{T}\) 和 \(\mathbf{e}_{z}=\left(\begin{array}{lll}0 & 0 & 1\end{array}\right)^{T}\) 的轴称为主轴 (main axes) 或主轴方向,它们分别单独称为 \(\mathrm{x}\) 轴 \((\mathrm{x}\)-axis \()\) , \(\mathrm{y}\) 轴 (y-axis) 和z轴 (z-axis) 。这组轴通常称为标准基 (standard basis) 。除非另有说明,我们将使用正交基 (orthonormal basis,由相互垂直的单位向量组成)。
包含 \(a\) 和 \(b\) 以及两者之间的所有数字的范围的表示法是 \([a, b]\) 。如果我们想要 \(a\) 和 \(b\) 之间的所有数字,而不是 \(a\) 和 \(b\) 本身,那么我们写 \((a, b)\) 。 也可以将它们组合起来,例如 \([a, b)\) 表示 \(a\) 和 \(b\) 之间的所有数字,包括 \(a\) 但不包括 \(b\) 。
本书中将经常使用C数学函数 \(\operatorname{atan} 2(y, x)\) ,因此需要引起注意。它是数学函数 \(\arctan (x)\) 的扩展。它们之间的主要区别是 \(-\frac{\pi}{2}<\arctan (x)<\frac{\pi}{2}\) 与 \(0 \leq \operatorname{atan} 2(y, x)<2 \pi\) ,并且在后一个函数中添加了一个额外的参数。
\(arctan\) 的常见用法是计算 \(\arctan (y / x)\) ,但是当 \(\mathrm{x}=0\) 时,会有除以零的错误。atan \(2(y, x)\) 的额外参数就避免了这种情况。
在本书中,符号 \(\log (n)\) 始终表示自然对数 \(\log _{e}(n)\) ,而不是以10为底的对数 \(\log _{10}(n)\) 。
我们使用右手坐标系,因为这是计算机图形学领域中三维几何图形的标准系统。
颜色由三维向量表示,例如(红色,绿色,蓝色),其中每个元素的范围为 \([0,1]\) 。
1.2.2 几何定义 Geometrical Definitions
几乎所有图形硬件都使用的基本渲染图元(也称为绘图图元)是点、线和三角形。
在本书中,我们将几何实体的集合称为模型或对象。场景是模型的集合,其中包含要渲染的环境中包含的所有内容。场景还可以包括材质描述、照明和查看规范。
对象的示例是汽车、建筑物,甚至是一条线。在实践中,一个对象通常由一组绘图基元组成,但情况并非总是如此;一个对象可能有更高级的几何表示,例如贝塞尔曲线或曲面,或细分曲面。此外,对象可以由其他对象组成,例如,汽车对象包括四个门对象、四个车轮对象等。
1.2.3 着色 Shading
遵循完善的计算机图形用法,本书中源自“着色”、“着色器”和相关词的术语用于指代两个不同但相关的概念:计算机生成的视觉外观(例如,“着色模型”、“着色方程”、“卡通着色”)或渲染系统的可编程组件(例如,“顶点着色器”、“着色语言”)。在这两种情况下,预期的含义都应该从上下文中明确。
进一步阅读和资源
我们可以为您推荐的最重要的资源是本书的网站:realtimerendering.com。它包含指向与每一章相关的最新信息和网站的链接。实时渲染领域正在以实时速度变化。在本书中,我们试图关注基本概念和不太可能过时的技术。在网站上,我们有机会展示与当今软件开发人员相关的信息,并且我们有能力使其保持最新状态。