目录
坐标系与变换(Coordinate System and Transformation)
Bounding Volume Hierarchy Culling
《GAMES104》渲染系统课程大纲
![](https://i-blog.csdnimg.cn/blog_migrate/de506fc0258674894a8436422eb19fc3.jpeg)
渲染概述
我们首先看到渲染技术的发展
![](https://i-blog.csdnimg.cn/blog_migrate/cf3e867ba665ceb69385335ea2ae3dff.jpeg)
以及作为游戏引擎渲染基础的图形学理论
![](https://i-blog.csdnimg.cn/blog_migrate/5d65fdb069c048ab18e913d8b7f48990.jpeg)
游戏渲染面临的挑战
一个容器中同一时刻有大量的游戏对象需要进行渲染,并且不同对象渲染的形式、算法还有所差异,这些使得游戏的绘制系统变得非常复杂;其次,游戏引擎的渲染还要与当代的硬件适配;同时,游戏引擎需要保证渲染的稳定性,即使进入非常巨大复杂的场景,也要在至少1/30ms内完成绘制,随着玩家需求的提高,这一时间甚至可能被缩短到1/60ms、1/120ms之内;游戏引擎的渲染还要考虑到可用的计算资源,一般渲染可用资源只能占到百分之十左右,还需预留资源用于GamePlay等系统。
![](https://i-blog.csdnimg.cn/blog_migrate/da4df8899a256042651c0e62a9afdc80.jpeg)
渲染流水线
这一过程将一个个顶点数据进行投影(Projection)、光栅化(Rasterization),形成许多像素点,许许多多的像素点便组成了我们看到的画面。
![](https://i-blog.csdnimg.cn/blog_migrate/71a1609e4220240760d239af8c0c4311.jpeg)
着色
在着色的时候我们会对某些常量/变量进行访问,比如说屏幕长和宽的像素数量;会进行一些数学运算,比如计算光照时寻找法线的位置,以及光线的衰减程度;还会进行纹理采样等计算。
![](https://i-blog.csdnimg.cn/blog_migrate/f07ac69126250258090b0bdabb9f6034.jpeg)
纹理采样(Texture Sampling)
为了防止走样现象,也就是为了防止在游戏中当我们的视角由近及远移动时产生的画面抖动,我们会在层级与层级之间进行插值,还会在每个层级中的相邻像素点之间进行插值,构成多级渐远纹理(Mipmap)。
![](https://i-blog.csdnimg.cn/blog_migrate/9e1e805acf311885fa093049704f69dc.jpeg)
GPU的概念
对于图形程序中的复杂计算,我们交由另一独立硬件处理——GPU,也正是GPU不断的发展进步,才有了现在越来越精致的画面。
SIMD and SIMT
- SIMD指单指令多数据流(Single Instruction Multiple Data),一般是用于处理矩阵变换等复杂运算
- SIMT指单指令多线程(Single Instruction Multiple Threads),一条指令交由多个线程处理,这即是GPU算力远高于CPU的原因
GPU Architecture
- 图形处理集群(Graphics Processing Cluster),用于计算、光栅化、着色、纹理处理的专用硬件块
- 流式多核处理器(Streaming Multiprocessor),作为GPU的一个组成部分,用于运行CUDA
- 纹理单元(Texture Units)用于采样和过滤纹理的纹理处理单元
- CUDA核心 ,允许不同处理器同时处理数据的并行处理器
![](https://i-blog.csdnimg.cn/blog_migrate/bbcd2e4102d9567b5d7c30a6a55c7952.jpeg)
CPU到GPU的数据流
数据在不同的运算单元之间读取传输是十分消耗资源的,所以一般只让数据由CPU单向流动到GPU。
![](https://i-blog.csdnimg.cn/blog_migrate/fd53aed1a117e426f3f59321fc89baf4.jpeg)
缓存(Cache)
我们在存放数据时一般集中存放,就是为了便于缓存的读取,即缓存命中数据(Cache hit);若缓存不断的无法读取数据(Cache miss),不断的重新读取,将会大大降低处理的效率。
![](https://i-blog.csdnimg.cn/blog_migrate/16b64fe7bf8237563e8dbad88216a05c.jpeg)
现代计算机的结构就是一条流水线,每一个环节的效率低下都可能限制整体的表现。
一个应用的表现就受限于:
- 内存
- 算术逻辑单元
- 纹理贴图
- 带宽
![](https://i-blog.csdnimg.cn/blog_migrate/1671df16914fc84d5fefe8c916a1def7.jpeg)
Renderable可渲染对象
Mesh
起初的网格体数据储存方式并不高效,它储存每个点的位置,法线朝向等属性,进而储存每三个点组成的三角形的数据,而这一个个三角形的数据便构成了这个网格体的数据。
![](https://i-blog.csdnimg.cn/blog_migrate/cf5680ab05520d030abf4176dcebb8c6.jpeg)
因为每个顶点是由多个三角形公用的,所以我们可以通过只储存每个顶点的数据和对应的索引值,绘制三角形时根据索引值顺序绘制来提高效率。
![](https://i-blog.csdnimg.cn/blog_migrate/82c41905649bdef8e0355433672219e3.jpeg)
为什么每个顶点都需要定义法线方向?
当绘制表面有折线时,可能会出现顶点位置一样,但法线方向完全不同的情况,所以每个顶点都需要定义法线方向。
![](https://i-blog.csdnimg.cn/blog_migrate/c69e9a20ff61c6b32b99d99150aa59cf.jpeg)
Materials
材质决定了物体的外观和被光线照射时的表现
![](https://i-blog.csdnimg.cn/blog_migrate/01423c36b9276f2592bd5255e7d60f7a.jpeg)
比较著名的材质模型有:Phong Model、PBR Model等等
![](https://i-blog.csdnimg.cn/blog_migrate/3e5242df77beb68246800b848dac3f17.jpeg)
纹理(Texture)是材质的一种非常重要的表达方式
![](https://i-blog.csdnimg.cn/blog_migrate/161489161beaa0363648eb5806736ce2.jpeg)
着色器(Shaders)也是Renderable对象的一个重要组成部分
![](https://i-blog.csdnimg.cn/blog_migrate/01e66e95d815fefec60b1b3689baaa30.jpeg)
坐标系与变换(Coordinate System and Transformation)
我们可以通过不同的投影变换将物体投影到不同的坐标系中,具体原理参考GAMES101课程
![](https://i-blog.csdnimg.cn/blog_migrate/16cea592e595c68af6e4e5fd8b7ec993.jpeg)
SubMesh
我们根据Mesh的材质不同将其分为许多子网格(SubMesh),每个子网格存储一个Offset值,在计算时只需要通过对应的Offset值便可知道该部分三角形使用的材质
![](https://i-blog.csdnimg.cn/blog_migrate/2a2fb69cfc0c5830bce157edc36a5bd8.jpeg)
资源池(Resource Pool)
在储存时,为了节省资源以及方便相同资源的复用,我们会将每个游戏对象切分为Mesh、Material、Shader等,并将相同类型的资源储存到一个统一的资源池中,比如Material类型的资源统一储存在Material类型对应的资源池中
![](https://i-blog.csdnimg.cn/blog_migrate/82e210565d2601c98724652911c63032.jpeg)
相应的,每一个游戏对象也就是这些资源的实例化组合
![](https://i-blog.csdnimg.cn/blog_migrate/de43f89eb06c8f7398bb4dad2912203b.jpeg)
为了提高速度,我们可以将资源池中可复用的资源按照材质分类后再传入GPU中
同时,我们注意到游戏中许多子物体也是相同的,我们也可以利用上面的策略,在一次绘制指令中,创建许多对象,但只传入一次Vertex Buffer和Index Buffer,通过避免重复传入来提高速度
Visibility Culling (可见性裁剪)
游戏世界中一般只绘制视锥中的物体
![](https://i-blog.csdnimg.cn/blog_migrate/cb13fff20e6518078b958a99aff5b72b.png)
不同的包围盒模型:
![](https://i-blog.csdnimg.cn/blog_migrate/3cddea4460fee8f286d3641779546335.jpeg)
Bounding Volume Hierarchy Culling
从最大的包围盒开始依次向下级包围盒做裁剪剔除
![](https://i-blog.csdnimg.cn/blog_migrate/edc14eccddb9407b6cf51c9fa7376fb5.jpeg)
Potential Visibility Set
当玩家每经过一个Portal时,就只绘制当前所在的Zone内可以看见的其他Zone,这一思想可以用于动态载入场景
![](https://i-blog.csdnimg.cn/blog_migrate/23b5e5a5c5de0f53627d9c6e7d680b2b.jpeg)
GPU Culling
通过GPU对不同面之间的交集的快速计算,以此来裁剪剔除无需渲染的面
![](https://i-blog.csdnimg.cn/blog_migrate/e2c727540ad427915c294c8254a2b833.jpeg)
纹理压缩(Texture Compression)
对传统的图片压缩格式(如JPG、PNG)采样需要全部解压,无法实现随机访问其中的一个点,并且采样的计算十分复杂
因此游戏引擎中一般采用块压缩(Block Compression),这种压缩使得我们只需要知道图片中像素的极大值和极小值以及其他像素相对两者的插值的坐标,便可以得到原先的图片
![](https://i-blog.csdnimg.cn/blog_migrate/ada412dd69c5e6f600b7a8e97737a32b.jpeg)
Authoring Tools of Modeling
- 建模(Polymodeling)
- 雕刻(Sculpting)
- 三维扫描重建(Scanning)
- 程序生成(Procedural modeling)
![](https://i-blog.csdnimg.cn/blog_migrate/d3a67d151bc14267bdfd9585df1b95a2.png)
Cluster-Based Mesh Pipeline
随着开放世界、3A大作的流行,模型的细节、精度也越来越高,也就需要新的模型管线Cluster-Based Mesh Pipeline。它将一个高精度模型按规律分为许多簇(Cluster),一簇可以是64个面片,这种细分使得我们可以对随机的簇进行绘制指令,并根据深度进行排序
![](https://i-blog.csdnimg.cn/blog_migrate/782b0973ef71fb52e8be62f9a3015263.jpeg)
Unreal的Nanite就是上述思想细分到像素级别的体现,也是上述思想的工业化体现
Take Away
- 游戏引擎的设计与硬件架构的设计紧密关联
- 游戏引擎的一个核心问题是Mesh、Materials等数据之间的关系
- 为了优化性能,要设计Culling算法使得尽可能少的东西需要绘制
- 随着GPU不断的发展强大,可以将任务更多的交由GPU处理