diff --git a/03-UnrealEngine/卡通渲染相关资料/渲染功能/ToonReflection&GI控制/ToonReflection.md b/03-UnrealEngine/卡通渲染相关资料/渲染功能/ToonReflection&GI控制/ToonReflection.md index 9b84cf9..06f95fd 100644 --- a/03-UnrealEngine/卡通渲染相关资料/渲染功能/ToonReflection&GI控制/ToonReflection.md +++ b/03-UnrealEngine/卡通渲染相关资料/渲染功能/ToonReflection&GI控制/ToonReflection.md @@ -548,6 +548,287 @@ float3 CompositeReflectionCapturesAndSkylightTWS( 8. 应用GI到渲染结果上。 9. ApplyAmbientCubemapComposite() -DiffuseIndirectComposite +FDiffuseIndirectCompositePS位于/Engine/Private/DiffuseIndirectComposite.usf的MainPS() -FDiffuseIndirectCompositePS, "/Engine/Private/DiffuseIndirectComposite.usf", "MainPS", SF_Pixel); \ No newline at end of file +### FDiffuseIndirectCompositePS +```c++ +void MainPS( + float4 SvPosition : SV_POSITION +#if DIM_APPLY_DIFFUSE_INDIRECT +#if ENABLE_DUAL_SRC_BLENDING + , out float4 OutAddColor DUAL_SOURCE_BLENDING_SLOT(0) : SV_Target0 + , out float4 OutMultiplyColor DUAL_SOURCE_BLENDING_SLOT(1) : SV_Target1 +#else + , out float4 OutColor : SV_Target0 +#endif +#else + , out float4 OutMultiplyColor : SV_Target0 +#endif +) +{ + const uint2 PixelPos = SvPosition.xy; + const float2 SceneBufferUV = SvPositionToBufferUV(SvPosition); + const float2 ScreenPosition = SvPositionToScreenPosition(SvPosition).xy; + + #if !ENABLE_DUAL_SRC_BLENDING && DIM_APPLY_DIFFUSE_INDIRECT + float4 OutAddColor = float4(0.0, 0.0, 0.0, 0.0); + float4 OutMultiplyColor; + + const float4 SceneColor = SceneColorTexture.SampleLevel(SceneColorSampler, SceneBufferUV, 0); + #endif + + // Sample scene textures. + const FLumenMaterialData Material = ReadMaterialData(PixelPos, SceneBufferUV); + + // Sample the ambient occlusion that is dynamically generated every frame. + const float DynamicAmbientOcclusion = AmbientOcclusionTexture.SampleLevel(AmbientOcclusionSampler, SceneBufferUV, 0).r; + + // Compute the final ambient occlusion to be applied. Lumen handles material AO internally. + float FinalAmbientOcclusion = 1.0f; + #if DIM_APPLY_DIFFUSE_INDIRECT != DIM_APPLY_DIFFUSE_INDIRECT_SCREEN_PROBE_GATHER + { + float AOMask = IsValid(Material); + FinalAmbientOcclusion = lerp(1.0f, Material.MaterialAO * DynamicAmbientOcclusion, AOMask * AmbientOcclusionStaticFraction); + } + #endif + + const float3 TranslatedWorldPosition = mul(float4(GetScreenPositionForProjectionType(ScreenPosition, Material.SceneDepth), Material.SceneDepth, 1), View.ScreenToTranslatedWorld).xyz; + + const float3 N = Material.WorldNormal; + const float3 V = normalize(View.TranslatedWorldCameraOrigin - TranslatedWorldPosition); + const float NoV = saturate(dot(N, V)); + + // Apply diffuse indirect. + //这里的DIM可能是Diffuse Indirect Map的缩写 + #if DIM_APPLY_DIFFUSE_INDIRECT + OutAddColor = 0; + { + FDirectLighting IndirectLighting = (FDirectLighting)0; + + if (IsValid(Material)) + { + float3 DiffuseIndirectLighting = 0; + float3 RoughSpecularIndirectLighting = 0; + float4 SpecularIndirectLighting = 0; + + //直接从屏幕空间探针中获取数据(Lumen) + #if DIM_APPLY_DIFFUSE_INDIRECT == DIM_APPLY_DIFFUSE_INDIRECT_SCREEN_PROBE_GATHER + DiffuseIndirectLighting = DiffuseIndirect_Textures_0.SampleLevel(GlobalPointClampedSampler, SceneBufferUV, 0).rgb; + RoughSpecularIndirectLighting = DiffuseIndirect_Textures_2.SampleLevel(GlobalPointClampedSampler, SceneBufferUV, 0).rgb; + SpecularIndirectLighting = DiffuseIndirect_Textures_3.SampleLevel(GlobalPointClampedSampler, SceneBufferUV, 0).rgba; + #else + { + //设置降噪器参数 + // Sample the output of the denoiser. + FSSDKernelConfig KernelConfig = CreateKernelConfig(); + + #if DEBUG_OUTPUT + { + KernelConfig.DebugPixelPosition = uint2(SvPosition.xy); + KernelConfig.DebugEventCounter = 0; + } + #endif + + // Compile time. + KernelConfig.bSampleKernelCenter = true; + KernelConfig.BufferLayout = CONFIG_SIGNAL_INPUT_LAYOUT; + KernelConfig.bUnroll = true; + + #if DIM_UPSCALE_DIFFUSE_INDIRECT + { + KernelConfig.SampleSet = SAMPLE_SET_2X2_BILINEAR; + KernelConfig.BilateralDistanceComputation = SIGNAL_WORLD_FREQUENCY_REF_METADATA_ONLY; + KernelConfig.WorldBluringDistanceMultiplier = 16.0; + + KernelConfig.BilateralSettings[0] = BILATERAL_POSITION_BASED(3); + + // SGPRs + KernelConfig.BufferSizeAndInvSize = View.BufferSizeAndInvSize * float4(0.5, 0.5, 2.0, 2.0); + KernelConfig.BufferBilinearUVMinMax = View.BufferBilinearUVMinMax; + } + #else + { + KernelConfig.SampleSet = SAMPLE_SET_1X1; + KernelConfig.bNormalizeSample = true; + + // SGPRs + KernelConfig.BufferSizeAndInvSize = View.BufferSizeAndInvSize; + KernelConfig.BufferBilinearUVMinMax = View.BufferBilinearUVMinMax; + } + #endif + + // VGPRs + KernelConfig.BufferUV = SceneBufferUV; + { + // STRATA_TODO: We use the top layer data, but we should resolve lighting for each BSDFs. + KernelConfig.CompressedRefSceneMetadata = MaterialToCompressedSceneMetadata(Material.SceneDepth, Material.WorldNormal, Material.Roughness, Material.ShadingID); + KernelConfig.RefBufferUV = SceneBufferUV; + KernelConfig.RefSceneMetadataLayout = METADATA_BUFFER_LAYOUT_DISABLED; + } + KernelConfig.HammersleySeed = Rand3DPCG16(int3(SvPosition.xy, View.StateFrameIndexMod8)).xy; + + FSSDSignalAccumulatorArray UncompressedAccumulators = CreateSignalAccumulatorArray(); + FSSDCompressedSignalAccumulatorArray CompressedAccumulators = CompressAccumulatorArray( + UncompressedAccumulators, CONFIG_ACCUMULATOR_VGPR_COMPRESSION); + + AccumulateKernel( + KernelConfig, + DiffuseIndirect_Textures_0, + DiffuseIndirect_Textures_1, + DiffuseIndirect_Textures_2, + DiffuseIndirect_Textures_3, + /* inout */ UncompressedAccumulators, + /* inout */ CompressedAccumulators); + + //PassDebugOutput[uint2(SvPosition.xy)] = float4(UncompressedAccumulators.Array[0].Moment1.SampleCount, 0, 0, 0); + + FSSDSignalSample Sample; + #if DIM_UPSCALE_DIFFUSE_INDIRECT + Sample = NormalizeToOneSample(UncompressedAccumulators.Array[0].Moment1); + #else + Sample = UncompressedAccumulators.Array[0].Moment1; + #endif + + //SSGI、RTGI直接将降噪(上采样)结果赋予DiffuseIndirectLighting + #if DIM_APPLY_DIFFUSE_INDIRECT == DIM_APPLY_DIFFUSE_INDIRECT_SSGI || DIM_APPLY_DIFFUSE_INDIRECT == DIM_APPLY_DIFFUSE_INDIRECT_RTGI + { + DiffuseIndirectLighting = Sample.SceneColor.rgb; + } + #else + #error Unimplemented + #endif + } + #endif + + #if STRATA_ENABLED + { + FStrataAddressing StrataAddressing = GetStrataPixelDataByteOffset(PixelPos, uint2(View.BufferSizeAndInvSize.xy), Strata.MaxBytesPerPixel); + FStrataPixelHeader StrataPixelHeader = UnpackStrataHeaderIn(Strata.MaterialTextureArray, StrataAddressing, Strata.TopLayerTexture); + if (StrataPixelHeader.GetMaterialMode() > HEADER_MATERIALMODE_NONE) + { + const FStrataDeferredLighting IndirectLighting_Strata = StrataIndirectLighting( + PixelPos, + Strata.MaterialTextureArray, + StrataAddressing, + StrataPixelHeader, + V, + DynamicAmbientOcclusion, + DiffuseIndirectLighting, + SpecularIndirectLighting); + + OutAddColor = IndirectLighting_Strata.SceneColor; + #if STRATA_OPAQUE_ROUGH_REFRACTION_ENABLED + const uint2 OutCoord = PixelPos; + OutOpaqueRoughRefractionSceneColor[OutCoord] = IndirectLighting_Strata.OpaqueRoughRefractionSceneColor; + OutSubSurfaceSceneColor[OutCoord] = IndirectLighting_Strata.SubSurfaceSceneColor; + #endif + } + } + #else // STRATA_ENABLED + { + FGBufferData GBuffer = Material.GBufferData; + + float3 DiffuseColor = bVisualizeDiffuseIndirect ? float3(.18f, .18f, .18f) : GBuffer.DiffuseColor; + float3 SpecularColor = GBuffer.SpecularColor; + + #if DIM_APPLY_DIFFUSE_INDIRECT == DIM_APPLY_DIFFUSE_INDIRECT_SCREEN_PROBE_GATHER + RemapClearCoatDiffuseAndSpecularColor(GBuffer, NoV, DiffuseColor, SpecularColor); + #endif + + //取得AO + FShadingOcclusion Occlusion = GetShadingOcclusion(PixelPos, V, N, GBuffer.Roughness, GBuffer.BaseColor, DynamicAmbientOcclusion); + + //对双面植被与次表面进行DiffuseOcclusion适配 + if (GBuffer.ShadingModelID == SHADINGMODELID_TWOSIDED_FOLIAGE || GBuffer.ShadingModelID == SHADINGMODELID_SUBSURFACE) + { + Occlusion.DiffuseOcclusion = lerp(1, Occlusion.DiffuseOcclusion, LumenFoliageOcclusionStrength); + } + + //Hair需要单独处理 + if (GBuffer.ShadingModelID == SHADINGMODELID_HAIR) + { + float3 L = 0; + const float3 IndirectDiffuseColor = EvaluateEnvHair(GBuffer, V, N, L /*out*/); + IndirectLighting.Diffuse = DiffuseIndirectLighting * Occlusion.DiffuseOcclusion * IndirectDiffuseColor; + IndirectLighting.Specular = 0; + } + else + { + float3 BackfaceDiffuseIndirectLighting = 0; + + //双面植被,计算BackfaceDiffuseIndirectLighting。如果不支持BackfaceDiffuse则将预积分结果加到DiffuseColor中。 + if (GBuffer.ShadingModelID == SHADINGMODELID_TWOSIDED_FOLIAGE) + { + float3 SubsurfaceColor = ExtractSubsurfaceColor(GBuffer); + + if (bLumenSupportBackfaceDiffuse > 0) + { + BackfaceDiffuseIndirectLighting += SubsurfaceColor * DiffuseIndirect_Textures_1.SampleLevel(GlobalPointClampedSampler, SceneBufferUV, 0).rgb; + } + else + { + // Adding Subsurface energy to the diffuse lobe is a poor approximation when DiffuseColor is small and SubsurfaceColor is large + // Reduce the error by attenuating SubsurfaceColor, even though diffuse already has the 1/PI for Lambert. + const float PreintegratedTwoSidedBxDF = 1.0f / PI; + DiffuseColor += SubsurfaceColor * PreintegratedTwoSidedBxDF; + } + } + + //次表面、预积分皮肤,直接将次表面颜色加到Diffsue上。 + if (GBuffer.ShadingModelID == SHADINGMODELID_SUBSURFACE || GBuffer.ShadingModelID == SHADINGMODELID_PREINTEGRATED_SKIN) + { + float3 SubsurfaceColor = ExtractSubsurfaceColor(GBuffer); + // Add subsurface energy to diffuse + DiffuseColor += SubsurfaceColor; + } + + //布料计算 + if (GBuffer.ShadingModelID == SHADINGMODELID_CLOTH) + { + float3 ClothFuzz = ExtractSubsurfaceColor(GBuffer); + DiffuseColor += ClothFuzz * GBuffer.CustomData.a; + } + + //最终GI结果计算 + IndirectLighting.Diffuse = (DiffuseIndirectLighting * DiffuseColor + BackfaceDiffuseIndirectLighting) * Occlusion.DiffuseOcclusion; + IndirectLighting.Transmission = 0; + + #if DIM_APPLY_DIFFUSE_INDIRECT == DIM_APPLY_DIFFUSE_INDIRECT_SCREEN_PROBE_GATHER + //Lumen计算的反射 + RoughSpecularIndirectLighting *= Occlusion.SpecularOcclusion; + IndirectLighting.Specular = CombineRoughSpecular(GBuffer, HasBackfaceDiffuse(Material), NoV, SpecularIndirectLighting, RoughSpecularIndirectLighting, SpecularColor); + #else + //SSGI、RTGI等其他GI方法的反射结果 + IndirectLighting.Specular = AddContrastAndSpecularScale(SpecularIndirectLighting.xyz) * EnvBRDF(SpecularColor, GBuffer.Roughness, NoV); + #endif + } + } + #endif // STRATA_ENABLED + } + + // Accumulate lighting into the final buffers + #if !STRATA_ENABLED + IndirectLighting.Specular *= GetSSSCheckerboadSpecularScale(PixelPos, Material.bNeedsSeparateLightAccumulation); + FLightAccumulator LightAccumulator = (FLightAccumulator)0; + LightAccumulator_Add( + LightAccumulator, + IndirectLighting.Diffuse + IndirectLighting.Specular, + IndirectLighting.Diffuse, + 1.0f, + Material.bNeedsSeparateLightAccumulation); + OutAddColor = LightAccumulator_GetResult(LightAccumulator); + #endif // !STRATA_ENABLED + + } + #endif + + OutMultiplyColor = FinalAmbientOcclusion; + + #if !ENABLE_DUAL_SRC_BLENDING && DIM_APPLY_DIFFUSE_INDIRECT + OutColor = SceneColor * OutMultiplyColor + OutAddColor; + #endif +} +``` + +PS. +1. 采样自DiffuseIndirect_Textures_2的RoughSpecularIndirectLighting只会用在Lumen的计算中。 \ No newline at end of file