ue5-预计算可视性体积(PVS)

构建pvs

FStaticLightingSystem::BeginLightmassProcess在lightmass的构建过程中,如果设置了pvs的构建则会一起构建。执行InitiateLightmassProcessor,然后在里面执行LightmassProcessor->InitiateExport

在里面如果选择了生成pvs则会创建FGuid::NewGuid

然后执行Exporter->WriteToChannel(Statistics, DebugMappingGuid);将VisibilityBucketGuids写入scene里面。

然后通过swarm来分布式写入文件Swarm.WriteChannel( Channel, &Scene, sizeof(Scene) );

PrecomputedVisibility体积计算与存储

然后在FLightmassExporter::WriteToChannel里通过WriteVisibilityData写入可见数据。

在FLightmassExporter::WriteVisibilityData里会拿所有的APrecomputedVisibilityVolume然后通过Volume->GetComponentsBoundingBox拿到这个

APrecomputedVisibilityVolume放置的范围。

并且如果有设置APrecomputedVisibilityOverrideVolume则会拿到希望覆盖的区域的范围并写入文件。

限制:

然后执行ApplyPrecomputedVisibility,这里会建立CombinedPrecomputedVisibilityCells,如果格子的x和y范围都在10000以内则开始遍历获取可见对象。

对cell范围内的对象执行SpreadVisibilityCell,取获取其他cell里面的可见对象信息。

这里面的AccumulateVisibility就是会将邻居的可见性与当前单元格的可见性相结合,这样可以减少可见性错误,但代价是剔除效率较低。

然后讲数据压缩为NAME_Zlib模式

运行时执行pvs:

在FDeferredShadingSceneRenderer::InitViews执行ComputeViewVisibility来获取可视信息。

FSceneRenderer::ComputeViewVisibility中执行View.PrecomputedVisibilityData = ViewState->GetPrecomputedVisibilityData(View, Scene);获取可见数据。

计算可见几何体

在FSceneRenderer::ComputeViewVisibility计算出可是对象后,通过执行OcclusionCull来剔除对象。

在SceneVisibility.cpp的OcclusionCull中如果拿到View.PrecomputedVisibilityData的数据说明有pvs的数据。他遍历View.PrimitiveVisibilityMap中的所有几何体数据,如果(View.PrecomputedVisibilityData[VisibilityId.ByteIndex] & VisibilityId.BitMask)也就是pvs的数据和当前的几何对象数据不重合,说明不在可视范围内,则把他隐藏。

获取数据:

在SceneOcclusion.cpp中FSceneViewState::GetPrecomputedVisibilityData是获取具体的视野和场景里面的可见对象列表。

Bucket和Cell:

首先如果开启了pvs则GAllowPrecomputedVisibility会为true

如果有pvs的数据,那么他的数据是通过Bucket和Bucket下的Cell组成的。通过Handler.PrecomputedVisibilityCellBuckets来遍历Bucket以及Bucket下的cell来设置视锥内的显示对象

cell下的视锥范围pvs对象

然后根据视锥内的索引起点来确定bucket的视野偏移索引的xy。让PrecomputedVisibilityBucketIndex平铺为一维数组。然后通过Handler.PrecomputedVisibilityCellBuckets来获取视锥内的可视对象。然后遍历这个bucket下的cell,看每个cell是否在视锥范围内。

如果在范围内则记录到从CachedVisibilityChunk中拿到PrecomputedVisibilityData数据或者从压缩的FCompressedVisibilityChunk里面拿到数据。

解压数据并缓存

CachedVisibilityChunk中自然是之前缓存下来的数据。而FCompressedVisibilityChunk中就要通过FCompression::UncompressMemory然后通过类型为NAME_Zlib的方式解压zlib格式的数据。最终还是存在CachedVisibilityChunk中,然后返回PrecomputedVisibilityData数据出去。

猜你喜欢

转载自blog.csdn.net/llsansun/article/details/123947952