--- title: Untitled date: 2024-12-08 12:18:54 excerpt: tags: rating: ⭐ --- # 阴影 ## 阴影类型 - **Static Shadow** - **Cascading Shadow Map** - **Per Object Shadow**:可移动组件使用的逐物体阴影应用阴影图到物体的包围盒,因此包围盒必须是精确的。对于骨骼网格,这意味着它们应该有一个物理资产。对于粒子系统,任何固定的边界框必须足够大,以容纳所有的粒子。_在网格的Lighting属性组中,Dynamic Inset Shadow可以开启逐物体阴影,对需要高质量高精度的物体非常有用。_ - **Dynamic Shadow**:可移动光源在所有物体上投射出完全动态的阴影(和光)。这种光源的任何数据不会被烘焙到光照图中,它可以自由地在所有东西上投射动态阴影。静态网格、骨架网格、粒子效果等等将完全从可移动光源投射和接收动态阴影。 - **Capsule Shadow** - **Contact Shadow** - **Distance Field Shadow** ## 相关类型 - ShadowRendering.h **FProjectedShadowInfo**:存储投影阴影先关信息。包含各种变换矩阵、阴影渲染函数以及渲染参数、灯光&场景&图元信息。 - SceneRendering.h FVisibleLightInfo:可见光源信息, 主要是阴影相关的信息. FVisibleLightViewInfo: ## DynamicShadows ### InitDynamicShadows() => CreateDynamicShadows() InitViews() => FSceneRenderer::InitDynamicShadows() PS. UE5.3中相关逻辑移动到***CreateDynamicShadows()*** 中了。InitDynamicShadows() => BeginInitDynamicShadows() => BeginGatherShadowPrimitives() => CreateDynamicShadows() 计算各种灯光类型,之后调用: - CreateWholeSceneProjectedShadow() - AddViewDependentWholeSceneShadowsForView() - SetupInteractionShadows() ### CreateWholeSceneProjectedShadow # 阴影偏移 可以考虑的Buffer有 - ShadowDepths - CustomDepth # 相关Paas 1. ShadowDepths 2. Lights 1. DirectLighting 1. UnbatchedLights 1. ShadowProjectionOnOpaque # ShadowDepths - FSceneRenderer::RenderShadowDepthMaps():位于CustomDepth之前。 - RenderVirtualShadowMaps() - RenderShadowDepthMapAtlases() - SortedShadowsForShadowDepthPass.ShadowMapCubemaps循环 - # Lights ### Shader ShadowProjectionPixelShader.usf - TShadowProjectionPS: - TDirectionalPercentageCloserShadowProjectionPS:方向光投影 - TSpotPercentageCloserShadowProjectionPS:SpotLight - FOnePassPointShadowProjectionPS(Moible?) ### 相关函数 - FDeferredShadingSceneRenderer::RenderLights() - FDeferredShadingSceneRenderer::RenderDeferredShadowProjections() - FSceneRenderer::RenderShadowProjections() - FProjectedShadowInfo::SetupFrustumForProjection():构建阴影投影4棱椎平面信息。 - FProjectedShadowInfo::SetupProjectionStencilMask(): # 其他 顺序: RenderCustomDepthPass FSceneRenderer::CreateDynamicShadows => FSceneRenderer::CreatePerObjectProjectedShadow ```c++ if (!IsForwardShadingEnabled(ShaderPlatform)) { // Dynamic shadows are synced later when using the deferred path to make more headroom for tasks. FinishInitDynamicShadows(GraphBuilder, InitViewTaskDatas.DynamicShadows, InstanceCullingManager, ExternalAccessQueue); } ``` ```c++ if (RendererOutput == ERendererOutput::DepthPrepassOnly) { RenderOcclusionLambda(); if (bUpdateNaniteStreaming) { Nanite::GStreamingManager.SubmitFrameStreamingRequests(GraphBuilder); } CopySceneCaptureComponentToTarget(GraphBuilder, SceneTextures, ViewFamilyTexture, ViewFamily, Views); } else { GVRSImageManager.PrepareImageBasedVRS(GraphBuilder, ViewFamily, SceneTextures); if (!IsForwardShadingEnabled(ShaderPlatform)) { // Dynamic shadows are synced later when using the deferred path to make more headroom for tasks. FinishInitDynamicShadows(GraphBuilder, InitViewTaskDatas.DynamicShadows, InstanceCullingManager, ExternalAccessQueue); } // Update groom only visible in shadow if (IsHairStrandsEnabled(EHairStrandsShaderType::All, Scene->GetShaderPlatform()) && RendererOutput == ERendererOutput::FinalSceneColor) { UpdateHairStrandsBookmarkParameters(Scene, Views, HairStrandsBookmarkParameters); // Interpolation for cards/meshes only visible in shadow needs to happen after the shadow jobs are completed const bool bRunHairStrands = HairStrandsBookmarkParameters.HasInstances() && (Views.Num() > 0); if (bRunHairStrands) { RunHairStrandsBookmark(GraphBuilder, EHairStrandsBookmark::ProcessCardsAndMeshesInterpolation_ShadowView, HairStrandsBookmarkParameters); } } // NOTE: The ordering of the lights is used to select sub-sets for different purposes, e.g., those that support clustered deferred. FSortedLightSetSceneInfo& SortedLightSet = *GraphBuilder.AllocObject(); { RDG_CSV_STAT_EXCLUSIVE_SCOPE(GraphBuilder, SortLights); RDG_GPU_STAT_SCOPE(GraphBuilder, SortLights); ComputeLightGridOutput = GatherLightsAndComputeLightGrid(GraphBuilder, bComputeLightGrid, SortedLightSet); } ```