概览
游戏渲染的四个挑战:
- 需要渲染大量的物体,考虑各种各样的效果
- 要运行在现代的复杂的CPU和GPU架构上,深度适配
- 帧率要无懈可击,永远保持住,即使在各种渲染环境和分辨率下
- CPU的带宽和内存受限,游戏逻辑、网络、动画、物理和AI等更需要内存
这门课主要强调于工程实践,而非理论,总体分四部分:
- 游戏渲染基础
- 特殊渲染
- 材质、着色器和光照
- 管线
渲染系统的对象
渲染管线和数据:
在许多方面计算非常重要:
- 投影和光栅化
- 着色
- 纹理采样
所以GPU非常重要。
GPU
架构
SIMD是指单指令多数据,在一条指令里同时对很多数据进行一样的处理,比如一条指令完成四次加法 SIMT是指把计算内核做的很小数量很多,然后这些核都可以去进行同样的指令操作,从而让同时能进行的计算变多 GPU的具体架构如下(每代GPU不完全一样,但基础原理类似,下图为费米架构): GPU包含许多GPC,每个GPC中有数个SM,每个SM中又有很多CUDA内核。 核心在于各种内核,它们之间不仅并行运算,还可以进行信息交互,共享内存。 随着时代发展,之后又新增了tensor core(AI)、RT core(光追)等。
数据流
数据在CPU和GPU中传输时: CPU和主存: 数据的加载和卸载、数据的准备 GPU to GPU: 高延迟、受限的带宽 GPU和现存: 高性能并行渲染 简单讲就是数据在CPU和GPU之间传输这步骤很拉低速率,所以尽量要减少CPU和GPU之间的数据传输
Cache
要充分利用硬件的并行计算能力,所以要充分利用cache,减少cache miss(做计算的时候数据不在缓存中,还要等待去内存中找)
GPU Bound
木桶效应,各个步骤都要优化好,不然其他再优化好都没用,包含:
- 内存限制
- ALU(算术逻辑单元)限制
- TMU(纹理映射单元)限制
- BW(带宽)限制
渲染
Renderable
可渲染的对象,包含:
- Mesh:顶点、三角形、顶点索引
- Material:外观以及如何与光互动,一般只指外观材质,物理材质单独定义
- Texture:纹理是材质非常重要的表达方式
- Shader:既是资产又是代码
如果一个模型(GO)上有多个材质,那么其结构应该是如下图: 根据材质不同会将mesh切分成很多不同的子mesh(利用offset确定位置),对应不同的材质贴图,但其其他mesh信息比如坐标等是统一处理的
Resource Pool
- 许多GO之间有共用的材质、mesh和网格,因而建立一个资源池,包含这些材质等信息,在设置对象时让它们指向要用的共享的资源就行,这一操作经常用在实例化对象过程中,众多对象的材质信息等是共享的。
- 另外,实操中常用的一个方法是在初始化资源池和加载资源之后,对所有的submesh按材质进行排序,这样在实际工作中发现会让GPU计算更快
- GPU Batch Rendering概念。对同一类submesh和材质进行批处理,比如树、草等。
可见性裁剪
Culling: 确认物体的包围盒是否在视锥内来决定是否剔除。 有各种各样的包围盒,比如球状、AABB、OBB、Vertex Hull等。 另外也有比如八叉树、BVH这样的判断方法来减少计算量。其中BVH在动态物体特别多的场景中会更有优势,因为那种情况下八叉树本身的划分会需要经常变动,影响效率。
PVS(Potential Visibility Set):把场景划分成一个个房间,因为每个房间理论上只能看到其他固定哪些房间,所以在渲染时只需要将这些房间考虑进来就行。这一点在资源加载上也有很大优势。
Early-Z:先进行一次深度测试来确认遮挡关系,从而避免被遮挡像素的渲染。
纹理压缩
传统压缩方案比如jpeg压缩率很高很好,但是不能随机访问,所以没法用在游戏中。游戏中更侧重快解码率和随机访问。 常用的策略是把图片分块压缩(比如4x4),针对每一块,找到其中最亮的和最暗的,并利用其他块之间的关联度来确定每一个像素的情况。 PC中新的方法有BC7,旧的有DXTC Mobile端有ASTC(新)和ETC/PVRTC(旧)
建模工具
常用的有四类:
- MAX、MAYA、Blender等多边形建模工具
- Z-brush等雕塑工具
- 三维扫描
- 通过算法自动生成的建模工具如Houdini
新的渲染管线
游戏引擎的渲染管线是一直在进步的,毕竟软硬件上的需求是在不断发展的。
Cluster-Based Mesh Pipeline
将大物体划分为很多小的mesh,这些mesh之间操作上同质化严重,所以可以一起渲染。 这新的shader的核心作用是可以使用一个算法基于数据凭空生成很多的几何,而且依据其到摄像机的距离选择它的精度。这样对GPU来说要处理的都是大小一致的小块了,十分高效而且潜力无限。比如在culling上的使用,会智能计算是否需要渲染。UE5的Nanite也是这个方向更进一步的成果。
总结
- 游戏引擎设计十分依赖对于硬件架构的理解
- submesh的设计对多材质物体十分关键
- 可以culling算法中尽量减少渲染物体
- 要让尽可能多的工作移到GPU,使得工作变成GPU驱动
|