ue4 离线渲染_UE4渲染引擎模块简介(2)

PSO Caching(Pipeline State Object Caching)

UE4用新的PSO Caching用来替代原来的FShaderCache。原来的FShaderCache实现的是对Shader代码(或二进制的ByteCode)进行Cache.新的PSO Caching则是ShaderCache的超集,它不仅Cache了渲染所用的Shader代码,同时也Cache了渲染状态.PSO Caching的设计在很大程度是贴合了新的渲染API的方向,向Vulkan的Pipeline Cache致敬

PSO Caching会把渲染状态、顶点声明、Primitive类型、RenderTarget像素格式等等的数据保存到文件中,或是从文件中加载它们——因为这些渲染状态数字类数据大都是一系列的Int或枚举类数据,空间大小占用有限,故没有做额外的处理。

但PSO Caching中不会直接保存Shader代码(不管是源代码或是编译好的二进制Shader),也不保存Shader的路径,它保存的是Shader路径的SHA1 Hash做为Shader唯一的索引,真正的Shader是由FShaderCodeLibrary管理。

Unreal Lightmass

Lightmass模块是UE4的烘焙渲染器,是一个单独的可执行文件。它工作在CPU上而非GPU上,配合UE自带的Swarm Agent和Swarm Coordinate实用程序,Lightmass还能实现分布式的烘焙。除了光照图,还烘焙阴影、AO,BentNormal、可见性、Mesh距离场等等。

Lightmass是一个基于简化版本的Photon mapping实现的渲染器,虽然有大量的示例证明它能渲染的和离线渲染器一样好。但我这半吊子离线民科还是强烈的感受到,实际上它的实现传统的离线渲染器相距甚远,实现的思路并没有考虑到离线渲染所关注的最大问题:海量资源的管理调度。

相对于暴力Path Tracing来说,Lightmass是有偏的。

相对于Jensen的提出Photon Mapping时的构想来说,Lightmass的实现是个阉割版。它失去了重构Caustic的可能;它不区分镜面和非镜面反射,Photon Trace的结果只有一份Photon Mapping;它内部的材质模型是单一的;它有实现诸如蒙特卡罗,Irrandiance Cachiing,Final Gather 等Photon Mapping的优化手法,但是许多实现都不是非常完善。

Lightmass中的光子被存在八叉树中,Jensen实现是基于数组的KD-Tree。

一整个场景中参与投影的Mesh在Lightmass里会被组织为一个硕大的Mesh,再使用KD-Tree对其进行划分以加速Ray Cast求交。UE4有实现一套自己的Mesh KD-Tree构建,但它默认的并不使用自己的这份Kd-tree,而是用的Intel的Embree库来表达场景快速求交。

Lightmass对几何体的光栅化是基于平底三角形拆分进行光栅化。

UE4烘焙的基本工作流程

Render Path

UE4目前支持3种渲染路径:移动端简单的Forward Render Path,PC/主机端的Deffered Render Path和Forward+。在FrameGraph尚未完善情况下,每种渲染器对应的渲染Pass是人肉组装的。

UE4用于组织渲染路径实现h/cpp文件的后缀均为Renderer,每个Renderer均由数个渲染Pass顺序级联而成,对于具体每个Pass的渲染实现和某个单独的功能性的渲染实现,UE4中的h/cpp文件后缀则是Rendering,如FogRendering,DepthRendering等等

Renderer的基类是FSceneRenderer,当你想实现一个自己的渲染路径时,它的核心接口只有一个:

虽然该接口名为Render,但实际上它的工作不止是渲染,它同时负责了更新部分数据、裁剪、遮挡剔除,组织渲染指令等工作。这就容易在和GPU进行渲染指令同步时出现断供和积压的情况,为了应对渲染线程在干这些脏活累活时的所带来的额外延迟,UE4一方面尽可能的把一些耗时大且可并行的任务扔到线程里去实现(如可见性计算,生成渲染指令),另外一方面还专门针对GPU同步的提交实现了一个RHI线程。

UE4渲染数据和命令组织、可视性计算是通过InitViews函数实现的,这不是FSceneRenderer的接口,但是FSceneRenderer的两个子类均有一个一样功能实现。

FDeferredShadingSceneRenderer用于其它非移动平台。它内部的实现是同时集成了延迟渲染和Forward+。在4.23开发版本中还看到有实现单独的Deffered Cluster Pass。关于Deffered Shading Renderer具体的渲染过程,每个Pass的功能分析,网上资料较为详实可观了。

UE4中用于移动端的渲染器叫FMobileSceneRenderer,它实现了一个传统的Forward Renderer。MobileRendeer最核心的Pass是MobileBasePass ,它的具体实现分两部分,CPU端的数据组织,Shader及其Permutation管理在MobileBasePassRendering.h/cpp中,Shader本身的实现则在MobileBasePassVertexShader.usf和MobileBasePassPixelShader.usf中。UE4的Shader Permutation是基于Pass和预编译宏来组合的,MobileBasePassPixelShader.usf也不利外,它实现了一个mesh着色的基本过程:从光照图、Shadowmap采样和计算、反射球采样、天光、到实时灯光、Fog混合等。在硬件支持的前提下,它还基于Frame Buffer Fetch实现了Alpha Blend。

UE4同时支持硬件遮挡剔除和软件遮挡剔除,只是它的软件遮挡剔除目前仅用于ES2相关的设备。

UE4 Render Path的实现包含在“Renderer”这一模块中。

Instancing

在Batch和Instancing这两项减少DrawCall的技术方案选型上,和U3D不同,UE4选的是Instancing,所以UE4的Batch功能是比较弱的,你在场景中放100个一模一样的Box,在没有Instancing时,它就是100个DrawCall。

UE4目前有三种Mesh相关的Instancing实现:

UInstancedStaticMeshComponent(ISM),静态的模型Instance,即我们在书上和其它引擎中最常见的Instance形式——只有位置相异而mesh和材质均完全相同的物体可以合并成一个Actor,在理想情况下只提交一次DrawCall。ISM好处是DrawCall少,坏处是LOD计算,裁剪和OC等等都是按一个对象来做,往往ISM的Drawcall减少了,但提交渲染的三角形却更多了。

UHierarchicalInstancedStaticMeshComponent(HISM),UE4中的HISM和ISM不同之处是它是基于分层实现。目的是为了满足一个Mesh有大量实例时分区域进行裁剪、计算LOD。UE中的植被就是HISM的子类。看到HISM大量的Console Variable都直接叫Foliagexxx...可以猜到的是HISM大概一开始是为植被系统所准备的。HISM的实现有两部分,一部分是构建分层(自动化的,每次修改它的instance个数、位置等都会触发)并保存到文件中,另一部分则是基于分层的可见性计算、LOD和渲染组织。

HISM的分层结构是一个KD-Tree,不过它的生成不是基于启发式平衡的结构去做,而是直接用的最长轴做为当前拆分轴,且简单粗暴的从长轴中间分开成左右子树,叶节点所包含的Instance数或三角形数由外部控制。

Dynamic Instance,UE4在4.22中支持的Dynamic Instance和上述的ISM/HISM虽同为Instancing,但实现上是完全不相关的。ISM/HISM的实现是静态的,需要显示的在场景中对相同物件强制打包到一个PrimitiveComponent下面,属于编辑阶段需要确定的数据组织功能。而Dynamic Instancing则是在渲染指令组织的时候,发现相同的mesh+pipeline state自动组装的。Dynamic Instance实现的核心是UE4实现了一个GPU Scene——用一个Buffer来存储全场景每个Primitive的Transform等信息,这样在组装出Instance Buffer之后只需用PrimitiveID就可以访问到自己的位置相关数据,从而实现Instance渲染了。

Dynmic Instance在4.22上的移动端没有实现,但其实只要稍微修改一下UE4使用的RWStructureBuffer为RWBuffer,并且把GPU Scene相关的检测和更新修正,就可以在手机端ES3.1 Feature上正常使用。

GPU Scene的实现可以参考GPUScene.h/cpp。

渲染模块的简介到这儿就基本结束了,光照的介绍、RayTracer的介绍、渲染线程之间的分工和交互、Shader生成和组织过程、Mesh渲染的流程、LOD更迭、HLOD、StreamingTexture等等主题。这些主题因为涉及到具体的算法和代码实现,放到单独文章里去介绍会更容易理解。

你可能感兴趣的:(ue4,离线渲染)