【GAMES-104现代游戏引擎】4、引擎渲染基础(渲染基础数据、全局光照、PBR、阴影)


游戏渲染的挑战

  • 一个场景包含成千上万的GO需要的材质、shader、效果都不尽相同,因此 复杂度极高
  • 当代各种硬件的适配难度高,硬件架构一直在变化
  • 高帧率、高分辨率的要求下,使得绘制算法绘制一帧的时间越来越短,算法效率要求高
  • 绘制系统可以100%的使用显卡,但CPU只能使用一小部分,因为CPU还要处理游戏逻辑、网络、动画、物理、AI等计算

1、光栅化流程

光栅化主要流程

  • 顶点属性输入(位置、法线、纹理坐标等)
  • MVPV变换、裁剪、透视除法后得到每个顶点在屏幕空间的坐标(范围 ( 0 , 0 ) → ( w i d t h , h e i g h t ) (0,0)\to(width,height) (0,0)(width,height)),主要顶点着色器完成
  • 光栅化:根据顶点位置采样出三角形所覆盖的像素,交给像素着色器处理
  • 像素着色器中对每个像素进行着色计算(纹理映射光照计算后处理等)。
  • 输出像素着色器的计算结果
    在这里插入图片描述

2、一丢丢显卡知识

在这里插入图片描述

SIMD:单指令多数据的数学运算,渲染中有大量的向量、矩阵运算,因此SIMD是非常重要的(CPU GPU都可)
SIMT:单指令多线程,一条指令可以在多个核上做同样的运算
SIMD+SIMT可以让计算速度比单指令单数据快很多。如:一个加法指令c = a + b,在100个核心上同时进行,每个核心又是4个分量同时计算,则速度快400倍

CPU与GPU的数据交换非常的慢,因此衍生出几个原则

  • 尽可能单向、批量从CPU向GPU传输数据
  • 尽可能不要从GPU中读取数据

Cache的重要性

  • 越大的缓存越能减少Cache Miss
  • 如果出现Cache Miss,再去内存中取该数据的代价是100多个时钟周期

3、网格绘制组件(Mesh Render Component)

逻辑上的GO是由多个不同的组件组合起来的,其中一个让这个GO变得可见的组件叫 网格绘制组件

Mesh包含哪些东西?

为什么每个顶点都要定义法线?

  • 首先如果不逐顶点定义法线,那么在后面的计算中,需要用到法线时,应该根据该顶点周围的三角面的法线求平均得到,而三角面的法线是通过两个边叉乘得出,这样会产生一个问题如下左图所示。面的交接线处的顶点法线是斜着的,这样计算着色就会出问题,但看cube的任何一个表面,表面周围的法线有了梯度,根据这样插值出来的法线逐像素着色计算完成后,这个边就不硬!尽管我们的模型是方方正正非常硬的,但他着色后就看起来不硬
  • 因此每个顶点定义法线就很重要,右图所示交界处顶点有2、3个法线的是同一个空间位置定义多个顶点的结果。这样有极大的灵活性,想硬就硬,想软也能软,改变顶点的法线即可
    在这里插入图片描述

4、材质

  • Phong Model:Color = Ambient + Diffuse + Specular
  • PBR Model:Physically Based Rendering,基于物理的渲染模型
  • Subsurface Material:微表面模型
    在这里插入图片描述

现代的材质模型中,纹理(Texture)起着非常重要的作用,可以说是决定性作用

比如下面这个生锈的球是怎么表现出来的?

  • 高光贴图:生锈部分没有高光,未生锈部分有高光
  • 法线贴图:表现物体表面的细节
  • 金属度贴图、粗糙度贴图、AO(环境光遮蔽贴图)

纹理/贴图:定义球面上每个点的属性
在这里插入图片描述

着色器(Shader)

  • 首先 shader是一串代码,但是 在游戏引擎中,shader被当做跟纹理、模型一样的 数据 来使用
  • 怎么理解?一个球模型、一堆贴图,再用一段shader,就能形成一个生锈铁球、毛线球、玻璃球等等不一样的球。

如何让一个对象的不同部位表现出不同的材质呢?

  • 把模型不同部分应用不同的shader和纹理。一个物体还是对应一个顶点数组,但是我们可以定义不同的偏移量offset,将其分成不同的子网格subMesh,对每个submesh应用不同的shader和texture即可
  • 总之Mesh要根据材质的不同进行切分,切分成一个个submesh,submesh与材质是一一对应的
    在这里插入图片描述

课上讲的是 Mesh对应一个大的模型,sub mesh 对应这个模型的不同部位。现代引擎都是这个逻辑但是命名规则可能不同。有些是一整个模型叫Model,而一个Model由不同的Mesh组成。

5、资源池(Resource Pool)

如果游戏中有100个小兵GO,我们难道要为每个小兵都存储一套Mesh(几何模型)Material(纹理、shader)?这样明显太浪费内存,因为所有的小兵Mesh、纹理、shader都是一样共用的,因此提出了 资源池 的概念。即同一个GO的Mesh、shader、Texture都分别用一个Resource Pool来管理,不同的实例(instance)只需要用指针去引用这些资源即可
在这里插入图片描述

根据材质来分类Submesh ,在绘制的时候,材质相同的submesh一起绘制,这种方法在工作量上并没有减少,但是速度会更快。因为不用频繁的更改GPU的状态,比如绘制一个小兵就要切换比如5次shader、绑定5次纹理、切换5次submesh几何数据。绘制下一个小兵又要重复这个过程,这样会非常慢。
在这里插入图片描述

GPU Batch Rendering

  • 一个Draw Call 绘制一大批相同的submesh
  • 就是通过将一些渲染状态一致的GO数据,一次提交给gpu进行绘制,这可以显著的节省drawcall,实际上这主要节省了cpu的时间,cpu从提交多次到提交一次,对gpu来说也不用多次切换渲染状态

6、Cluster-Based Mesh Pipeline

一个新的表达模型的管线,主要思想是:将高精度模型分成多个多个mesh块进行渲染。以前只能对单个物体进行可见性裁剪,现在能够对物体的mesh块进行裁剪。
在这里插入图片描述

UE5-Nanite系统

  • 在此基础上更往前走一步,走向商业化应用
    在这里插入图片描述

7、渲染

重复的知识就不写了…很多渲染基础知识可以看GAMES101的课程学习,也可以看笔记,甚至可以不用学


猜你喜欢

转载自blog.csdn.net/Motarookie/article/details/127008873