lumen在渲染的时候会走几个步骤:
第一是BeginUpdateLumenSceneTasks对场景的距离场体素重建
第二是UpdateLumenScene更新lumen的场景以及包括用nanite提出并且上传lumen的card
第三是RenderLumenSceneLighting获取lumen光照的直接光与间接光
第四是RenderLumenSceneVisualization可视化探针的获取与设置,体素步进与辐射度设置。
第五是RenderDiffuseIndirectAndAmbientOcclusion中对lumen的探针执行计算获取探针的光照来叠加。
这个是更新场景的card的分布信息。他叫做带距离场景。
首先获取NumDesiredCascades来获取从相机到远端的分布。最多是8个分布的包围盒。
如果数量不一致则要删除之前的card的分布。
然后开始建立类似级联阴影的长方体范围(简称包围盒吧)
GenerateCoordinateSystem(CardToLocalRotationZ, CardToLocalRotationX, CardToLocalRotationY);这里是通过CardToLocalRotationZ来建立出x轴和y轴。这个是为了后面建立每个包围盒下的范围做准备的。
SplitNear = GetCascadeStartDistance(CascadeIndex, NumDesiredCascades);
这里是获取包围盒离相机最近的距离。
SplitFar = GetCascadeStartDistance(CascadeIndex + 1, NumDesiredCascades);是包围盒离相机的最远距离。
CascadeBounds = GetCascadeBounds(View, SplitNear, SplitFar);这里是获取包围盒的整个bounds。
LumenSceneData.Cards[DistantCardIndex].SetTransform(FMatrix::Identity, CascadeCenter, CardToLocalRotationX, CardToLocalRotationY, CardToLocalRotationZ, LocalExtent);这里是设置整个card的包围盒的范围到card上。
完成整个card的设置。
如果设置了需要显示这个card的包围盒的信息,在后面会设置显示。
其中DrawWireBox是底层提供的绘制线框的接口
FSimpleElementCollector::DrawLine这里画线。画整个线框是:
这个是对lumen场景中的三角形做卸载和加载。
首先要对要移除的三角形从大到小排序,LumenSceneData.PendingRemoveOperations.Sort(FGreaterLumenPrimitiveIndex())
然后移除三角形,
接下来就是对需要加入到场景的对象做加入场景的操作。
首先会通过LocalToWorld和LocalBoundingBox来确定是否所有三角形都在范围内。然后如果是nanite下的话必然有一个instances。
然后查看这些三角形是否能合并成一个meshcard来处理,主要让三角形大小跟GLumenMeshCardsMergedMaxWorldSize比较,如果小于这个大小则可以合并成一个meshcard。然后组成一个FLumenPrimitive。如果不能合并则每个instance都单独一个FLumenPrimitive
然后会看是否可以执行raytracing,然后用sdf来加入sdf的index进来。加入到可以加入到lumen更新的sdf信息。
以上的添加三角形的过程,然后就会进行更新三角形的过程。还是通过bMergedInstances来确定是否可以合并到一个meshcard,如果可以就只执行一个LumenSceneData.UpdateMeshCards,如果不能合并就每个单独走LumenSceneData.UpdateMeshCards。
这里的UpdateMeshCards主要做FLumenMeshCards中的所有MeshCardsInstance的数据更新到FLumenCard中,然后让FLumenCard的SetTransform应用到场景中。并存到CardIndicesToUpdateInBuffer来方便后面对card处理。
完成UpdateLumenScenePrimitives处理。
完成UpdateDirtyCards(Scene, bReallocateAtlas, bRecaptureLumenSceneOnce);
UpdateLumenScenePrimitives(Scene);UpdateDistantScene(Scene, Views[0]);后
用TArray
在NumMeshCardsAddsPerBucket这里对每个meshcard的权重数量增加,对meshcard的优先级排序MeshCardsAddsSortedByPriority。
然后就是添加FCardRenderData此信息到CardsToRender中,这个CardsToRender是用于在UpdateLumenScene中执行正式的渲染SubmitMeshDrawCommandsRange用的,首先根据距离添加
AllocateOptionalCardAtlases,主要给到LumenSceneData.IrradianceAtlas和LumenSceneData.IndirectIrradianceAtlas,这里是给到直接光照的rt和间接光照的rt。
UpdateLumenCardAtlasAllocation这里是拿到CardsToRender然后更新FLumenCard。
后面就开始更新CardsToRender下的rhi的uniform,如果是静态的则加入到静态处理的PrimitivesToUpdateStaticMeshes。
通过FPrimitiveSceneInfo::UpdateStaticMeshes来更新静态的网格。这里的UpdateStaticMeshes是ue通用的关于三角形的静态处理。他分为普通的静态处理和nanite的静态处理。
处理完静态网格后就是正式的丢到渲染中了
这里也是分为nanite版本和普通静态网格版本。如果是nanite则加入到NaniteInstanceIds让nanite单独处理。如果是普通版本则执行NewVisibleMeshDrawCommand.Setup
加入到MeshPassProcessor中,让mesh统一处理,这里只是设置了lumen的渲染指令,还没提交渲染,提交渲染是用MeshPassProcessor中的SubmitMeshDrawCommands或SubmitMeshDrawCommandsRange的。