图形学原理与U3D渲染管线


前言
今天要分享的主题是图形学原理与U3D渲染管线,本文除了讲解传统的图形学原理以外,还会讲到U3D最新的可编程渲染管线
版权声明
本文为“优梦创客”原创文章,您可以自由转载,但必须加入完整的版权声明
更多学习资源请加QQ:1517069595或WX:alice17173获取(企业级性能优化/热更新/Shader特效/服务器/商业项目实战/每周直播/一对一指导)
点赞、关注、分享可免费获得配套学习资源
3D图形渲染流水线

图形学解决了什么问题?
图形学解决的问题就是使用程序控制显卡将场景中的游戏模型全部渲染出来
其中还涉及了几个方面的知识
游戏模型
写程序控制物体渲染,发送数据到图形渲染管线里
理解图形渲染管线
下图是3D图形渲染流水线的流程图,这张图将整个渲染流水线分成了11个步骤

这11个步骤又可以划分为3块
第一块是游戏的数据,这些数据会被送到显卡的渲染流水线里面
第二块内容是一些顶点处理,因为美工做好的模型文件中存储的就是模型的每一个顶点的各种信息,比如位置信息、方向信息、纹理坐标等等,这些信息送到显卡的渲染流水线里面经过2、3、4、5、6、7这六个步骤处理后就变成了一个个像素点
这些像素点在处理时要经过8、9、10这3个像素阶段,也就是上图中的第三块内容,经过这些像素阶段处理后输出的就是屏幕上最终显示的3D画面
渲染步骤下面的图介绍了模型在经过一系列渲染时发生的变化

图中的第一个小房子是美工制作的模型,这个模型在顶点处理阶段会进行顶点位置变换和顶点光照计算,现在的光照计算一般都是放在像素管线里进行的,因为像素管线渲染出的效果比较精细
上面第二张带有太阳的图就是灯光计算环节,可以看到图中的一盏灯光对游戏场景进行照射,其实在这张图还有一项处理,就是模型的位置变换,将这些三维空间中的这些房子模型放置在游戏世界的某一角落里,经过位置变换后,模型被摄像机照射时就会被染出来了
顶点处理阶段到像素处理阶段中有一个重要的步骤叫做光栅化,光栅化的算法比较复杂,它内部需要经过一些扫描线格处理
光栅化会对物体的表面进行填充,上图最后的小房子上有一个个点状的,像像素点一样的花纹,这就是光栅化步骤的算法要实现的功能
变成像素后会进入到像素处理阶段,像素处理阶段需要进行基于像素的光照运算和基于像素的贴图运算
这些步骤都走完以后,还有一些比较细节的步骤,比如渲染的背面裁剪、阿尔法测试、模板测试、一些误效处理、阿尔法混合等等,经过这些处理以后就能看到屏幕上面显示的一个又一个三角形了
其实3D流水线和工厂造车的概念是非常类似的,下面就带大家看看流水线里的每一个车间是干什么事的,但因为篇幅关系,没有办法把每一个车间都看一遍,就重点看一下最基本的和最重要的两个环节:顶点着色器和像素着色器
世界变换

顶点着色器所处理的三维空间变换可以划分为四个空间三个阶段
每一个物体都有自己的坐标空间,这个坐标空间可以叫做模型空间,假设将自己看成是游戏中的一个角色,那么以自己的坐标位置为中心点来观察世界,这时所处的空间就叫做模型空间,模型空间是物体自身的坐标空间
上图中最上方画了3个茶壶,它们都有自身的坐标空间,但如果把这三个茶壶放在同一个游戏世界里,那么这些茶壶在游戏世界当中不可能每一个都有坐标空间,它们必须处于同一个坐标空间中,这个坐标空间就是世界坐标空间
也就是说这3个茶壶从自己的视角来看都是世界的中心,但如果站在游戏世界的角度来看,每一个物体都不是世界的中心,世界的中心只有一个,就是世界空间的原点,这时再把茶壶放在游戏世界的各个角落(如上图最下方的图片)里,那么它们的方向、位置都不一样
图形学要解决的第一个问题就是怎样把这些茶壶放到游戏世界的某一个角落上去,这需要经过一系列的图形学计算,这样的计算可以叫做矩阵变换
经过矩阵变换后,物体就能够被显卡渲染在游戏世界的某一角落,程序员只需要告诉显卡游戏模型在游戏世界里的位置(Position)和模型是否进行旋转(Rotation)以及要不要进行缩放(Scale),将这3个信息告诉显卡,显卡就会生成一个4行4列的世界空间矩阵
显卡是不能识别游戏模型的,它看不出来它所渲染的是茶壶,还是人物角色,显卡只知道你输入了一批三角形,因为每一个模型都是由三角形面片构成的,只要将模型所有的三角形面片输入到显卡中,显卡再经过矩阵变换就能把三角形面片的每一个顶点渲染在程序员设置的位置上
视图变换

在游戏世界里从某一个视角去观察物体时就发生了第二个坐标变换,物体所在的空间由世界空间变换到了视图空间,在一些术语里被翻译成摄像机空间
将世界空间里的物体转换到视图空间里去的变换过程叫做视图变换,有的术语叫做摄像机变换,这个步骤需要做各种各样的矩阵变换,如果不用矩阵表示就必须向显卡输入一些信息,这些信息包括:
1,摄像机所处位置
2,摄像机的方向
3,摄像机的视角是广角摄像机还是普通角度摄像机,它的视角有多大?
4,摄像机横重比是多少?
其实上面这些信息在Unity中都能找到对应的摄像机参数,所以在学习Unity时不能浮于表面,只是知道Unity需要提供4个参数,却不知道这四个参数背后所对应的图形学原理
投影变换

上个世纪80年代的老式照相机的原理与图形学里的投影变换非常相似,老式照相机在拍照片时会把景象全部生成到底片上去,其实这也是投影变换要做的事
摄像机的投影方式有两种
1,平行投影
平行投影就是物体本身是多大最终显示出的画面就有多大(如上面PPT中的平行投影图),此投影方式显示出的画面不会因为物体远近而变化
2,透视投影
透视投影是符合人眼的视觉的,它显示出的画面会因为物体远近而变化,遵循近大远小(如上面PPT中的透视投影图)
平行投影常常用在2D游戏里面,因为2D游戏的摄像机都是平行投影的,还有一种情况就是一些3D斜45度视角的游戏,为了模拟那种2D斜视角风格使用平行投影
透视投影常用于3D游戏,如果想做一个写实的3D游戏就肯定要用到透视投影

上图也是投影变换的概念图,只是更具体一点,是从一些数学计算的角度来看的,在Unity里也有这些选项,比如设置摄像机的近裁剪平面、远裁剪平面,设置摄像机视口的宽度和横重比
设置完这些东西以后投影变换就能正常工作了,使物体能够进行近大远小的透视投影
屏幕变换

使用拍立得拍的照片会拍到照片纸上,如果想要将照片放大就需要送去冲印,同样的,在三维世界里拍到的游戏世界场景实际上也是拍在一个X坐标介于-1到1之间、Y坐标介于-1到1之间、Z坐标介于-1到1之间(如果使用的是OpenGL是-1到1,如果是DirectX3D则是0到1之间)的投影空间中
这个投影空间的坐标范围很小,横向、纵向都是两个单位,而正常情况下的游戏至少也是800乘600的分辨率,所以需要将这一块非常小的投影空间经过图形学放大,放大到游戏所需的屏幕分辨率
总结:顶点变换流程

每一个物体都有自己的坐标空间,叫做模型空间,有的术语翻译为对象空间,模型空间经过世界空间变换以后就变换到世界空间了,也就是放在游戏世界的某一个角落
在场景里架设一台摄像机,由摄像机去看游戏场景,这时就要把整个游戏世界切换到摄像机空间,进入摄像机空间里的物体会有一些透视效果,需要经过透视变换
因为投影空间的范围比较小,所以要将图像显示在屏幕上的时候就需要对它进行放大,就像冲印底片一样,之后就可以得到在屏幕上所能看到的图像了
像素阶段
纹理贴图

像素着色的大致流程
要将纹理贴图贴到游戏模型上必须确定每一个物体的顶点与像素图位置的对应关系
上图模型的(x0,y0,z0)、(x1,y1,z1)、(x2,y2,z2)是物体的顶点坐标,它们对应了上图右边纹理图的UV坐标

确定了物体的顶点坐标点和贴图的坐标点后,就可以明确的把纹理贴图的左上角(由(u0~2,v0~2)构成的三角形)贴在模型盒子左上角的三角形上(由(x0~2,y0~2,z0~2)构成的三角形),这就是显卡贴图的过程
在这个过程中程序员需要提供每一个顶点的UV坐标,有了这些信息以后,显卡就能确定顶点和它所对应的图片位置关系
像素阶段

如果不进行贴图,只进行光照运算和光栅化,最终得到的图像就是上图中的白色飞龙图片,这个飞龙没有任何细节表现,看上去就像是塑料,为了表现模型的细节,就需要为模型贴上贴图,贴上贴图以后的飞龙模型就是上图中带有颜色花纹的图像
但这样的图像看上去还是有点假,因为从视觉角度来看,这个模型并没有光照明暗信息,这就需要用到一种次世代技术,叫做逐像素光照
逐像素光照是基于每一个像素点计算每个像素点的光照反射、折射、灯光的遮蔽、光照的方向等等信息,使用逐像素光照,再加上凹凸贴图、遮挡贴图、金属贴图、反射贴图等等一堆贴图就能实现基于PBR的渲染
通过自定义渲染管线提升渲染性能

刚才讲的显卡渲染流水线是比较低级的流水线,只能识别并针对三角形进行渲染,如果要进行性能优化也只能针对这些三角形的缓冲来进行优化,没有办法进一步提升性能
其实Unity游戏引擎提供了一个更高级别的渲染流水线来让程序员对渲染过程进行优化,这就是下面要讲的主题:通过自定义的渲染管线来提升渲染性能
它是一个新技术,叫做SRP(可编程渲染管线技术),它不是比较底层的Shader可编程,而是Unity引擎层面的可编程

渲染管线级别中最低级的是GPU,GPU无法识别物体,只是基于三角形构成的三角形缓冲区来进行渲染
引擎级别的渲染管线就是Unity,Unity能识别游戏中的每一个物件,然后针对这些物件做各种各样的处理,比如遮挡剔除、LOD优化等等
Unity渲染管线的种类

Unity的渲染管线种类有三种,在Unity5.x阶段使用的是Built-in,Unity2018之后增加了SRP渲染管线
Built-in渲染管线是不能做过多的控制的,只能做一些简单的控制,它也叫内置渲染管线
Unity2018之后增加的SRP可编程渲染管线能控制的方面就比较多,但是传统项目是不能使用SRP的,而SRP又是性能优化的一个关键点,所以就必须把项目升级到使用LWRP(URP)或者HDRP这两种渲染管线之一
IWRP在平时开发中可能会用的多一点,因为除非你的硬件性能很好,否则一般都会用LWRP。LWRP翻译成中文叫做轻量级渲染管线,从功能的角度上来说,LWRP适用于移动平台和VR平台,因为VR的渲染负担比较大,再简单的画面都需要渲染两次
HDRP适用于主机平台,比如PC、游戏主机都可以使用HDRP
自定义渲染管线优化效果

上图场景里有N多个游戏角色,将这些角色全部同屏渲染出来的开销是很大的,要进行优化就需要用到GPUInstance(GPU实例化)技术,GPUInstance的原理就是针对相同模型、相同材质的角色进行批处理优化
在这个场景中直接使用GPUInstance进行优化是无效的,因为GPUInstance的优化原理是进行同材质的角色合批,而场景中的角色和阴影的渲染是交错进行的,从而无法合批
优化方法

优化方法
1,通过轻量级渲染管线对渲染进行重新排序,从而实现优化
2,尽量保证合批
上图显示的场景是通过自定义渲染管线SRP进行合批后的效果,一共只有20个DrawCall
SRP还能做什么?

SRP可以用来做半透明处理优化,在笔试面试时经常会问到的问题就是半透明的渲染问题,因为半透明物体在渲染时的性能很差,半透明物体渲染时必须要关闭深度写入,深度写入关掉后在渲染时就必须把所有的物体从后到前全部渲染一遍
要解决这个问题可以先开启深度写入渲染所有不透明物体,渲染完以后再关闭深度写入将半透明物体按照距离摄像机远近排序,从后到前渲染
写在最后
更多学习资源请加QQ:1517069595或WX:alice17173获取(企业级性能优化/热更新/Shader特效/服务器/商业项目实战/每周直播/一对一指导)
点赞、关注、分享可免费获得配套学习资源
到顶部