|
一,Disney原则的PBR
虚幻受SIG 2012《Physically-based shading at Disney》中的启发,将引擎设计为基于物理的工作流,虽然C++写的无比蛋疼,但是Shader里还是有很多值得学习的地方。
1,Disney的原则
- 使用方便、便于理解比物理真实更重要
- 可调参数越少越好
- 参数的值必须在效果可接受范围内归一化到0~1之间
- 参数可以被赋予超过其实际可接受范围(0~1)之外的值
- 所有参数组合的效果都必须是可接受并且稳定的
Disney原则的PBR在UE4中的应用
其中第3,4,5不用多说,针对第一点:
UE4的很多内置ShadingModel并不是完全物理的,一方面没有按照公式或者物理光学效应直接还原计算,而是对性能与画面进行了折中;另一方面也并没有刻意追寻能量守恒,比如Hair。这些着色模型在R&D过程即做到了理论上有理可据,又照顾了画面舒适性。
针对第二点:7个材质领,7种混合模式,13个ShadingModel共享20个pin接口,所有上层的功能实现最终都会转换为这20个Pramaters作为PBR计算的核心数据汇入内建着色器框架。这一点是非常难能可贵的,既要保证丰富的视觉表现需要,又得兼顾引擎自身PBR框架的稳定性,因此哪些参数需要暴露出来都是经过谨慎定夺的,这也是很多引擎无法做到的一点。
内建着色器系统提供了高质量的照明,着色功能;丰富,易用,可扩展的工具生态为内容生产创造了舒适的环境。依据引擎的特点进行开发会非常的安逸,但是如果想要定制一些Render Feature,可能就得系统了解下UE4是如何做PBR的了,而这一成本相对较高,一个小功能可能需要改动很多文件。
因此,本文的核心行文目标就是分析清楚UE4是如何实现物理渲染的。
2,PBR的图形引擎
这绝对是一个老生长谈的问题了,但是这里还是有必要说一下,因为每个人对PBR的理解是不同的,在我工作过程中发现甚至每个人对GI的理解也是不同的,甚至这种不同的认知居然还有那么些道理!
无论是Octance,Renderman,Unreal,Unity还是其他实时引擎或者离线渲染器,你会发现它们做PBR都是在围绕一件事:
渲染方程的方向积分形式
是的,渲染方程!所有的PBR都是在讨论如何高效无偏的求解这个方程,所提出的不同GI模型都是针对上述方程所做的不同数学变种。这个方程描述了这样一个过程:单位立体角的辐照度到达到表面与物料发生一定相互作用然后从单位投影表面发射出一定强度的辐射。
L_i表示入射辐射率,乘上cosθ是因为光线入射时能量贡献只能考虑有效的投影表面,所以有个朗伯余弦定律。因此可以理解为每单位立体角的功率到达投影表面;L_o表示出射辐射率,可以理解为单位投影表面所能发射出的辐射强度;这中间肯定有能量损失,所以出射辐射率与单位投影表面上累加的功率值(辐射照度)的比值就是f_r,是与物料的物理材质属性有关的,今天我们知道这个比值就是BXDF,并且曾经一度引发图形学界的研究热潮,各种模型被提了出来。
研究渲染就是研究怎么求出L_o,如果感觉上面的描述有些绕,可以看下Games101,里面针对各个物理量解释的比较清楚。渲染方程暗含非常多的隐性条件:
- 首先,贡献到投影表面的光线可能来自多个不同指向的立体角(说人话就是有很多束入射光),所以要求L_o肯定要进行积分,积分域呢?这个要看针对的问题,假设我们研究的是表面材料(非介质渲染)那么只针对表面以上的光线进行积分即可,也就是半球积分。这个时候我们用的fr是非常简化的一种模型,叫BRDF。
- 其次,为了求某一点p的L_o,我们得知道射到该点的L_i,而L_i相对与光源又是L_o,那么问题来了,什么是光源?可以是一盏灯,也可以是一盏灯照亮的物体上反弹的二次光线(也就是所谓的环境光,或者间接光),也可以是在N个物体上反弹了N次的光线。所以渲染方程至少暗含了每次作用时的光线积分与N层递归的过程。如果按照最朴素的思路直接上述过程层层求解,那么基于这种思路设计出来的渲染器被成为“分布式光线追踪渲染器”。
- 再者,从上一条描述可以知道,如果我们把光源单独拿出来进行追踪,对所谓的环境光与光源光(直接光)拆开讨论最终再按照贡献加回一起,似乎可以稍微提高些追踪效率。好的,来自光追时代一个重要的思想被传承了下来,光可以被分为直接光与环境光。其实不分也没事,但分开除了效率在还有别的好处,我们后面讨论。
拆开后,似乎光线递归的问题并没有被解决,计算环境光还是要进行积分。。。,怎么办,数学变形。如果我们把渲染方程的隐式积分显性表示出来,针对表面点(单位面积)构建路径,也就是把方向积分变形为面积积分,我们就得到“路径追踪渲染器”使用的形式;如果我们以牺牲全部或者部分实时动态照明为代价对光照进行预计算,写入Lightmap,或者把渲染方程进行拆分变形写入LUT,再或者不存纹理存入球谐系数之类的其他载体中,就得到了用于PRT渲染器的不同数学形式,典型的如SH Lighting,IBL ,Sphere Gaussian之类的,反正不同的求解方案基于不同的渲染方程数学变种。
游戏对实时的要求很高,所以基于PRT思路的方案大行其道,这个时候对光照进行拆分的好处就体现出来了,不同的光线可以采用不同的形式求解,而且可以做到对光照更为细腻的调控。至于GI怎么拆,看渲染引擎用的哪种解决方案,对光照拆分细粒度等,总之最后加回一起能自圆其说就行【可以对比不同引擎自行感受下】。这也就造成了一个问题,我们在用什么引擎做什么项目时,如果要走PBR的路线,最好美术程序TA就什么是GI达成一致认识。。。。
这篇文章主要分析UE4是怎么做PBR的,所以后面也会给出UE4中的GI是什么。
OK,基本到这我们已经把渲染方程所描述的物理现象用自然语言叙述了一遍,但还没有针对BXDF进行细致的展开说明,这也不是这篇文章的重点。但已经可以总结出整个PBR模拟时大体可以分为两个过程:
- 光线是如何传播的:简单举个例子就是不同形状的光源会有不同的光子发射包络以及整体的衰减模式,这个是针对光照传输过程进行的建模,光是有属性的:颜色,方向,强度计量方式,衰减与扩散样式等等,也就是PBL
- 光线入射到物料再出射的过程:这个过程与物料的物理属性直接相关,也就是BXDF的研究,放到渲染里就是研究着色的过程,也就是PBS。
在迪士尼实现”大一统“之前,PBR需要非常专业的知识去驾驭那些数量庞大又晦涩难懂的材料属性来模拟不同照明工况下的反馈,这对艺术家来说简直就是噩梦。直到上面文章初始罗列出的那几条参考出现,方向才变得明朗起来。
二,基于物理的照明
上面介绍的都是理论上的东西,细节可以参考《全局光照技术》与《PBRT》,这两本书从两个维度对PBR进行了很详实的分析。到了工程层面,又是另一个维度的事情,首先需要明确引擎的GI计算方案。
Unreal的GI策略
Epic对待技术算是比较激进的(当然只限于PC端。。。),在本专栏的第一章就专门针对上述各类GI算法在UE4中的工程应用进行了分析。对于PRT来说使用组合方案,SH来计算环境漫射,”分割近似求和“计算IBL作为环境反射,这部分已经在本专栏的第一章第一节进行了详细描述:
对于PRT的GI计算策略,UE4的光照拆分如下:
UE4 PRT策略中的GI组成
因为环境光计算已经在第一章第一节进行了比较详细的分析,因此这里主要补充下UE4的直接照明与第一章节第一节并未详细展开的SkyLight实现方式
1,灯光函数
1.1,Unreal的Studio Lighting
Unreal封装了一套灯光组件来实现直接照明
UE4的灯光函数
提供了四种类型的灯光,如果把SkyLight Component也算进来的话就是5类灯光组件,但是天光比较特殊因此会单独区分开后面介绍。这些灯光组件被赋予了基础属性与高级属性来实现灵活的调教:
UE4的物理灯光组件属性表
首先最简单的光源模型是点光,基础点光的渲染模型是没有体积的,并且只有三个基础属性:亮度,颜色,衰减半径,且依据辐射度量学对照明计量单位的定义,其亮度衰减应随距离平方成反比来设计。可以在这一基础模型之上增加新的属性,使其更物理真实,细腻或者视觉美观。比如可投射静态阴影与动态阴影,对间接光的贡献系数等等。
当点光源具有几何意义上的半径之后,它就变成了面光源,此时光源形状的几何特性对光子发射包络会产生实际影响,因此引擎将把它当作面光处理:
点光半径不为0会变为面光(非SimpleLight)
第二类就是定向光,也就是平行光。游戏中可以作为太阳或者月亮的亮度来源,这也就意味着除了基础的强度,颜色,方向,阴影视锥,间接光贡献系数等它还将会参与大气,云雾的照明,同时它会像整个世界投射阴影,所以被赋予了更多高级属性。另外一点需要注意的是从管线层面讲,定向光是不会参与TBDR与Forward+的光源剔除的(全局效应的光照组件进行光源剔除没什么实际意义!另外矩形光也不会参与光源剔除,因为对性能影响不大,真正参与分割本地灯光列表的条件非常苛刻)
第三类光照函数是SpotLight,它包含内外两个锥体效应器,因此能够通过内圆锥角与外圆锥角来塑造光源形状,并从内半径范围进入外圆锥角范围时开始衰减。
第四类光照函数,矩形光,也是最为复杂的一套光源。它复杂性来源于面积与形状,而渲染方程告诉我们物体表面是进行球面采样的,这导致了针对矩形光源的高光与漫射计算会非常复杂,同时也意味着区域光有自己单独的渲染方程数学形式。1989年Daniel采用形状因子的方法来解决无屏蔽的面光漫射,但是高光部分的解决方案工程界一直Trick了几十年,直到2016年的SIGGRAPH上来自Unity,Ubisoft,RAD的代表共同给出了一种叫做线性变换余弦(LTC)的思路,能够科学,高效,低偏差的解决面光问题。
LTC的理论基础来源于“线性变换球面分布”【Linearly Transformed Sphere Distributions,即LTSDs】, 它其实是数学领域的“好望角”,即对于一种球面分布总能找到一个线性矩阵将其变换为另外一种球面分布。BRDF当入射角与粗糙度固定时就变成了单一状态下的球面分布,因此如果能找到一种可解析的球面分布,就能用梯度下降或者其他办法拟合出适用于两者的变换矩阵,这样只要在预计算阶段将逆矩阵写入LUT,实时运行时就能通过采样与可解析的分布计算替换原有的渲染方程。
关于LTC是怎样实现这一过程的可以参考:
UE4同样采用了LTC的思路来支持矩形光照明,对应的核心文件是:
- LTC.h
- RectLight.ush
- RectLightIntegrate,ush
其中LTC.h里就是拟合出的变换矩阵,RectLight.ush里定义了矩形光纹理采样与多边形变换,至于RectLightIntegrate.ush则负责处理矩形光衰减,蒙特卡洛,以及针对ShadingModels.ush中封装的EvaluateBxDF完成各类ShadingModel对矩形光的支持。与定向光下的ShadingModel一致,物理的矩形光下直接照明也被拆分为了Diffuse + Specular + Transmission三项。
1.2,IES照明
显然,封装灯光函数主要有2个方面的劣势:
- 很难覆盖各个形状的光源
- 数学模型都是在针对物理模型的抽象与简化
因此,引擎提供了一些常见的灯光类型,又搭配了一套IES照明策略来弥补算法上的不足。IES文件其实就是一条曲线记录了灯光强度的变化以便实现更真实的照明效果。如考虑灯具表面反光的影响,灯泡形状以及光穿过灯泡玻璃罩产生的透镜效应,具有复杂几何外形的灯罩折射与聚光效应等。是点光,聚光,矩形光都可用的,但用在SpotLight上时受据光源弧度角的影响,部分IES数据会被原本效果替代。
IES照明
另外就是Stationary与Moveable下效果是比较好的,在Static模式下因为文件数据精度的缘故并不如烘焙质量。
2,SkyLight的实现分析
对于SkyLight Component,这是UE4独有的。也因其高质量的照明效果广受称赞,但其实其本质还是IBL + 天光球谐,并没有什么神秘地方也不应为此就为UE4蒙上多NB的面纱。。。与普通光照探针(反射球那些)唯一不同的是这个组件可以将遥远天穹处的环境反射到采集点。
Skylight
它同样支持三种模式。Moveable模式一旦开启PC卡成狗,我们来看下代码为什么
既然是灯光组件,那就可以在Engine模块下找到,文件为SkyLightComponent.cpp,在这里面可以找到SkyCapturesToUpdate与SkyCapturesToUpdateBlendDestinations前者负责更新,后者针对多个SkyLight之间的混合。USkyLightComponent::UpdateSkyCaptureContents给出了具体的更新逻辑,找到这个成员函数的定义:
先看单个SkyLight的更新,是通过调用UpdateSkyCaptureContentsArray实现的,继续追踪
核心函数是Scene类的一个成员函数UpdateSkyCaptureContents,实现在Render模块下的ReflectionEnviromentCapture.cpp中
这个文件里实现了反射捕获的主要功能,生成光照数据并传给Shader,主要包括
- ClearScratchCubemaps:清空cubemap每一层Level的每一个面
- CaptureSceneIntoScratchCubemap:分6个面拍摄场景,填充Cubemap的Mip[0]
- ReadbackRadianceMap:读取每一个面
- ComputeAverageBrightness:根据Mip[0]生成全套的mipmap,然后均一化亮度
- FilterReflectionEnvironment:遍历6个面,计算天光球谐做为漫射部分;执行重要性采样,生成天光IBL作为高光反射部分,最后把计算的光照结果拷贝到Skylight的ProcessedTexture中。
接下来就是Shader中依据Roughness采样Mipmap各级Level重建照明,这样就完成了整套IBL+ SH的实现。如果涉及多个SkyLight Component的混合,请详见另一个队列——SkyCapturesToUpdateBlendDestinations然后继续按照这个思路一个环节一个环节的捋顺执行过程。
这就是SkyLight,所以它本质上与反射球没什么差别,只不过是作用于整个场景的。因为它也作为一个光照组件存在所以部分朋友将其与前面四类灯光一起归到了直接光中。但按照UE4对GI的设计理念与SkyLight的工作逻辑,它应该是环境光组成部分。
三,基于物理的着色
分析完UE4是如何实现PBL的,我们来看下物理着色部分,也就是UE4的整套内建着色器系统
1,材质装配流程
分析UE4的着色框架,首先要弄清楚它的材质是怎么工作的:
UE4材质装配流程图
如上图,如果我们将UE4的PC端,Mobile端,Forward与Deferred全部拆开的话引擎一共有四条内置渲染管线,引擎的内建着色器为每一类网格提供了一套对应的顶点工厂与整套的PBR的着色框架,这套框架包含如下内容:
- 顶点阶段的空间变换,曲面细分与几何着色器(可选)
- 数据流的存储结构与传递函数:从DCC Fetch数据,顶点变换,输出写入Varying,从Shadermap传入20个Parameters并计算光照矢量与PBR中间量,光照计算与着色每一步都涉及到不同阶段或者来自多个阶段数据的存储与处理,如何高效组织这些中间数据,是工程化非常重要的一个指标
- GBuffer的编码与解码
- 光照叠加:直接光,各类环境光,各类阴影与AO,屏幕空间效果,后处理等
在本专栏的第二章第一节分析了UE4的MeshDrawPipeline:
每一个通过可见性测试的FPrimitiveSceneProxy都会被封装成MeshBatch从而经历不同pass完成整个渲染流水线的加工最终绘制到屏幕上,UE4的Engine,Renderer,RHI模块与内建着色器框架完成了上面所有工作。各类渲染方案造就了赏心悦目的裸模效果,我们衡量引擎默认画面质感就是比拼的这些。
但这还远不足以区分出大千世界。引擎把剩下的部分以蓝图形式暴露到了编辑器由TA或者3D艺术家完成最上层的“包装与赋能”。各类贴图,计算最终会通过master节点的20个pin接口经由HLSLTranslator.cpp与MaterialTemplate.ush翻译成有限个Parameters与Vertex阶段计算得到的数据汇总在一起共同构成整套PBR计算必须的所有初始值,这是一套被精心设计过的拼图,用户仅用手里有限的板块就能完成整幅PBR画卷。
我们研究UE4的渲染方案从方向上讲就可以分为2部分,其一是C++部分如何进行灯光排序,剔除,各个Pass如何组织,以及一些不适合部署到HLSL种的方案算法实现,也就是重点阅读Engine,Render与RHI模块;其二就是整套内建着色器框架的设计思路与各类方案的代码实现。
目的是什么呢?如何从0开始徒手撸PBR!工程上需要考虑的远比看懂PBRT或者自己写个demo渲染器多得多,在第二章的2,3节分别针对PC端与Mobile的渲染管线分析了C++部分的组织逻辑:
这里就简单聊下UE4的内建着色器框架。
2,内建着色器框架
引擎的内建着色器非常庞大,逐行去看是不可能的,而且最让人头疼的一点是它有4条管线,非常容易乱,但其实拨开迷雾真正需要TA去关注和了解实现细节的也就下面这几十个文件,不到5000行HLSL代码:
UE427核心内建着色器层级表
这幅图由下至上给出了不同粒度的代码部署情况,层层封装,一个大的趋势是下面定义的功能会被上面的文件所引用,但也存在部分网状的引用关系。
最下层的是基础功能的实现,像球谐,动态光衰减,球面高斯,矩形光与胶囊体光照的功能函数;再往上是体积云,雾(高度雾,体积雾),两套大气解决方案;以及BRDF的封装;这两层代码属于功能层代码,相互之间解耦程度是可以做到非常高的,可以交给不同的人去开发。我们管这种程式设计思想叫做"模块化"或者“低耦合”。
再往上就是着色模型的封装,上文提到过不同的引擎对GI是如何组成的有着不同的定义,UE4是属于分的比较细的引擎。直接光被分为了漫射,高光反射与3S三个部分,高光的分布对PBR的质感影响非常大,其次是SSS,所以这3项共同被封装成了叫做ShadingModel的计算模型,不同ShadingModel根据其描述的材质种类不同使用下层定义好的不同的BXDF,这样一来能够对直接照明进行比较精细的控制。环境光则被分为了漫射与反射两部分,根据是否Moveable使用光线追踪拍预计算出的Lightmap或者球谐函数,IBL等方案组合解决,而且对AO进行了重点设计,来避免严重的漫射漏光与反射漏光【也就是美术所讲的“发飘”问题】,这样一来对环境光也可以进行非常精细的控制,当然不同的ShaderTarget方案不太相同,有需要定制就是渲染向TA出场的时候了。
再往上就是管线框架层代码了。对于PC平台来讲,Forward+与Deferred其实可以共用着色模型层实现,无需写两套,所以针对不同的渲染管线又有针对性的选择, 反正做到相当一部分代码可共用就行了,我们管这种程式设计思想叫做“高聚合”。同样的,无论是PC端Forward还是Deferred的Geometry Pass都需要BasePass的功能,所以这部分代码也应被设计为共用,因此它PC端BasePassPixelShader才读起来这么乱!至于Deferred的光照部分,实现则独立开来,然后在LightingPass阶段完成,可以去阅读FDeferredShadingSceneRenderer类的Lightingpass方法了解具体细节。
对于移动平台呢, ES 3.1要简单非常多,除了功能层少数方案有调用,整个着色模型层绝大部分会依据移动端需要重写,直接光的ShadingModel从4.25开始是独立的【425以前移动端就没ShadingModel这回事,全部退化成Unlit与DefaultLit!】,至于IBL采样,ILC采样等因为不需要设计的太复杂直接丢到MobileBasePassPixelShader.usf中,定义与调用一个文件解决。至于从4.26开始集成的移动端Deferred目前还是一个基础版,我了解的猪鹅二厂都有“第一个吃螃蟹”的团队,不管笔者没操练过只是看过对应的源码实现。
这就是UE4内建着色系统中最核心的部分,我们大部分工作都是围绕这些C++与HLSL代码的修改进行的。至于后处理,蒙特卡洛,低差异序列等只要用UE4引擎做项目基本就永远不会改动这些东西,所以对TA来说也没啥看的必要性【除非你要自己写渲染器,或者抄到别的引擎】
3,第一个灵魂拷问
接下来有一个相当常见,但很多人又写的迷迷糊糊的事情:加ShadingModel!
常见是因为网上教程已经烂大街了,但值得注意是因为加的是否恰当,因为对于一个做渲染的人来讲,在UE4里加ShadingModel至少得考虑3件事:
- 是否要支持光线追踪?
- 用的哪条管线?
- 是否需要统一SM5与ES3.1下的效果?
上面3点决定了我们要改哪些文件的哪些Block以及怎么改的问题,至于新的BXDF封装,IBL,AO的Modulate等根据需要定制就行,但不要改到没用的文件~。编辑器要改哪些,Client的C++管线要改哪些,对应的HLSL要改哪些都是事出有因的,咱不能编译通过不报错就万事大吉~ 。这就是UE4比较蛋疼的一点,但凡要魔改一丢丢就得熟悉整套框架是怎么工作的,特别是NPR项目。
<hr/> 本节正文结束,接下来为唠叨部分!
<hr/>四,你这引擎PBR嘛?
最后,第二个灵魂拷问:
我觉得所有渲染开发者都应该发出这样的灵魂拷问。之前见过很多引擎组的朋友万字长文,又是微表面,又是GGX,又是IBL球谐函数,最后效果还不如我美术手画贴图+Blinn-Phong!这里没有吐槽的意思,我是抱着非常严肃的态度讨论这个问题的。为什么几万条指令的计算堆上去画面效果一点都不GroundTruth,甚至还不如PS随便画画呢?这是大家都应该认真思考的问题。
很多朋友对这一块其实没有深入考虑过,因为现在几乎没有项目需要TA去从画三角形开始做PBR了,UE4与Unity占据了大半壁江山,人家功能都做好了直接拿来用就行,但从另一个角度讲也挺可惜的,所以想一想确实渲染向TA有必要自己手撸套渲染器来扎实基础。
笔者也玩过几款引擎,包括两款自研引擎,以及一部分学术目的为导向的开源引擎。而且有幸参与过一款项目自用自研引擎的内建着色器框架开发,我感觉可能有以下原因:
1,光照与着色计算的严谨性
PBR嘛,如本文第一部分所述,肯定PBL与PBS都得照顾到了,在万字长文分析”咱家引擎是怎么做PBR之前“,我们先确认一件事请,引擎的光照度量单位有统一规范嘛?Candela,Lux,lm,Watt这么多计量单位,不同单位对应着不同物理量或者相同物理量的不同强度值,引擎内部在处理的时候是否是严谨靠谱的。强度值不一样,在漫长的渲染流水线之后一个典型的表现就是关了后处理颜色值也对不上,这份痛苦估计走过双引擎流程的团队都清楚。
再举一个例子,引擎支持几种光源?内部数据精度转化是怎样的?拿最简单的直接光举例子,工程实现上平行光的强度,颜色,方向这些数据是拿几个Uniform存储的,如果不是平行光聚光灯的衰减是如何实现的?是否支持面积光源?面积光源是否具有形状不变性?支持GGX嘛,是各向同性的GGX还是各项异性的GGX等等这些都是实际存在的问题。
照明问题相对简单,PBS要更为繁琐一些。漫长的着色流水线任何一个环节出了问题都会导致效果不那么PBR。比如常见的SSAO问题,引擎的GI采样,比如球谐的阶数,辐照图的编码,阴影精度,后处理算法等等非常多的细节需要考虑
2,渲染方案的拟合手法
谈到PBS不得不说拟合的问题,很多渲染方案我们都是基于原型进行简化或者曲线拟合得到的,比如UE4的Hair ShadingModel,可以看之前写的这篇:
它既不是原生的Marschner又不是原生的d&#39;Eon,那些推导后的解析式这么复杂,不可能直接对着敲代码,这个时候就要有针对性的对公式进行变形与简化,或者干脆进行拟合。拟合的偏差控制原本就是一件很主观的事情。再比如,大气散射模拟是程序化天空盒必须的,其中常用的预计算光学深度查找表怎么设计也是一个很主观的事情啊,采样点采多少怎么采就是这些细节堆在一起,某个关键步骤差一点最后输出效果拉跨非常多。或者干脆在渲染方案中出现原则性的错误,这些工程问题导致了乍一看源码该有的都有,实际效果土成狗。
这就是为什么大家都是PBR,但是裸模效果差非常多的原因。
3,美术流程的把控
前面两点都是引擎的问题,引擎设计好后,怎样的美术Pipeline也是影响非常大的一部分环节。影响非常大的是贴图,Substance官方给出了一套非常有借鉴价值的Metaliic-Roughness贴图设计流程,但实际上不少情况下我们做的时候都是视觉引导性的,这样不是不可以,但需要注意生产环节的严谨性,偏的太离谱就得构建自己的标准。另外一个方面就是模型的设计问题,很多美术同学会遇到亮部效果调好了但暗部死黑,再调亮部又过曝了的情况,然后要TA去改Shader,但实际情况是像一些大平面结构在统一的场景光照下它暗部就是受光不足的。。,总不能为了这么一个模型改光照方案吧,或者类似原本应该设计为整体的,但却拆开了结果放到场景中发现漏光等等,像这些问题是属于原画或者模型设计阶段就应该规避掉的,与引擎的GI计算或者AO算法关系甚微。更有离谱的比如基于PBR的思路去做风格化,然后场景,角色的GI方案是分开的,这会造成很大的生产问题。除此之外还有打光等等,几乎每一个环节不够严谨都会导致做出来的东西不那么PBR,但看着又不那么风格化。。。
Reference:
[1] LTC:https://eheitzresearch.wordpress.com/415-2/
[2] Unreal的动态天光:https://zhuanlan.zhihu.com/p/93338549 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|