From 5d45822c38f7c03dd7afaa7307cd63ef0ab95636 Mon Sep 17 00:00:00 2001 From: BlueRose <378100977@qq.com> Date: Mon, 24 Mar 2025 17:49:25 +0800 Subject: [PATCH] vault backup: 2025-03-24 17:49:25 --- .../渲染功能/ToonReflection&GI控制/ToonReflection.md | 233 +++++++++++++++++- 1 file changed, 231 insertions(+), 2 deletions(-) diff --git a/03-UnrealEngine/卡通渲染相关资料/渲染功能/ToonReflection&GI控制/ToonReflection.md b/03-UnrealEngine/卡通渲染相关资料/渲染功能/ToonReflection&GI控制/ToonReflection.md index 7e50578..32bcc73 100644 --- a/03-UnrealEngine/卡通渲染相关资料/渲染功能/ToonReflection&GI控制/ToonReflection.md +++ b/03-UnrealEngine/卡通渲染相关资料/渲染功能/ToonReflection&GI控制/ToonReflection.md @@ -19,7 +19,7 @@ rating: ⭐ 不开启Lumen GI,反射方法为: - Lumen:`RenderLumenReflections()` -- Rtx Reflection:`RenderRayTracingReflections()` +- RT Reflection:`RenderRayTracingReflections()` - SSR:`ScreenSpaceRayTracing::RenderScreenSpaceReflections()` `RenderDeferredReflectionsAndSkyLighting()`主要执行了: @@ -40,7 +40,7 @@ rating: ⭐ 几种反射方式的大致执行逻辑: - LumenReflection 1. 输出FRDGTextureRef ReflectionsColor。 -- SSR与Rtx +- SSR与RT 1. 输出结果到IScreenSpaceDenoiser::FReflectionsInputs DenoiserInputs的FRDGTextureRef Color。 2. 执行对应的降噪算法。 3. 结果赋予给FRDGTextureRef ReflectionsColor。 @@ -287,5 +287,234 @@ float3 ReflectionEnvironment(FGBufferData GBuffer, float AmbientOcclusion, float return -min(-Color.rgb, 0.0); } ``` + +### GatherRadiance() +```c++ +float3 GatherRadiance(float CompositeAlpha, float3 TranslatedWorldPosition, float3 RayDirection, float Roughness, float3 BentNormal, float IndirectIrradiance, uint ShadingModelID, uint NumCulledReflectionCaptures, uint CaptureDataStartIndex) +{ + // Indirect occlusion from DFAO, which should be applied to reflection captures and skylight specular, but not SSR + float IndirectSpecularOcclusion = 1.0f; + float3 ExtraIndirectSpecular = 0; + +#if SUPPORT_DFAO_INDIRECT_OCCLUSION + float IndirectDiffuseOcclusion; + GetDistanceFieldAOSpecularOcclusion(BentNormal, RayDirection, Roughness, ShadingModelID == SHADINGMODELID_TWOSIDED_FOLIAGE, IndirectSpecularOcclusion, IndirectDiffuseOcclusion, ExtraIndirectSpecular); + // Apply DFAO to IndirectIrradiance before mixing with indirect specular + IndirectIrradiance *= IndirectDiffuseOcclusion; +#endif + + const bool bCompositeSkylight = true; + return CompositeReflectionCapturesAndSkylightTWS( + CompositeAlpha, + TranslatedWorldPosition, + RayDirection, + Roughness, + IndirectIrradiance, + IndirectSpecularOcclusion, + ExtraIndirectSpecular, + NumCulledReflectionCaptures, + CaptureDataStartIndex, + 0, + bCompositeSkylight); +} +``` + + +```c++ +float3 CompositeReflectionCapturesAndSkylightTWS( + float CompositeAlpha, + float3 TranslatedWorldPosition, + float3 RayDirection, + float Roughness, + float IndirectIrradiance, + float IndirectSpecularOcclusion, + float3 ExtraIndirectSpecular, + uint NumCapturesAffectingTile, + uint CaptureDataStartIndex, + int SingleCaptureIndex, + bool bCompositeSkylight, + uint EyeIndex) +{ + float Mip = ComputeReflectionCaptureMipFromRoughness(Roughness, View.ReflectionCubemapMaxMip); + float4 ImageBasedReflections = float4(0, 0, 0, CompositeAlpha); + float2 CompositedAverageBrightness = float2(0.0f, 1.0f); + +#if REFLECTION_COMPOSITE_USE_BLENDED_REFLECTION_CAPTURES + // Accumulate reflections from captures affecting this tile, applying largest captures first so that the smallest ones display on top + LOOP + for (uint TileCaptureIndex = 0; TileCaptureIndex < NumCapturesAffectingTile; TileCaptureIndex++) + { + BRANCH + if (ImageBasedReflections.a < 0.001) + { + break; + } + + uint CaptureIndex = 0; +#ifdef REFLECTION_COMPOSITE_NO_CULLING_DATA + CaptureIndex = TileCaptureIndex; // Go from 0 to NumCapturesAffectingTile as absolute index in capture array +#else + #if (INSTANCED_STEREO || MOBILE_MULTI_VIEW) + BRANCH + if (EyeIndex == 0) + { + #endif + + CaptureIndex = GetCulledLightDataGrid(CaptureDataStartIndex + TileCaptureIndex); + + #if (INSTANCED_STEREO || MOBILE_MULTI_VIEW) + } + else + { + CaptureIndex = GetCulledLightDataGridISR(CaptureDataStartIndex + TileCaptureIndex); + } + #endif +#endif + + FLWCVector3 CaptureWorldPosition = MakeLWCVector3(GetReflectionTilePosition(CaptureIndex).xyz, GetReflectionPositionAndRadius(CaptureIndex).xyz); + float3 CaptureTranslatedWorldPosition = LWCToFloat(LWCAdd(CaptureWorldPosition, ResolvedView.PreViewTranslation)); + float CaptureRadius = GetReflectionPositionAndRadius(CaptureIndex).w; + + float4 CaptureProperties = GetReflectionCaptureProperties(CaptureIndex); + + float3 CaptureVector = TranslatedWorldPosition - CaptureTranslatedWorldPosition; + float CaptureVectorLength = sqrt(dot(CaptureVector, CaptureVector)); + float NormalizedDistanceToCapture = saturate(CaptureVectorLength / CaptureRadius); + + BRANCH + if (CaptureVectorLength < CaptureRadius) + { + float3 ProjectedCaptureVector = RayDirection; + float4 CaptureOffsetAndAverageBrightness = GetReflectionCaptureOffsetAndAverageBrightness(CaptureIndex); + + // Fade out based on distance to capture + float DistanceAlpha = 0; + + #define PROJECT_ONTO_SHAPE 1 + #if PROJECT_ONTO_SHAPE + #if REFLECTION_COMPOSITE_HAS_BOX_CAPTURES + #if REFLECTION_COMPOSITE_HAS_SPHERE_CAPTURES + // Box + BRANCH if (CaptureProperties.b > 0) + #endif + { + ProjectedCaptureVector = GetLookupVectorForBoxCapture(RayDirection, TranslatedWorldPosition, float4(CaptureTranslatedWorldPosition, CaptureRadius), + GetReflectionBoxTransform(CaptureIndex), GetReflectionBoxScales(CaptureIndex), CaptureOffsetAndAverageBrightness.xyz, DistanceAlpha); + } + #endif + + #if REFLECTION_COMPOSITE_HAS_SPHERE_CAPTURES + // Sphere + #if REFLECTION_COMPOSITE_HAS_BOX_CAPTURES + else + #endif + { + ProjectedCaptureVector = GetLookupVectorForSphereCapture(RayDirection, TranslatedWorldPosition, float4(CaptureTranslatedWorldPosition, CaptureRadius), NormalizedDistanceToCapture, CaptureOffsetAndAverageBrightness.xyz, DistanceAlpha); + } + #endif + #else + DistanceAlpha = 1.0; + #endif //PROJECT_ONTO_SHAPE + + float CaptureArrayIndex = CaptureProperties.g; + + { + float4 Sample = ReflectionStruct.ReflectionCubemap.SampleLevel(ReflectionStruct.ReflectionCubemapSampler, float4(ProjectedCaptureVector, CaptureArrayIndex), Mip); + + Sample.rgb *= CaptureProperties.r; + Sample *= DistanceAlpha; + + // Under operator (back to front) + ImageBasedReflections.rgb += Sample.rgb * ImageBasedReflections.a * IndirectSpecularOcclusion; + ImageBasedReflections.a *= 1 - Sample.a; + + float AverageBrightness = CaptureOffsetAndAverageBrightness.w; + CompositedAverageBrightness.x += AverageBrightness * DistanceAlpha * CompositedAverageBrightness.y; + CompositedAverageBrightness.y *= 1 - DistanceAlpha; + } + } + } + +#else + + float3 ProjectedCaptureVector = RayDirection; + + FLWCVector3 SingleCaptureWorldPosition = MakeLWCVector3(GetReflectionTilePosition(SingleCaptureIndex).xyz, GetReflectionPositionAndRadius(SingleCaptureIndex).xyz); + float3 SingleCaptureTranslatedWorldPosition = LWCToFloat(LWCAdd(SingleCaptureWorldPosition, ResolvedView.PreViewTranslation)); + float SingleCaptureRadius = GetReflectionPositionAndRadius(SingleCaptureIndex).w; + + float4 SingleCaptureOffsetAndAverageBrightness = GetReflectionCaptureOffsetAndAverageBrightness(SingleCaptureIndex); + float SingleCaptureBrightness = GetReflectionCaptureProperties(SingleCaptureIndex).x; + float SingleCaptureArrayIndex = GetReflectionCaptureProperties(SingleCaptureIndex).y; + + #define APPROXIMATE_CONTINUOUS_SINGLE_CAPTURE_PARALLAX 0 + #if APPROXIMATE_CONTINUOUS_SINGLE_CAPTURE_PARALLAX + float3 CaptureVector = TranslatedWorldPosition - SingleCaptureTranslatedWorldPosition; + float CaptureVectorLength = sqrt(dot(CaptureVector, CaptureVector)); + float NormalizedDistanceToCapture = saturate(CaptureVectorLength / SingleCaptureRadius); + + float UnusedDistanceAlpha = 0; + ProjectedCaptureVector = GetLookupVectorForSphereCapture(RayDirection, TranslatedWorldPosition, float4(SingleCaptureTranslatedWorldPosition, SingleCaptureRadius), NormalizedDistanceToCapture, SingleCaptureOffsetAndAverageBrightness.xyz, UnusedDistanceAlpha); + + float x = saturate(NormalizedDistanceToCapture); + float DistanceAlpha = 1 - x * x * (3 - 2 * x); + // Lerp between sphere parallax corrected and infinite based on distance to shape + ProjectedCaptureVector = lerp(RayDirection, normalize(ProjectedCaptureVector), DistanceAlpha); + #endif + + float4 Sample = TextureCubeArraySampleLevel(ReflectionStruct.ReflectionCubemap, ReflectionStruct.ReflectionCubemapSampler, ProjectedCaptureVector, SingleCaptureArrayIndex, Mip); + + Sample.rgb *= SingleCaptureBrightness; + ImageBasedReflections = float4(Sample.rgb, 1 - Sample.a); + + float AverageBrightness = SingleCaptureOffsetAndAverageBrightness.w; + CompositedAverageBrightness.x += AverageBrightness * CompositedAverageBrightness.y; + CompositedAverageBrightness.y = 0; +#endif + + // Apply indirect lighting scale while we have only accumulated reflection captures + ImageBasedReflections.rgb *= View.PrecomputedIndirectSpecularColorScale; + CompositedAverageBrightness.x *= Luminance( View.PrecomputedIndirectSpecularColorScale ); + +#if ENABLE_SKY_LIGHT + + BRANCH + if (ReflectionStruct.SkyLightParameters.y > 0 && bCompositeSkylight) + { + float SkyAverageBrightness = 1.0f; + + #if REFLECTION_COMPOSITE_SUPPORT_SKYLIGHT_BLEND + float3 SkyLighting = GetSkyLightReflectionSupportingBlend(RayDirection, Roughness, SkyAverageBrightness); + #else + float3 SkyLighting = GetSkyLightReflection(RayDirection, Roughness, SkyAverageBrightness); + #endif + + // Normalize for static skylight types which mix with lightmaps, material ambient occlusion as well as diffuse/specular occlusion. + bool bNormalize = ReflectionStruct.SkyLightParameters.z < 1 && ALLOW_STATIC_LIGHTING; + + FLATTEN + if (bNormalize) + { + ImageBasedReflections.rgb += ImageBasedReflections.a * SkyLighting * IndirectSpecularOcclusion; + CompositedAverageBrightness.x += SkyAverageBrightness * CompositedAverageBrightness.y; + } + else + { + ExtraIndirectSpecular += SkyLighting * IndirectSpecularOcclusion; + } + } +#endif + +#if ALLOW_STATIC_LIGHTING + ImageBasedReflections.rgb *= ComputeMixingWeight(IndirectIrradiance, CompositedAverageBrightness.x, Roughness); +#endif + + ImageBasedReflections.rgb += ImageBasedReflections.a * ExtraIndirectSpecular; + + return ImageBasedReflections.rgb; +} +``` + + ## DiffuseIndirectComposite 位于IndirectLightRendering.cpp的`RenderDiffuseIndirectAndAmbientOcclusion()` \ No newline at end of file