diff --git a/.obsidian/app.json b/.obsidian/app.json index 30a8653..f238333 100644 --- a/.obsidian/app.json +++ b/.obsidian/app.json @@ -24,5 +24,6 @@ "09-Templates/" ], "readableLineLength": false, - "lineWrap": true + "lineWrap": true, + "strictLineBreaks": false } \ No newline at end of file diff --git a/03-UnrealEngine/Rendering/Lighting/VirualShadowMap.md b/03-UnrealEngine/Rendering/Lighting/VirualShadowMap.md deleted file mode 100644 index 17db8c1..0000000 --- a/03-UnrealEngine/Rendering/Lighting/VirualShadowMap.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: VirualShadowMap -date: 2023-03-18 09:27:10 -excerpt: -tags: -rating: ⭐ ---- diff --git a/03-UnrealEngine/Rendering/RenderingPipeline/Lighting/Lighting.md b/03-UnrealEngine/Rendering/RenderingPipeline/Lighting/Lighting.md new file mode 100644 index 0000000..53d4d1d --- /dev/null +++ b/03-UnrealEngine/Rendering/RenderingPipeline/Lighting/Lighting.md @@ -0,0 +1,202 @@ +--- +title: Untitled +date: 2025-02-11 11:30:34 +excerpt: +tags: +rating: ⭐ +--- + +# FSortedLightSetSceneInfo + +有序的光源集合相关定义: +```c++ +/** Data for a simple dynamic light. */ +class FSimpleLightEntry +{ +public: + FVector3f Color; + float Radius; + float Exponent; + float InverseExposureBlend = 0.0f; + float VolumetricScatteringIntensity; + bool bAffectTranslucency; +}; + +struct FSortedLightSceneInfo +{ + union + { + struct + { + // Note: the order of these members controls the light sort order! + // Currently bHandledByLumen is the MSB and LightType is LSB /** The type of light. */ uint32 LightType : LightType_NumBits; + /** Whether the light has a texture profile. */ + uint32 bTextureProfile : 1; + /** Whether the light uses a light function. */ + uint32 bLightFunction : 1; + /** Whether the light uses lighting channels. */ + uint32 bUsesLightingChannels : 1; + /** Whether the light casts shadows. */ + uint32 bShadowed : 1; + /** Whether the light is NOT a simple light - they always support tiled/clustered but may want to be selected separately. */ + uint32 bIsNotSimpleLight : 1; + /* We want to sort the lights that write into the packed shadow mask (when enabled) to the front of the list so we don't waste slots in the packed shadow mask. */ + uint32 bDoesNotWriteIntoPackedShadowMask : 1; + /** + * True if the light doesn't support clustered deferred, logic is inverted so that lights that DO support clustered deferred will sort first in list + * Super-set of lights supporting tiled, so the tiled lights will end up in the first part of this range. + */ + uint32 bClusteredDeferredNotSupported : 1; + /** Whether the light should be handled by Lumen's Final Gather, these will be sorted to the end so they can be skipped */ + uint32 bHandledByLumen : 1; + } Fields; + /** Sort key bits packed into an integer. */ + int32 Packed; + } SortKey; + + const FLightSceneInfo* LightSceneInfo; + int32 SimpleLightIndex; + + /** Initialization constructor. */ + explicit FSortedLightSceneInfo(const FLightSceneInfo* InLightSceneInfo) + : LightSceneInfo(InLightSceneInfo), + SimpleLightIndex(-1) + { + SortKey.Packed = 0; + SortKey.Fields.bIsNotSimpleLight = 1; + } + explicit FSortedLightSceneInfo(int32 InSimpleLightIndex) + : LightSceneInfo(nullptr), + SimpleLightIndex(InSimpleLightIndex) + { + SortKey.Packed = 0; + SortKey.Fields.bIsNotSimpleLight = 0; + }}; + +/** + * Stores info about sorted lights and ranges. + * The sort-key in FSortedLightSceneInfo gives rise to the following order: + * [SimpleLights,Clustered,UnbatchedLights,LumenLights] * Note that some shadowed lights can be included in the clustered pass when virtual shadow maps and one pass projection are used. */struct FSortedLightSetSceneInfo +{ + int32 SimpleLightsEnd; + int32 ClusteredSupportedEnd; + + /** First light with shadow map or */ + int32 UnbatchedLightStart; + + int32 LumenLightStart; + + FSimpleLightArray SimpleLights; + TArray SortedLights; +}; +``` + +## 开始获取有序光源集合 +UE的光源分配由`FDeferredShadingSceneRenderer::Render`内的`bComputeLightGrid`变量决定的,bComputeLightGrid的赋值逻辑如下: +```c++ +void FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList) { +... + bool bComputeLightGrid = false; + + if (RendererOutput == ERendererOutput::FinalSceneColor) + { + if (bUseVirtualTexturing) + { + // Note, should happen after the GPU-Scene update to ensure rendering to runtime virtual textures is using the correctly updated scene + FVirtualTextureSystem::Get().EndUpdate(GraphBuilder, MoveTemp(VirtualTextureUpdater), FeatureLevel); + } + +#if RHI_RAYTRACING + GatherRayTracingWorldInstancesForView(GraphBuilder, ReferenceView, RayTracingScene, InitViewTaskDatas.RayTracingRelevantPrimitives); +#endif // RHI_RAYTRACING + + bool bAnyLumenEnabled = false; + + { + if (bUseGBuffer) + { + bComputeLightGrid = bRenderDeferredLighting; + } + else + { + bComputeLightGrid = ViewFamily.EngineShowFlags.Lighting; + } + + for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) + { + FViewInfo& View = Views[ViewIndex]; + bAnyLumenEnabled = bAnyLumenEnabled + || GetViewPipelineState(View).DiffuseIndirectMethod == EDiffuseIndirectMethod::Lumen + || GetViewPipelineState(View).ReflectionsMethod == EReflectionsMethod::Lumen; + } + + bComputeLightGrid |= ( + ShouldRenderVolumetricFog() || + VolumetricCloudWantsToSampleLocalLights(Scene, ViewFamily.EngineShowFlags) || + ViewFamily.ViewMode != VMI_Lit || + bAnyLumenEnabled || + VirtualShadowMapArray.IsEnabled() || + ShouldVisualizeLightGrid()); + } + } +... +} +``` + +获取有序的光源集合 +```c++ +void FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList) { +... + // 有序的光源集合. + FSortedLightSetSceneInfo& SortedLightSet = *GraphBuilder.AllocObject(); + { + RDG_CSV_STAT_EXCLUSIVE_SCOPE(GraphBuilder, SortLights); + RDG_GPU_STAT_SCOPE(GraphBuilder, SortLights); + ComputeLightGridOutput = GatherLightsAndComputeLightGrid(GraphBuilder, bComputeLightGrid, SortedLightSet); + } +... +} +``` + +## +```c++ +FComputeLightGridOutput FDeferredShadingSceneRenderer::GatherLightsAndComputeLightGrid(FRDGBuilder& GraphBuilder, bool bNeedLightGrid, FSortedLightSetSceneInfo& SortedLightSet) +{ + SCOPED_NAMED_EVENT(GatherLightsAndComputeLightGrid, FColor::Emerald); + FComputeLightGridOutput Result = {}; + + bool bShadowedLightsInClustered = ShouldUseClusteredDeferredShading() + && CVarVirtualShadowOnePassProjection.GetValueOnRenderThread() + && VirtualShadowMapArray.IsEnabled(); + + const bool bUseLumenDirectLighting = ShouldRenderLumenDirectLighting(Scene, Views[0]); + + GatherAndSortLights(SortedLightSet, bShadowedLightsInClustered, bUseLumenDirectLighting); + + if (!bNeedLightGrid) + { + SetDummyForwardLightUniformBufferOnViews(GraphBuilder, ShaderPlatform, Views); + return Result; + } + + bool bAnyViewUsesForwardLighting = false; + bool bAnyViewUsesLumen = false; + for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) + { + const FViewInfo& View = Views[ViewIndex]; + bAnyViewUsesForwardLighting |= View.bTranslucentSurfaceLighting || ShouldRenderVolumetricFog() || View.bHasSingleLayerWaterMaterial || VolumetricCloudWantsToSampleLocalLights(Scene, ViewFamily.EngineShowFlags) || ShouldVisualizeLightGrid(); + bAnyViewUsesLumen |= GetViewPipelineState(View).DiffuseIndirectMethod == EDiffuseIndirectMethod::Lumen || GetViewPipelineState(View).ReflectionsMethod == EReflectionsMethod::Lumen; + } + + const bool bCullLightsToGrid = GLightCullingQuality + && (IsForwardShadingEnabled(ShaderPlatform) || bAnyViewUsesForwardLighting || IsRayTracingEnabled() || ShouldUseClusteredDeferredShading() || + bAnyViewUsesLumen || ViewFamily.EngineShowFlags.VisualizeMeshDistanceFields || VirtualShadowMapArray.IsEnabled()); + + // Store this flag if lights are injected in the grids, check with 'AreLightsInLightGrid()' + bAreLightsInLightGrid = bCullLightsToGrid; + + Result = ComputeLightGrid(GraphBuilder, bCullLightsToGrid, SortedLightSet); + + return Result; +} +``` \ No newline at end of file