hdrp-延迟渲染光照渲染

BuildGPULightLists

在ExecuteRenderRequest中执行BuildGPULightLists来构建整个gpu的灯光列表。

BuildGPULightListsCommon

在LightLoop中的BuildGPULightListsCommon,在里面会通过PrepareBuildGPULightListParameters先准备好数据,在里面创建BuildGPULightListParameters,往里面填参数,包括要执行的cs。

然后在PrepareBuildGPULightListResources中创建BuildGPULightListResources,往里面填TileAndClusterData的Computebuffer。

ClearLightLists清除灯光列表

然后首先执行ClearLightLists,执行Runtime/Lighting/LightLoop/ClearLightLists.compute,清除之前的灯光列表信息。

GenerateLightsScreenSpaceAABBs计算NDC空间中的光的AABB

然后执行GenerateLightsScreenSpaceAABBs执行Runtime/Lighting/LightLoop/scrbound.compute,该程序的目标是计算NDC空间([0,1]范围)中光的AABB。灯光由一个凸体(长方体)表示,它有6个面(平面四边形)和8个顶点。

由于光量可能部分脱离屏幕,我们必须在计算AABB之前对其进行剪裁。剪裁产生的AABB(而不是光体积本身)可能会导致AABB松动。

为了避免处理透视变换的“Moebius扭曲”属性,我们使用齐次(投影)后透视坐标执行剪切。Blinn在题为“线裁剪”的论文中描述了这种裁剪方法。

该算法处理4个线程上的灯光。虽然在最坏的情况下,所有6个面都可能需要剪裁,但剪裁超过4个面是非常罕见的(通常,我们剪裁0、3或4个面)。有些面可能需要剔除而不是剪裁(前者更简单)。

重要的是要认识到,面部剔除可能最终会剔除5张(甚至全部6张)面部。这意味着剪裁的灯光体积可能会减少到单个多边形,或者根本没有。(想象一个视图体积完全或部分位于灯光体积内)。因此,我们必须在光体积测试中执行视图体积角。

BigTilePrepass屏幕范围的灯光列表

然后执行BigTilePrepass,执行到Runtime/Lighting/LightLoop/lightlistbuild-bigtile.compute

这里是对灯光列表的aabb进行比较,如果是屏幕范围内则加入可以计算光照的列表

BuildPerTileLightList每个tile的灯光列表

然后执行BuildPerTileLightList执行到Runtime/Lighting/LightLoop/lightlistbuild.compute

将修剪列表索引重新映射到原始g_vLightList。

VoxelLightListGeneration基于簇得到灯光列表

这里首先会执行clearClusterAtomicIndexShader,执行到Runtime/Lighting/LightLoop/lightlistbuild-clearatomic.compute

里面主要是清除g_LayeredSingleIdxBuffer,这个是跟这个簇相交的灯光的数量。

然后执行VoxelLightListGeneration,执行到Runtime/Lighting/LightLoop/lightlistbuild-clustered.compute。

通过SnapToClusterIdx,给到可见光的当前和附近灯光信息获取簇的id(clusterIdxs),

每个线程都会根据交叉口的所有粗糙灯光检查各自的clusters。最后,“iSum”表示与该簇相交的灯光数!数量会限制在128以内然后写入g_LayeredSingleIdxBuffer

我们所有的剔除数据都在同一个列表中,但在渲染时,环境光是分开的,所以我们需要移动索引以使其正常工作。

然后通过FetchPlane来识别灯光是否在地面,然后存到lightPlanes

然后记录分层光照列表g_vLayeredLightList

g_LayeredOffset存储分层光照的偏移信息

g_logBaseBuffer在开启深度的时候让指定的tile未知存储g_fClustBase

BuildDispatchIndirectArguments获取像素上所属材质

然后执行BuildDispatchIndirectArguments,执行到Runtime/Lighting/LightLoop/materialflags.compute

这里主要是获取这个像素用的是什么材质,默认是用g_BaseFeatureFlags,g_BaseFeatureFlags是用这几个shader

如果是有模板的,则会通过MATERIAL_FEATURE_FLAGS_FROM_GBUFFER获取材质类型,会在Lit.hlsl执行MaterialFeatureFlagsFromGBuffer,通过DecodeFromGBuffer也就是拿到gbuffer,主要拿inGBuffer2的a通道来获取材质类型,因为之前说outGBuffer2的a通道是厚度,或者是各向异性及金属度,或者是菲涅尔,根据用的材质决定。

clearDispatchIndirectShader清除间接光信息

执行Runtime/Lighting/LightLoop/cleardispatchindirect.compute

这里是清除g_DispatchIndirectBuffer的数据。

buildDispatchIndirectShader构建间接光的索引

执行Runtime/Lighting/LightLoop/builddispatchindirect.compute

在这里构建间接光照,首先检查是否没有材质(表示它是天空/背景像素)。我们可以没有灯光,但仍然需要使用预先计算的照明渲染几何体。最后记录间接光影响的信息到tile的索引到g_TileList中。

 完成BuildGPULightListsCommon。

计算间接光照

在LightLoop.cs中,InitializeLightLoop会初始化好29个s_shadeOpaqueIndirectFptlKernels。然后在RenderComputeDeferredLighting时执行所有的OpaqueIndirect的kernels。

在Runtime/Lighting/LightLoop/Deferred.compute中执行SHADE_OPAQUE_ENTRY关于USE_INDIRECT的逻辑。g_TileList是之前存储的间接光的tile的索引。通过DECODE_FROM_GBUFFER执行DecodeFromGBuffer,这里面是通过gbuffer来计算光照的地方。填充BSDFData。还返回从G缓冲区的内容推断出的(每像素)材质特征标志,该标志可由特征分类系统使用。请注意,返回类型不是来自_GBUFFER的宏解码_的一部分,因此根据需要使用返回值是安全的。“tileFeatureFlags”是功能分类系统提供的编译时标志。如果未使用要素分类系统,请传递UINT_MAX。此外,请参阅TileVariantToFeatureFlags中的注释。当我们遇到更糟糕的情况(即最后一个变体)时,我们从结构化缓冲区读取featureflags,以生成间接绘制调用。它允许不通过所有分支,并且分支是标量的(不是VGPR)。

在材质处理中,对于材质分类,我们将tileFeatureFlags指定给bsdfData。材质特征这意味着tile内部的分支将是使用相同的材质。AMD GCN上的分歧分支意味着我们将对所有分支执行这两个分支。我们在像素级设置值,这样一个特定的分支在不应该的情况下就不会生效。例如,如果启用了SSS,则将sssMask设置为0不会产生任何影响,可以安全地将SSS分支用于tile。请注意,在物料分类的catch all变量中,从分类过程中完成的结构缓冲区中获取值。

着色器或其他着色器不会从材质分类中的最后一个catch all variant调用生成材质分类,这意味着我们在材质分类中的特定情况下(目前我们有variant 0)调用的同一个平铺中有所有可能的材质。发生这种情况时,我们更喜欢使用pixelFeatureFlags而不是tileFeatureFlags作为bsdfData。可以在一块tile内有分歧(比如是否有各向异性),但更可能的是整个时间都是收敛的(就像所有东西都有SSS和透明涂层)。

各向异性的特殊处理:当一块tile中存在各向异性时,整个tile将使用各向异性来避免对GGX的不同评估,从而增加成本。注意,这意味着当我们遇到更糟糕的情况时,我们总是使用各向异性和类着色器。

函数解析:

在SHADE_OPAQUE_ENTRY的LightLoop中,执行到LightLoop.hlsl的LightLoop,拿到关于这个位置的所有光照信息,然后循环获取光照来执行EvaluateBSDF_Punctual及AccumulateDirectLighting计算颜色信息。

这里29个SHADE_OPAQUE_ENTRY的区别是VARIANT,通过TileVariantToFeatureFlags去获取到材质信息。在Lit.hlsl中TileVariantToFeatureFlags是去拿kFeatureVariantFlags的枚举,

​​​​​​​

最终整个函数返回的是漫反射和高光颜色

specularLightingUAV和diffuseLightingUAV,其中diffuseLightingUAV还会考虑次表面的影响TagLightingForSSS

猜你喜欢

转载自blog.csdn.net/llsansun/article/details/123598987
今日推荐