# 虚幻4渲染编程(重写渲染管线篇)【第一卷:从零开始推导PBR渲染模型---上】 章节概述: 作为一个美术,一般遇到渲染管线上的问题的时候往往会束手无策,因为整个c++层到shader层这么大一块的系统都是由图形程序大佬一手搭建起来的。这就会导致平凡地需要去打扰别人。为了加快工作效率,我觉得美术有必要能自己完成整套渲染管线的搭建,优化和游戏跨平台发布。 这章将会从零开始,在虚幻4中搭建一个forward PBR渲染管线。内容大概会分为:理论推导,c++引擎底层渲染器搭建,shader层管线搭建和如何根据我们自己搭建的管线来定制美术资源开发文档及跨平台优化等一整套流程。 本篇章会写得非常通俗易懂,因为我是个美术,所以我觉得我写的东西应该大部分美术也都能看懂。 如有错误还请各路大神斧正,也欢迎大神留言和我一起讨论学习。 【1】数学工具基础 我们的终极目的就是用计算机画一张图出来,但是要如何画呢,计算机可只认识0和1,所以我们只能通过数学来描述。用公式来描述清楚光线是如何传播的,如何和物体作用的。我们需要一些数学工具来帮助我们度量光和物体表面的作用。 (1)圆心角 圆心角是弧度微分和半径的比值 ![img](D:/Program Files/Typora) 如果对【0,2π】积分的话,就变成了圆的周长2π。 (2)球面坐标 ![img](D:/Program Files/Typora) 其中r表示向量的长度,θ表示向量和Z轴的夹角,Φ表示向量在x-y平面上的投影和x轴的逆时针夹角。  (3) 立体角 立体角与圆心角类似,立体角ds的含义就是球面上的面积微分和半径平方的比值 ![img](D:/Program Files/Typora) 1单位球面度即1dA的球面度对应的球面面基为r的平方。 因为球体表面积等于4πr^2 ,所以上面的式子积分到整个球体的话,立体角等于4π。所以对立体角进行半球积分可以得到为立体角的一半为2π(单位球) 由前面的球面坐标即可得到立体角的微分式为 (4)投影面积 ![img](UnrealCustomPipeLine_03.assets/Thu, 08 Aug 2019 133106.jpeg) 【2】辐射度量工具 有了上面的数学工具,下面我们就可以开始想办法度量物体表面的受光了。 下面是我从wiki上找到的一个表 ![img](UnrealCustomPipeLine_03.assets/Thu, 08 Aug 2019 133115.jpeg) (1)辐射通量/光通量---用符号   表示 单位时间内(一帧)通过某一面积的所有电磁辐射(我们这里可以认为是光)总功率的度量。单位是瓦特 Q代表辐射能单位是焦耳 (2)辐射度---用符号   表示 单位表面出射及反射的辐射通量。对一个点(比如说点光源)来说,辐射强度表示每单位立体角的辐射通量。 (3)辐射率---用符号   表示 每单位立体角每单位投射表面的辐射通量。 表示物体表面沿某一方向的明亮程度,它等于每单位投影面积和单位立体角上的辐射通量,单位是W·sr−1·m−2,瓦特每球面度每平方米。在光学中,光源的辐射率,是描述非点光源时光源单位面积强度的物理量,定义为在指定方向上的单位立体角和垂直此方向的单位面积上的辐射通量。辐射率   也可以理解为辐射度   在表面dA上的积分。 (4)辐照度---用符号   表示 单位时间内入射表面的辐射通量。在游戏里的单位时间可认为是一帧。单位是   ,瓦特每平方米。辐照度还可以写成辐射率   在入射光形成的半球上的积分。 【3】光和物体表面的作用现象归纳整理分析 现在我们已经有了度量光照到物体表面的方法了,现在终于可以开始研究光和物体的作用了。 我们研究光和物体的作用肯定不能靠自己的想象,一切还是需要先基于现实。 ![img](UnrealCustomPipeLine_03.assets/Thu, 08 Aug 2019 133121.jpeg) 当光从太阳发射出来到达大气层之后,光被大气散射,所以把整个大气都照亮了(体积光,GI)。当太阳光照到山上,一部分光线被反射一部分光线被吸收。反射的这部分光射到水面上,一部分光线反射(高光),一部分吸收,一部分折射。水面反射光的分布是有规律的(菲尼尔因子)。最后这些光线再进入我们的眼睛。 通过对现实世界的分析,我们按照光线的传播路径把它们分一下类:反射光线,折射光线,散射光线,被吸收的光线,透射光线。 真实世界实在太复杂了,各种光线各种传播途径。于是光线追踪横空出世,通过光线的追踪渲染出图片,不过光线追踪计算量太大。于是我们只好对现实世界的光线进行简化,现在我们来把光线一条一条拆解分析。 当我们把光线通过传播路径来分类之后发现,光线数量还是很多,有必要再把它们归类,于是很容易想到,可以按照光照到不同的物质来再对光线进行分类,照到水上的光线,照到泥土上的光线,照到金属上的光线。现在我们有了一个二维的表。 ![img](UnrealCustomPipeLine_03.assets/Thu, 08 Aug 2019 133127.jpeg) 物质类型在游戏里可以表示为 *材质* 这个概念。 用做实验时常用的控制变量法来讨论。 (1)当光路都是反射类型,物质类型不同时 物质如何分类呢,稍微背过元素周期表的都知道可以根据金属性来区分物质类型。于是可以把物体分为金属和非金属。定义:M,金属度 ![img](D:/Program Files/Typora) ![img](D:/Program Files/Typora) ![img](D:/Program Files/Typora) 当光线照到元素周期表靠左的主族元素和副族元素物质的时候(高金属度),由于元素比较活泼,所以光线如果进入物质内的话大部分会被吸收(就不考虑电子跃迁什么的了)。光线照到元素周期表偏右边的主族元素时则相反(低金属度),照进物体的部分光线还是可以被反射回去。 我们再对反射光线进行细分,则可以分为漫反射(上图反射光蓝色部分)和高光(上图反射光橙色部分)。 这时候还有个问题,我们上面两个视图所没有考虑到的,那就是表面十分光滑,然而世界上没有绝对光滑的物体(*三体星人的水滴除外【手动滑稽】*)。 物质的分类里面除了金属度会影响光线的反射外,还有物体表面的粗糙度也会影响,这个因素我们也应该纳入考虑范围。 ![img](D:/Program Files/Typora) 如果物体表面很粗糙,此时反射光线就会被阻挡。 ![img](D:/Program Files/Typora) 这时候可能就会问了,不是有法线么!我用法线贴图描述物体表面坑坑洼洼的信息了呀。但是别忘了,我们现在所处的环境是在计算机里模拟。不可否认法线的确是描述物体表面信息,但是这是建立在法线贴图精度足够高的情况下的。只有法线贴图精度足够高,我们才能用法线来描述物体表面非常细小的起伏。然而我们游戏里不可能给大片大片的物体使用超级高超级高的法线贴图。而且当贴图精度过高时,我们屏幕分辨率也不够用,现在主流的游戏画面也不过4k而已。 所以我们这里描述的物体表面的信息应该再加一个限定,叫“物体微表面信息”。所以定义:光滑度 R 这个概念。同时这也告诉我们,我们一定要注意正确使用贴图,这部分内容会在后面美术资源生产指导规范中详细说明。 微表面模型理论是一种从非光学平面获得表面反射BRDF的理论方法。它假设表面都是由很多的微小平面组成,每个微平面的尺度都很小,眼睛看不到,但远比光波波长要长。每个微平面都可以看成是完美的镜面,可以将入射光线反射到一个单独的出射的方向。  是微表面上的法线分布函数(Normal Distribution Function)NDF, 描述了单位宏表面上微表面法线为 的概率密度,即微表面法向量 与向量 相同的比例,在大多数表面上,微表面的方向不是均匀分布的。 微表面法线接近宏表面法线的频率越高就越光滑。当然也有特例,比如拉丝金属,头发这些的微表面分布均匀,甚至朝向还有一定规律。 (2)当光路是折射类型时,物质类型不同 我们如果能看到什么东西,一定时光线进入了我们的眼睛。所以当我们能看到折射现象的话,光一定时发生折射之后有反射到了我们眼睛里。 ![img](D:/Program Files/Typora) ![img](D:/Program Files/Typora) 可以看到当发生折射的时候,光线会发生偏移。现在我们就可以定义一个概念了,定义:折射强度。当光在物质A里的传播速度比B比值越大时,折射率肯定就越大,一般物质密度越高折射率越大。所以水<玻璃<水晶钻石 (3)当光路是散射类型时,物质类型不同 ![img](D:/Program Files/Typora) 这个现象在游戏里用得最多的就是人的皮肤,蜡烛,冰块,果冻糖果,体积雾之类的效果。虽然这么多效果有固态有气态不管时raymarching也好还是预积分也罢,它们都用到了同一个一个非常重要的属性,那就是厚度,这就是SubstancePainter中为啥要画厚度图的了,因为做散射效果的时候需要用到。 定义:厚度 还有一些特殊的我这里就暂时跳过了,因为上述三种情况已经包括了世界上绝大多数物质和光路了。 现在问题又来了,我们有了数学工具,并且用这个数学工具结合辐射学推导出了度量辐射光线的公式,现在又对自然现象进行了分析归纳。那下一步该干嘛呢?这和我们要用计算机绘制一幅图像好像还差很远。 我们下一步应该数学建模,利用我们现有的公式和算法来对现象进行抽象建模,对光线与表面的交互进行数学描述。 【4】利用上面1~3的数学工具,度量公式和归纳分类来进行光照模型的数学建模 我们有了上面的归纳总结和数学公式,下面就可以开始建立数学模型来描述我们的光线了。 我们用BRDF来表示指定方向的反射光和入射光的比例关系  这便是BRDF的定义 这里顺便强调一下,如果我们模拟一个现象的时候使用了错误的模型,往往会得到错误的效果。我下面先例举几个当今业界公认的数学模型,我们在学习完这些模型之后其实可以自己学着来建立自己的数学模型的(怎么感觉做个游戏跟搞科研一样啊)。 (1)Lambert漫反射模型 大家对这个模型应该十分熟悉了,非常古老的模型。注意它只考虑了反射。 lambert的模型描述了光照射到物体表面时,由于物体表面不平整光线向四面八方反射。它的特点是(1)光照强度与观察角度没有关系 (2)光照强度跟灯光的入射角有关系 这个模型假设环境中有两种光,环境光和方向光。 用数学公式表达BRDF即  kd是物体对光的反射系数(可以认为是粗糙度),Ia是方向光强度,E是辐照度 kd是物体对光的反射系数(可以认为是粗糙度),Ib是环境光强度 最后的结果是两者相加即可。 (2)half-Lambert漫反射模型 这个模型仍然是一个经验模型,是对lambert模型的改进,它主要是对辐照度E的计算方式进行改进,把E的范围变换到了【0,1】。 (3)Phong反射模型 Phong模型增加了光线的类型考虑。它分为了四部分,自发光,高光反射,漫反射,环境光 今天(2018/10/13)还有绝大多数手游(80%)在使用这种光照模型。 ![img](D:/Program Files/Typora) (4)Blinn-Phong反射模型 主要是对Phong模型高光反射部分计算的改进 ![img](D:/Program Files/Typora) 使用H向量来计算高光。 v为视角方向,l为灯光方向。 Ka代表环境光反射系数,ia代表环境光强度,lights代表场景中所有灯光的数量,Kd代表漫反射系数,Ks代表高光反射系数,Eefsiv代表物质的自发光光照度。Ed代表漫反射光照度,Es代表高光光照度,alpha代表*shininess* constant (5)Cook-Torrance BRDF(Cook-Torrance microfacet specular shading model)模型 随着计算机硬件的发展,我们可以实时做更多计算(2018年甚至出现了实时光线追踪)。于是我们可以给我们的光照模型考虑更多的因素。 ![img](D:/Program Files/Typora) 这个模型主要是对反射现象进行数学建模,也就是说它仍然没考虑全,但是相对于以前的经验模型已经又近了一步。对于透射,折射,散射其实是不适用的。 1.加入考虑光是可逆的 2.加入考虑能量守恒,出射光的能量应该小于等于入射光的能量 3.线性特征,最后结果是不同光路的光线性相加的结果 4.微表面理论。上面4个模型虽然都有考虑物体表面的平整程度,但是它们考虑得都比较粗略——越平整反射光就越强,越集中,越粗糙的表面反射就越弱越分散。 ![img](D:/Program Files/Typora) 其实还可以考虑得更细一些。而且它们还没考虑粗糙的表面的法线是非常不平整的,这里又有人有疑问了,不是有法线映射么!下面我将给一张图分别来看几个法线所表示的级别。顶点法线,法线贴图映射的表面法线,微表面理论的微表面的法线。 ![img](D:/Program Files/Typora) Vn(蓝色)代表顶点法线,Tn(紫色)代表法线贴图映射的法线,Mn(绿色)代表微表面理论中讨论的法线,可以看到法线贴图的法线精度太低,是个宏观的平均。理解这个层级关系非常重要,理解之后就不会纠结什么细节应该画在什么贴图上了。那些把非常细小的划痕做在法线贴图上的美术就是个典型的反例,还有把模型的切角做在法线贴图上的模型师也同样是个典型的反例。 总地来说,因为微表面的考虑,我们的反射光线会出现两个现象,第一个是反射光线不一定全部会反射到摄像机里,因为微表面的法线分布把反射光打散了(Normal Distribution Function即NDF)。第二个是微表面自己有相互遮挡,可能光线还没完全离开表面就被自身其它结构遮挡了(几何衰减因子)。 关于第二个现象有人又要说了,自身遮挡不是有AO么。其实AO和法线贴图映射是类似的原理,都是描述的体积更大一级的大结构现象了(暂时可以这么理解),这里描述的是微表面。 5.菲尼尔反射 我们需要对反射光线进一步讨论。之前的那些模型考虑得比较简单,光照到物体就反射了。但真实世界可不是这样。稍微学过物理的都知道反射的同时还有折射。又到了复习高中物理的时候了。翻到课本(第十七章 光的传播) ![img](D:/Program Files/Typora) 反射光线的强度和折射光线的强度会随着角度的变化而变化。 ![img](D:/Program Files/Typora) 而出射光线的方向就是我们摄像机的方向,摄像机接收到的光的强度就是反射光的能量。由前面的能量守恒条件可知,折射光线越强,反射光线就越弱,我们摄像机接受到的光就越弱,图像那点像素的亮度就越低。 ![img](D:/Program Files/Typora) 上面只讨论了一种物质,下面来讨论下多种不同的物质。 ![img](D:/Program Files/Typora) 不同的物质,折射角和入射角的变化对折射光和反射光能量的变化曲线是不一样的。上面是一些物质的变化曲线图。而这些因素应该都需要加入我们的数学模型中。 \---------------------------------------------------------------------------------------------- 终于把前置条件因素考虑了一遍,下面开始数学建模。下面就以解数学题的格式来推导数学模型吧。 解: 由条件3线性特性可得:可以对整个模型进行拆解最后再线性组合。 ![img](D:/Program Files/Typora) 第一部分对漫反射建模: 对漫反射部分进行建模分析,设漫反射光照模型为   ,物体的基础颜色为   ,此处的辐照度为  ![img](D:/Program Files/Typora) 由辐照度和辐射率的转换公式可得  ........................................(1) 因为   的取值范围是【0,   】 故   ...................................(2)  (L0代表反射光线,Li代表入射光线)  .................................................(3) 联立(1)(2)(3)可得      ........................(3-1) 这种方式对diffuse建模非常高效,但是还可以考虑得更复杂一些。迪士尼的漫反射模型还考虑了更多。,理想情况下漫反射部分应与镜面反射相关并考虑表面粗糙度。迪士尼漫射BRDF和Oren-Nayar模型都考虑了粗糙度并在掠射角度下创造了一些后向反射。鉴于我们的限 制,我们认为额外的质量些许提高并不值得所花费的运行时成本。这种复杂的漫反射模型也使得 基于图像和球谐更难以表达和实现。 的迪斯尼漫射BRDF如下:  ....................(3-2) 其中 该公式中使用的粗糙度是感知线性粗糙度 ![img](D:/Program Files/Typora) ![img](D:/Program Files/Typora) 基色重映射: 材质的基色受所述材质的“金属性”的影响。电介质具有消色差镜面反射率,但保留其基色作为漫 反射颜色。另一方面,导体使用其基色作为镜面反射颜色,并且没有漫反射成分。 因此,光照方程必须使用漫反射颜色和f 0 而不是基色。漫反射颜色可以很容易地从基色计算 ![img](D:/Program Files/Typora) 第二部分对高光反射光线建模: 由上面的第四和第五点可知,反射光线受微表面及菲尼尔两个因素影响(F项),微表面又向下细分两个,一个是法线分布(D),一个是阴影遮罩(G)。需要确定这几个因素之间的关系,所以需要对反射光线的各个部分的关系再进行数学建模。 设入射光方向   观察方向   微表面的法线半角向量  则一束光打到微表面的微分通量  .................(1) 微表面的面积积分是  ....................................................................................(2) 由上两式联立可得  ............................................................................(3) 由菲尼尔定理可知,此时光线在微表面交互处会发生菲尼尔现象,所以  .................................................................(4) 所以由(3)(4)两式可得反射辐射率为  ....(5) 由BRDF的定义可得  ..(6) 是入射光线 与朝向为 的微表面法线的夹角 是入射光线 与宏观表面法线的夹角 是反射光线 与宏观表面法线的夹角 由Surface Reflection: Physical and Geometrical Perspectives所给出的推导  ................................................................................(7) 于是将(7)带入(6)可以得到  ......................................................(8) 再考虑到几何遮蔽项,与第(8)联立可得方程  ................................(9) *【注:然而上述只是推导出了一个组合了F项D项G项的模型罢了,还需要把F,D,G全部展开】* F项: 设   ,   表示高光颜色  ................................(10) 这个公式描述了Cook-Torrance镜面BRDF的菲尼尔的近似。 ![img](D:/Program Files/Typora) D项:  ............................................(11) 这个公式是拟合出来的,把这个公式的曲线和真实世界的衰减曲线对比,发现它和真实的曲线很像,所以这个公式就出现啦。 ![img](D:/Program Files/Typora) G项: .................................................................(12) 将微平面高度考虑进来,是的遮蔽和阴影相关联,可以得到更准确的结果。因此定义高度相关的史密斯函数  .................................................................(13)  ..........................................................(14) 用   替换   可得  ..............................................(15) 所以可得到我们最后的可见性函数 ....................................................(16) ![img](D:/Program Files/Typora) 在注意到平方根下的所有项都是平方并且所有项都在 范围内之后,我们可以通过使用近似来 优化此可见性函数:  .......................(17) ![img](D:/Program Files/Typora) 其实还可以近似  ..............................................(18) 故最终的光照模型为  ..............(14) 【3】第三步对环境反射建模 我们可以看到(13)的最终公式中,我们对前两个做了建模,环境反射还没有处理。在blin-phong这些模型中,计算环境光十分粗暴,但是真实的环境中,我们环境光形程十分复杂,太阳光打到物体A上又反射到另一个物体B上,此时物体A相对于物体B相当于是光源。以我们需要渲染的物体为参考物,周围物体反射光线给它,所以周围物体其实相当于是光源。所以IBL(Image Based Lighting)应运而生。 IBL在游戏中有几个问题(1)采样次数太少,只有一次,对比substance的64次简直太少了。其次是重要性采样的匹配。其实就是根据粗糙度的不同对Cube Map进行down sample,但是这个曲线需要匹配。Unreal采用预积分的办法来解决。但是这会增加一张贴图采样的消耗,也可以拿公式自己去拟合曲线。 ![img](D:/Program Files/Typora) ![img](D:/Program Files/Typora) 最后,Cube Map的制作不能随意制作,要基于物理的方式来。这会在后面的美术资源生产规范中详细说明。 IBL分几种类型 (1)远光探针,用于捕捉“无限远”的照明信息,可以忽略视差。远程探针通常包含天空,远距离 景观特征或建筑物等。它们由引擎捕获或从相机获取,为高动态范围图像(HDRI)。 (2)本地光探针,用于从特定的角度捕捉世界的某个区域。捕获根据周围的几何体投影在立方 体或球体上。本地探针比远距离探针更精确,对于向材料添加局部反射特别有用。 (3)平面反射,用于通过渲染平面镜像的场景来捕获反射。该技术仅适用于建筑地板,道路和 水等平面。 (4)屏幕空间反射,用于通过深度缓冲区中的光线行进捕获基于渲染场景(例如,使用前一 帧)的反射。 SSR效果很好但可能非常昂贵。 此外,我们必须区分静态和动态IBL。 例如实现完全动态的日/夜循环需要动态地重新计算远距离 光探测器。 平面和屏幕空间反射本身都是动态的。 (6)各向异性BRDF模型 ![img](D:/Program Files/Typora) 使用各向异性GGX NDF实 现了这一目标: ![img](D:/Program Files/Typora) 这个NDF依赖于两个补充粗糙度项,即 ,沿着切线方向的粗糙度,以及沿着次切线方向的粗糙度 。 Neubelt和Pettineo提出了一种通过使用anisotropy参数从   派生   的方法,该参数描述了材质的两个粗糙度值之间的关系: ![img](D:/Program Files/Typora) 下面是美观的结果,但是计算会相对费一些 ![img](D:/Program Files/Typora) 不过使用另一种可以创建锋利的高光 ![img](D:/Program Files/Typora) ![img](D:/Program Files/Typora) 此外还需要对遮蔽项进行改进 ![img](D:/Program Files/Typora) 其中 ![img](D:/Program Files/Typora) 最后可以得到 ![img](D:/Program Files/Typora) ![img](D:/Program Files/Typora) \------------------------------------------------------------------------------- 于是我们终于完成了光照模型的数学建模。然而还没有完(哭笑)。再现实世界,除了光与物体交互外,还有一种情况就是光没有与物体交互,这将形成阴影。不过不急,我们先把我们上面讲到的知识先敲到我们的渲染器中再研究剩下的影子这些知识。下一节我们将推导各种常用的光照模型和物理光源。 呼!写这么多字手好酸,什么?我美术能力不行?去做个动画短片放松一下。 ![img](D:/Program Files/Typora) Enjoy it ! 参考资料 【1】[SIGGRAPH 2013 Course: Physically Based Shading in Theory and Practice](http://link.zhihu.com/?target=https%3A//blog.selfshadow.com/publications/s2013-shading-course/) 【2】[【《Real-Time Rendering 3rd》 提炼总结】(六) 第七章 · 高级着色:BRDF及相关技术](https://zhuanlan.zhihu.com/p/28059221) 【3】[深入浅出基于物理的渲染一](https://zhuanlan.zhihu.com/p/33630079) 【4】[立体角(Solid Angle)详解](http://link.zhihu.com/?target=https%3A//www.qiujiawei.com/solid-angle/) 【5】[【图片】游戏中基于物理的渲染简简明科普(2):微平面理论【孤岛危机吧】_百度贴吧](http://link.zhihu.com/?target=https%3A//tieba.baidu.com/p/3922948521) 【6】Real-Time Rendering.3rd 【7】[http://jcgt.org/published/0003/02/03/paper.pdf](http://link.zhihu.com/?target=http%3A//jcgt.org/published/0003/02/03/paper.pdf) 【8】[https://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_slides.pdf](http://link.zhihu.com/?target=https%3A//blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_slides.pdf) 【9】[https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf](http://link.zhihu.com/?target=https%3A//blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf) 【10】[基于物理着色:BRDF](https://zhuanlan.zhihu.com/p/21376124) 【11】[http://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf](http://link.zhihu.com/?target=http%3A//www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf)