UE4 SkyLight 使用

  1. D:\UnrealEngine426\Engine\Source\Runtime\Renderer\Private\DeferredShadingRenderer.cpp
    1.  FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList) 中 RenderDeferredReflectionsAndSkyLighting();
  2. D:\UnrealEngine426\Engine\Source\Runtime\Renderer\Private\IndirectLightRendering.cpp
    1. void FDeferredShadingSceneRenderer::RenderDeferredReflectionsAndSkyLighting(
      	FRDGBuilder& GraphBuilder,
      	TRDGUniformBufferRef<FSceneTextureUniformParameters> SceneTexturesUniformBuffer,
      	FRDGTextureMSAA SceneColorTexture,
      	FRDGTextureRef DynamicBentNormalAOTexture,
      	FRDGTextureRef VelocityTexture,
      	FHairStrandsRenderingData* HairDatas)
      {
      	if (ViewFamily.EngineShowFlags.VisualizeLightCulling 
      		|| ViewFamily.EngineShowFlags.RayTracingDebug
      		|| ViewFamily.EngineShowFlags.PathTracing
      		|| !ViewFamily.EngineShowFlags.Lighting)
      	{
      		return;
      	}
      
      	// If we're currently capturing a reflection capture, output SpecularColor * IndirectIrradiance for metals so they are not black in reflections,
      	// Since we don't have multiple bounce specular reflections
      	bool bReflectionCapture = false;
      	for (int32 ViewIndex = 0, Num = Views.Num(); ViewIndex < Num; ViewIndex++)
      	{
      		const FViewInfo& View = Views[ViewIndex];
      		bReflectionCapture = bReflectionCapture || View.bIsReflectionCapture;
      	}
      
      	if (bReflectionCapture)
      	{
      		// if we are rendering a reflection capture then we can skip this pass entirely (no reflection and no sky contribution evaluated in this pass)
      		return;
      	}
      
      	// The specular sky light contribution is also needed by RT Reflections as a fallback.
      	const bool bSkyLight = Scene->SkyLight
      		&& (Scene->SkyLight->ProcessedTexture || Scene->SkyLight->bRealTimeCaptureEnabled)
      		&& !Scene->SkyLight->bHasStaticLighting;
      
      	bool bDynamicSkyLight = ShouldRenderDeferredDynamicSkyLight(Scene, ViewFamily);
      	bool bApplySkyShadowing = false;
      	if (bDynamicSkyLight)
      	{
      		RDG_EVENT_SCOPE(GraphBuilder, "SkyLightDiffuse");
      		RDG_GPU_STAT_SCOPE(GraphBuilder, SkyLightDiffuse);
      
      		extern int32 GDistanceFieldAOApplyToStaticIndirect;
      		if (Scene->SkyLight->bCastShadows
      			&& !GDistanceFieldAOApplyToStaticIndirect
      			&& ShouldRenderDistanceFieldAO()
      			&& ShouldRenderDistanceFieldLighting()
      			&& ViewFamily.EngineShowFlags.AmbientOcclusion)
      		{
      			bApplySkyShadowing = true;
      			FDistanceFieldAOParameters Parameters(Scene->SkyLight->OcclusionMaxDistance, Scene->SkyLight->Contrast);
      			RenderDistanceFieldLighting(GraphBuilder, SceneTexturesUniformBuffer, Parameters, SceneColorTexture.Target, VelocityTexture, DynamicBentNormalAOTexture, false, false);
      		}
      	}
      
      	FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(GraphBuilder.RHICmdList);
      
      	const bool bReflectionEnv = ShouldDoReflectionEnvironment();
      
      	FRDGTextureRef AmbientOcclusionTexture = GraphBuilder.RegisterExternalTexture(SceneContext.bScreenSpaceAOIsValid ? SceneContext.ScreenSpaceAO : GSystemTextures.WhiteDummy);
      	float DynamicBentNormalAO = 1.0f;
      
      	if (!DynamicBentNormalAOTexture)
      	{
      		DynamicBentNormalAOTexture = GraphBuilder.RegisterExternalTexture(GSystemTextures.WhiteDummy);
      		DynamicBentNormalAO = 0.0f;
      	}
      
      	FSceneTextureParameters SceneTextures = GetSceneTextureParameters(GraphBuilder);
      
      	uint32 ViewIndex = 0;
      	for (FViewInfo& View : Views)
      	{
      		const uint32 CurrentViewIndex = ViewIndex++;
      
      		const FRayTracingReflectionOptions RayTracingReflectionOptions = GetRayTracingReflectionOptions(View, *Scene);
      
      		const bool bScreenSpaceReflections = !RayTracingReflectionOptions.bEnabled && ShouldRenderScreenSpaceReflections(View);
      		const bool bComposePlanarReflections = !RayTracingReflectionOptions.bEnabled && HasDeferredPlanarReflections(View);
      
      		FRDGTextureRef ReflectionsColor = nullptr;
      		if (RayTracingReflectionOptions.bEnabled || bScreenSpaceReflections)
      		{
      			int32 DenoiserMode = GetReflectionsDenoiserMode();
      
      			bool bDenoise = false;
      			bool bTemporalFilter = false;
      
      			// Traces the reflections, either using screen space reflection, or ray tracing.
      			IScreenSpaceDenoiser::FReflectionsInputs DenoiserInputs;
      			IScreenSpaceDenoiser::FReflectionsRayTracingConfig DenoiserConfig;
      			if (RayTracingReflectionOptions.bEnabled)
      			{
      				RDG_EVENT_SCOPE(GraphBuilder, "RayTracingReflections");
      				RDG_GPU_STAT_SCOPE(GraphBuilder, RayTracingReflections);
      
      				bDenoise = DenoiserMode != 0;
      
      				DenoiserConfig.ResolutionFraction = RayTracingReflectionOptions.ResolutionFraction;
      				DenoiserConfig.RayCountPerPixel = RayTracingReflectionOptions.SamplesPerPixel;
      
      				check(RayTracingReflectionOptions.bReflectOnlyWater == false);
      
      				RenderRayTracingReflections(
      					GraphBuilder,
      					SceneTextures,
      					View,
      					DenoiserMode,
      					RayTracingReflectionOptions,
      					&DenoiserInputs);
      			}
      			else if (bScreenSpaceReflections)
      			{
      				bDenoise = DenoiserMode != 0 && CVarDenoiseSSR.GetValueOnRenderThread();
      				bTemporalFilter = !bDenoise && View.ViewState && IsSSRTemporalPassRequired(View);
      
      				ESSRQuality SSRQuality;
      				GetSSRQualityForView(View, &SSRQuality, &DenoiserConfig);
      
      				RDG_EVENT_SCOPE(GraphBuilder, "ScreenSpaceReflections(Quality=%d)", int32(SSRQuality));
      
      				RenderScreenSpaceReflections(
      					GraphBuilder, SceneTextures, SceneColorTexture.Resolve, View, SSRQuality, bDenoise, &DenoiserInputs);
      			}
      			else
      			{
      				check(0);
      			}
      
      			if (bDenoise)
      			{
      				const IScreenSpaceDenoiser* DefaultDenoiser = IScreenSpaceDenoiser::GetDefaultDenoiser();
      				const IScreenSpaceDenoiser* DenoiserToUse = DenoiserMode == 1 ? DefaultDenoiser : GScreenSpaceDenoiser;
      
      				// Standard event scope for denoiser to have all profiling information not matter what, and with explicit detection of third party.
      				RDG_EVENT_SCOPE(GraphBuilder, "%s%s(Reflections) %dx%d",
      					DenoiserToUse != DefaultDenoiser ? TEXT("ThirdParty ") : TEXT(""),
      					DenoiserToUse->GetDebugName(),
      					View.ViewRect.Width(), View.ViewRect.Height());
      
      				IScreenSpaceDenoiser::FReflectionsOutputs DenoiserOutputs = DenoiserToUse->DenoiseReflections(
      					GraphBuilder,
      					View,
      					&View.PrevViewInfo,
      					SceneTextures,
      					DenoiserInputs,
      					DenoiserConfig);
      
      				ReflectionsColor = DenoiserOutputs.Color;
      			}
      			else if (bTemporalFilter)
      			{
      				check(View.ViewState);
      				FTAAPassParameters TAASettings(View);
      				TAASettings.Pass = ETAAPassConfig::ScreenSpaceReflections;
      				TAASettings.SceneDepthTexture = SceneTextures.SceneDepthTexture;
      				TAASettings.SceneVelocityTexture = SceneTextures.GBufferVelocityTexture;
      				TAASettings.SceneColorInput = DenoiserInputs.Color;
      				TAASettings.bOutputRenderTargetable = bComposePlanarReflections;
      
      				FTAAOutputs TAAOutputs = AddTemporalAAPass(
      					GraphBuilder,
      					View,
      					TAASettings,
      					View.PrevViewInfo.SSRHistory,
      					&View.ViewState->PrevFrameViewInfo.SSRHistory);
      
      				ReflectionsColor = TAAOutputs.SceneColor;
      			}
      			else
      			{
      				if (RayTracingReflectionOptions.bEnabled && DenoiserInputs.RayHitDistance)
      				{
      					// The performance of ray tracing does not allow to run without a denoiser in real time.
      					// Multiple rays per pixel is unsupported by the denoiser that will most likely more bound by to
      					// many rays than exporting the hit distance buffer. Therefore no permutation of the ray generation
      					// shader has been judged required to be supported.
      					GraphBuilder.RemoveUnusedTextureWarning(DenoiserInputs.RayHitDistance);
      				}
      
      				ReflectionsColor = DenoiserInputs.Color;
      			}
      		} // if (RayTracingReflectionOptions.bEnabled || bScreenSpaceReflections)
      
      		if (bComposePlanarReflections)
      		{
      			check(!RayTracingReflectionOptions.bEnabled);
      			RenderDeferredPlanarReflections(GraphBuilder, SceneTextures, View, /* inout */ ReflectionsColor);
      		}
      
      		bool bRequiresApply = ReflectionsColor != nullptr || bSkyLight || bDynamicSkyLight || bReflectionEnv;
      
      		if (bRequiresApply)
      		{
      			RDG_GPU_STAT_SCOPE(GraphBuilder, ReflectionEnvironment);
      
      			// Render the reflection environment with tiled deferred culling
      			bool bHasBoxCaptures = (View.NumBoxReflectionCaptures > 0);
      			bool bHasSphereCaptures = (View.NumSphereReflectionCaptures > 0);
      
      			FReflectionEnvironmentSkyLightingPS::FParameters* PassParameters = GraphBuilder.AllocParameters<FReflectionEnvironmentSkyLightingPS::FParameters>();
      
      			// Setup the parameters of the shader.
      			{
      				// Setups all shader parameters related to skylight.
      				{
      					FSkyLightSceneProxy* SkyLight = Scene->SkyLight;
      
      					float SkyLightContrast = 0.01f;
      					float SkyLightOcclusionExponent = 1.0f;
      					FVector4 SkyLightOcclusionTintAndMinOcclusion(0.0f, 0.0f, 0.0f, 0.0f);
      					EOcclusionCombineMode SkyLightOcclusionCombineMode = EOcclusionCombineMode::OCM_MAX;
      					if (SkyLight)
      					{
      						FDistanceFieldAOParameters Parameters(SkyLight->OcclusionMaxDistance, SkyLight->Contrast);
      						SkyLightContrast = Parameters.Contrast;
      						SkyLightOcclusionExponent = SkyLight->OcclusionExponent;
      						SkyLightOcclusionTintAndMinOcclusion = FVector4(SkyLight->OcclusionTint);
      						SkyLightOcclusionTintAndMinOcclusion.W = SkyLight->MinOcclusion;
      						SkyLightOcclusionCombineMode = SkyLight->OcclusionCombineMode;
      					}
      
      					// Scale and bias to remap the contrast curve to [0,1]
      					const float Min = 1 / (1 + FMath::Exp(-SkyLightContrast * (0 * 10 - 5)));
      					const float Max = 1 / (1 + FMath::Exp(-SkyLightContrast * (1 * 10 - 5)));
      					const float Mul = 1.0f / (Max - Min);
      					const float Add = -Min / (Max - Min);
      
      					PassParameters->OcclusionTintAndMinOcclusion = SkyLightOcclusionTintAndMinOcclusion;
      					PassParameters->ContrastAndNormalizeMulAdd = FVector(SkyLightContrast, Mul, Add);
      					PassParameters->OcclusionExponent = SkyLightOcclusionExponent;
      					PassParameters->OcclusionCombineMode = SkyLightOcclusionCombineMode == OCM_Minimum ? 0.0f : 1.0f;
      					PassParameters->ApplyBentNormalAO = DynamicBentNormalAO;
      					PassParameters->InvSkySpecularOcclusionStrength = 1.0f / FMath::Max(CVarSkySpecularOcclusionStrength.GetValueOnRenderThread(), 0.1f);
      				}
      
      				// Setups all shader parameters related to distance field AO
      				{
      					FIntPoint AOBufferSize = GetBufferSizeForAO();
      					PassParameters->AOBufferBilinearUVMax = FVector2D(
      						(View.ViewRect.Width() / GAODownsampleFactor - 0.51f) / AOBufferSize.X, // 0.51 - so bilateral gather4 won't sample invalid texels
      						(View.ViewRect.Height() / GAODownsampleFactor - 0.51f) / AOBufferSize.Y);
      
      					extern float GAOViewFadeDistanceScale;
      					PassParameters->AOMaxViewDistance = GetMaxAOViewDistance();
      					PassParameters->DistanceFadeScale = 1.0f / ((1.0f - GAOViewFadeDistanceScale) * GetMaxAOViewDistance());
      
      					PassParameters->BentNormalAOTexture = DynamicBentNormalAOTexture;
      					PassParameters->BentNormalAOSampler = TStaticSamplerState<SF_Bilinear>::GetRHI();
      				}
      
      				PassParameters->AmbientOcclusionTexture = AmbientOcclusionTexture;
      				PassParameters->AmbientOcclusionSampler = TStaticSamplerState<SF_Point>::GetRHI();
      
      				PassParameters->ScreenSpaceReflectionsTexture = ReflectionsColor ? ReflectionsColor : GraphBuilder.RegisterExternalTexture(GSystemTextures.BlackDummy);
      				PassParameters->ScreenSpaceReflectionsSampler = TStaticSamplerState<SF_Point>::GetRHI();
      
      				if (Scene->HasVolumetricCloud())
      				{
      					FVolumetricCloudRenderSceneInfo* CloudInfo = Scene->GetVolumetricCloudSceneInfo();
      
      					PassParameters->CloudSkyAOTexture = GraphBuilder.RegisterExternalTexture(View.VolumetricCloudSkyAO.IsValid() ? View.VolumetricCloudSkyAO : GSystemTextures.BlackDummy);
      					PassParameters->CloudSkyAOWorldToLightClipMatrix = CloudInfo->GetVolumetricCloudCommonShaderParameters().CloudSkyAOWorldToLightClipMatrix;
      					PassParameters->CloudSkyAOFarDepthKm = CloudInfo->GetVolumetricCloudCommonShaderParameters().CloudSkyAOFarDepthKm;
      					PassParameters->CloudSkyAOEnabled = 1;
      				}
      				else
      				{
      					PassParameters->CloudSkyAOTexture = GraphBuilder.RegisterExternalTexture(GSystemTextures.BlackDummy);
      					PassParameters->CloudSkyAOEnabled = 0;
      				}
      				PassParameters->CloudSkyAOSampler = TStaticSamplerState<SF_Bilinear>::GetRHI();
      
      				PassParameters->PreIntegratedGF = GSystemTextures.PreintegratedGF->GetRenderTargetItem().ShaderResourceTexture;
      				PassParameters->PreIntegratedGFSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
      
      				PassParameters->SceneTextures = SceneTextures;
      
      				PassParameters->ViewUniformBuffer = View.ViewUniformBuffer;
      				PassParameters->ReflectionCaptureData = View.ReflectionCaptureUniformBuffer;
      				{
      					FReflectionUniformParameters ReflectionUniformParameters;
      					SetupReflectionUniformParameters(View, ReflectionUniformParameters);
      					PassParameters->ReflectionsParameters = CreateUniformBufferImmediate(ReflectionUniformParameters, UniformBuffer_SingleDraw);
      				}
      				PassParameters->ForwardLightData = View.ForwardLightingResources->ForwardLightDataUniformBuffer;
      			}
      
      			PassParameters->RenderTargets[0] = FRenderTargetBinding(SceneColorTexture.Target, ERenderTargetLoadAction::ELoad);
      
      			// Bind hair data
      			const bool bCheckerboardSubsurfaceRendering = IsSubsurfaceCheckerboardFormat(SceneColorTexture.Target->Desc.Format);
      
      			// ScreenSpace and SortedDeferred ray traced reflections use the same reflection environment shader,
      			// but main RT reflection shader requires a custom path as it evaluates the clear coat BRDF differently.
      			const bool bRequiresSpecializedReflectionEnvironmentShader = RayTracingReflectionOptions.bEnabled
      				&& RayTracingReflectionOptions.Algorithm != FRayTracingReflectionOptions::EAlgorithm::SortedDeferred;
      
      			auto PermutationVector = FReflectionEnvironmentSkyLightingPS::BuildPermutationVector(
      				View, bHasBoxCaptures, bHasSphereCaptures, DynamicBentNormalAO != 0.0f,
      				bSkyLight, bDynamicSkyLight, bApplySkyShadowing,
      				bRequiresSpecializedReflectionEnvironmentShader);
      
      			TShaderMapRef<FReflectionEnvironmentSkyLightingPS> PixelShader(View.ShaderMap, PermutationVector);
      			ClearUnusedGraphResources(PixelShader, PassParameters);
      
      			GraphBuilder.AddPass(
      				RDG_EVENT_NAME("ReflectionEnvironmentAndSky %dx%d", View.ViewRect.Width(), View.ViewRect.Height()),
      				PassParameters,
      				ERDGPassFlags::Raster,
      				[PassParameters, &View, PixelShader, bCheckerboardSubsurfaceRendering](FRHICommandList& InRHICmdList)
      			{
      				InRHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f);
      
      				FGraphicsPipelineStateInitializer GraphicsPSOInit;
      				FPixelShaderUtils::InitFullscreenPipelineState(InRHICmdList, View.ShaderMap, PixelShader, GraphicsPSOInit);
      
      				extern int32 GAOOverwriteSceneColor;
      				if (GetReflectionEnvironmentCVar() == 2 || GAOOverwriteSceneColor)
      				{
      					// override scene color for debugging
      					GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
      				}
      				else
      				{
      					if (bCheckerboardSubsurfaceRendering)
      					{
      						GraphicsPSOInit.BlendState = TStaticBlendState<CW_RGB, BO_Add, BF_One, BF_One>::GetRHI();
      					}
      					else
      					{
      						GraphicsPSOInit.BlendState = TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_One, BO_Add, BF_One, BF_One>::GetRHI();
      					}
      				}
      
      				SetGraphicsPipelineState(InRHICmdList, GraphicsPSOInit);
      				SetShaderParameters(InRHICmdList, PixelShader, PixelShader.GetPixelShader(), *PassParameters);
      				FPixelShaderUtils::DrawFullscreenTriangle(InRHICmdList);
      			});
      		}
      
      		const bool bIsHairSkyLightingEnabled = HairDatas && (bSkyLight || bDynamicSkyLight || bReflectionEnv);
      		if (bIsHairSkyLightingEnabled)
      		{
      			RDG_GPU_STAT_SCOPE(GraphBuilder, HairSkyLighting);
      			RenderHairStrandsEnvironmentLighting(GraphBuilder, Scene, CurrentViewIndex, Views, HairDatas);
      		}
      	}
      
      	AddResolveSceneColorPass(GraphBuilder, Views, SceneColorTexture);
      }

    2. /** Pixel shader that does tiled deferred culling of reflection captures, then sorts and composites them. */
      class FReflectionEnvironmentSkyLightingPS : public FGlobalShader
      {
      	DECLARE_GLOBAL_SHADER(FReflectionEnvironmentSkyLightingPS);
      	SHADER_USE_PARAMETER_STRUCT(FReflectionEnvironmentSkyLightingPS, FGlobalShader)
      
      	class FHasBoxCaptures : SHADER_PERMUTATION_BOOL("REFLECTION_COMPOSITE_HAS_BOX_CAPTURES");
      	class FHasSphereCaptures : SHADER_PERMUTATION_BOOL("REFLECTION_COMPOSITE_HAS_SPHERE_CAPTURES");
      	class FDFAOIndirectOcclusion : SHADER_PERMUTATION_BOOL("SUPPORT_DFAO_INDIRECT_OCCLUSION");
      	class FSkyLight : SHADER_PERMUTATION_BOOL("ENABLE_SKY_LIGHT");
      	class FDynamicSkyLight : SHADER_PERMUTATION_BOOL("ENABLE_DYNAMIC_SKY_LIGHT");
      	class FSkyShadowing : SHADER_PERMUTATION_BOOL("APPLY_SKY_SHADOWING");
      	class FRayTracedReflections : SHADER_PERMUTATION_BOOL("RAY_TRACED_REFLECTIONS");
      
      	using FPermutationDomain = TShaderPermutationDomain<
      		FHasBoxCaptures,
      		FHasSphereCaptures,
      		FDFAOIndirectOcclusion,
      		FSkyLight,
      		FDynamicSkyLight,
      		FSkyShadowing,
      		FRayTracedReflections>;
      
      	static FPermutationDomain RemapPermutation(FPermutationDomain PermutationVector)
      	{
      		// FSkyLightingDynamicSkyLight requires FSkyLightingSkyLight.
      		if (!PermutationVector.Get<FSkyLight>())
      		{
      			PermutationVector.Set<FDynamicSkyLight>(false);
      		}
      
      		// FSkyLightingSkyShadowing requires FSkyLightingDynamicSkyLight.
      		if (!PermutationVector.Get<FDynamicSkyLight>())
      		{
      			PermutationVector.Set<FSkyShadowing>(false);
      		}
      
      		return PermutationVector;
      	}
      
      	static FPermutationDomain BuildPermutationVector(const FViewInfo& View, bool bBoxCapturesOnly, bool bSphereCapturesOnly, bool bSupportDFAOIndirectOcclusion, bool bEnableSkyLight, bool bEnableDynamicSkyLight, bool bApplySkyShadowing, bool bRayTracedReflections)
      	{
      		FPermutationDomain PermutationVector;
      
      		PermutationVector.Set<FHasBoxCaptures>(bBoxCapturesOnly);
      		PermutationVector.Set<FHasSphereCaptures>(bSphereCapturesOnly);
      		PermutationVector.Set<FDFAOIndirectOcclusion>(bSupportDFAOIndirectOcclusion);
      		PermutationVector.Set<FSkyLight>(bEnableSkyLight);
      		PermutationVector.Set<FDynamicSkyLight>(bEnableDynamicSkyLight);
      		PermutationVector.Set<FSkyShadowing>(bApplySkyShadowing);
      		PermutationVector.Set<FRayTracedReflections>(bRayTracedReflections);
      
      		return RemapPermutation(PermutationVector);
      	}
      
      	static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
      	{
      		if (!IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5))
      		{
      			return false;
      		}
      
      		FPermutationDomain PermutationVector(Parameters.PermutationId);
      		return PermutationVector == RemapPermutation(PermutationVector);
      	}
      
      	static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
      	{
      		FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
      		OutEnvironment.SetDefine(TEXT("MAX_CAPTURES"), GMaxNumReflectionCaptures);
      		OutEnvironment.CompilerFlags.Add(CFLAG_StandardOptimization);
      		FForwardLightingParameters::ModifyCompilationEnvironment(Parameters.Platform, OutEnvironment);
      	}
      
      	BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
      
      		// Sky light parameters.
      		SHADER_PARAMETER(FVector4, OcclusionTintAndMinOcclusion)
      		SHADER_PARAMETER(FVector, ContrastAndNormalizeMulAdd)
      		SHADER_PARAMETER(float, ApplyBentNormalAO)
      		SHADER_PARAMETER(float, InvSkySpecularOcclusionStrength)
      		SHADER_PARAMETER(float, OcclusionExponent)
      		SHADER_PARAMETER(float, OcclusionCombineMode)
      
      		// Distance field AO parameters.
      		// TODO. FDFAOUpsampleParameters
      		SHADER_PARAMETER(FVector2D, AOBufferBilinearUVMax)
      		SHADER_PARAMETER(float, DistanceFadeScale)
      		SHADER_PARAMETER(float, AOMaxViewDistance)
      		SHADER_PARAMETER_RDG_TEXTURE(Texture2D, BentNormalAOTexture)
      		SHADER_PARAMETER_SAMPLER(SamplerState, BentNormalAOSampler)
      
      		SHADER_PARAMETER_RDG_TEXTURE(Texture2D, AmbientOcclusionTexture)
      		SHADER_PARAMETER_SAMPLER(SamplerState, AmbientOcclusionSampler)
      
      		SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ScreenSpaceReflectionsTexture)
      		SHADER_PARAMETER_SAMPLER(SamplerState, ScreenSpaceReflectionsSampler)
      
      		SHADER_PARAMETER_TEXTURE(Texture2D, PreIntegratedGF)
      		SHADER_PARAMETER_SAMPLER(SamplerState, PreIntegratedGFSampler)
      
      		SHADER_PARAMETER_RDG_TEXTURE(Texture2D<float2>, CloudSkyAOTexture)
      		SHADER_PARAMETER_SAMPLER(SamplerState, CloudSkyAOSampler)
      		SHADER_PARAMETER(FMatrix, CloudSkyAOWorldToLightClipMatrix)
      		SHADER_PARAMETER(float, CloudSkyAOFarDepthKm)
      		SHADER_PARAMETER(int32, CloudSkyAOEnabled)
      
      		SHADER_PARAMETER_STRUCT_INCLUDE(FSceneTextureParameters, SceneTextures)
      
      		SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
      		SHADER_PARAMETER_STRUCT_REF(FReflectionUniformParameters, ReflectionsParameters)
      		SHADER_PARAMETER_STRUCT_REF(FReflectionCaptureShaderData, ReflectionCaptureData)
      		SHADER_PARAMETER_STRUCT_REF(FForwardLightData, ForwardLightData)
      
      		RENDER_TARGET_BINDING_SLOTS()
      		END_SHADER_PARAMETER_STRUCT()
      }; // FReflectionEnvironmentSkyLightingPS
      
      IMPLEMENT_GLOBAL_SHADER(FDiffuseIndirectCompositePS, "/Engine/Private/DiffuseIndirectComposite.usf", "MainPS", SF_Pixel);
      IMPLEMENT_GLOBAL_SHADER(FAmbientCubemapCompositePS, "/Engine/Private/AmbientCubemapComposite.usf", "MainPS", SF_Pixel);
      IMPLEMENT_GLOBAL_SHADER(FReflectionEnvironmentSkyLightingPS, "/Engine/Private/ReflectionEnvironmentPixelShader.usf", "ReflectionEnvironmentSkyLighting", SF_Pixel);
      
      
      IMPLEMENT_GLOBAL_SHADER_PARAMETER_STRUCT(FReflectionUniformParameters, "ReflectionStruct");
      
      
      
      BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT(FReflectionUniformParameters,)
      	SHADER_PARAMETER(FVector4, SkyLightParameters)
      	SHADER_PARAMETER(float, SkyLightCubemapBrightness)
      	SHADER_PARAMETER_TEXTURE(TextureCube, SkyLightCubemap)
      	SHADER_PARAMETER_SAMPLER(SamplerState, SkyLightCubemapSampler)
      	SHADER_PARAMETER_TEXTURE(TextureCube, SkyLightBlendDestinationCubemap)
      	SHADER_PARAMETER_SAMPLER(SamplerState, SkyLightBlendDestinationCubemapSampler)
      	SHADER_PARAMETER_TEXTURE(TextureCubeArray, ReflectionCubemap)
      	SHADER_PARAMETER_SAMPLER(SamplerState, ReflectionCubemapSampler)
      	SHADER_PARAMETER_TEXTURE(Texture2D, PreIntegratedGF)
      	SHADER_PARAMETER_SAMPLER(SamplerState, PreIntegratedGFSampler)
      END_GLOBAL_SHADER_PARAMETER_STRUCT()
      
      void SetupReflectionUniformParameters(const FViewInfo& View, FReflectionUniformParameters& OutParameters)
      {
      	FTextureRHIRef SkyLightTextureResource = GBlackTextureCube->TextureRHI;
      	FSamplerStateRHIRef SkyLightCubemapSampler = TStaticSamplerState<SF_Trilinear>::GetRHI();
      	FTexture* SkyLightBlendDestinationTextureResource = GBlackTextureCube;
      	float ApplySkyLightMask = 0;
      	float BlendFraction = 0;
      	bool bSkyLightIsDynamic = false;
      	float SkyAverageBrightness = 1.0f;
      
      	const bool bApplySkyLight = View.Family->EngineShowFlags.SkyLighting;
      	const FScene* Scene = (const FScene*)View.Family->Scene;
      
      	if (Scene
      		&& Scene->SkyLight
      		&& (Scene->SkyLight->ProcessedTexture || (Scene->SkyLight->bRealTimeCaptureEnabled && Scene->ConvolvedSkyRenderTargetReadyIndex >= 0))
      		&& bApplySkyLight)
      	{
      		const FSkyLightSceneProxy& SkyLight = *Scene->SkyLight;
      
      		if (Scene->SkyLight->bRealTimeCaptureEnabled && Scene->ConvolvedSkyRenderTargetReadyIndex >= 0)
      		{
      			// Cannot blend with this capture mode as of today.
      			SkyLightTextureResource = Scene->ConvolvedSkyRenderTarget[Scene->ConvolvedSkyRenderTargetReadyIndex]->GetRenderTargetItem().ShaderResourceTexture;
      		}
      		else if (Scene->SkyLight->ProcessedTexture)
      		{
      			SkyLightTextureResource = SkyLight.ProcessedTexture->TextureRHI;
      			SkyLightCubemapSampler = SkyLight.ProcessedTexture->SamplerStateRHI;
      			BlendFraction = SkyLight.BlendFraction;
      
      			if (SkyLight.BlendFraction > 0.0f && SkyLight.BlendDestinationProcessedTexture)
      			{
      				if (SkyLight.BlendFraction < 1.0f)
      				{
      					SkyLightBlendDestinationTextureResource = SkyLight.BlendDestinationProcessedTexture;
      				}
      				else
      				{
      					SkyLightTextureResource = SkyLight.BlendDestinationProcessedTexture->TextureRHI;
      					SkyLightCubemapSampler = SkyLight.ProcessedTexture->SamplerStateRHI;
      					BlendFraction = 0;
      				}
      			}
      		}
      
      		ApplySkyLightMask = 1;
      		bSkyLightIsDynamic = !SkyLight.bHasStaticLighting && !SkyLight.bWantsStaticShadowing;
      		SkyAverageBrightness = SkyLight.AverageBrightness;
      	}
      
      	const int32 CubemapWidth = SkyLightTextureResource->GetSizeXYZ().X;
      	const float SkyMipCount = FMath::Log2(CubemapWidth) + 1.0f;
      
      	OutParameters.SkyLightCubemap = SkyLightTextureResource;
      	OutParameters.SkyLightCubemapSampler = SkyLightCubemapSampler;
      	OutParameters.SkyLightBlendDestinationCubemap = SkyLightBlendDestinationTextureResource->TextureRHI;
      	OutParameters.SkyLightBlendDestinationCubemapSampler = SkyLightBlendDestinationTextureResource->SamplerStateRHI;
      	OutParameters.SkyLightParameters = FVector4(SkyMipCount - 1.0f, ApplySkyLightMask, bSkyLightIsDynamic ? 1.0f : 0.0f, BlendFraction);
      	OutParameters.SkyLightCubemapBrightness = SkyAverageBrightness;
      
      	// Note: GBlackCubeArrayTexture has an alpha of 0, which is needed to represent invalid data so the sky cubemap can still be applied
      	FRHITexture* CubeArrayTexture = (SupportsTextureCubeArray(View.FeatureLevel))? GBlackCubeArrayTexture->TextureRHI : GBlackTextureCube->TextureRHI;
      
      	if (View.Family->EngineShowFlags.ReflectionEnvironment
      		&& SupportsTextureCubeArray(View.FeatureLevel)
      		&& Scene
      		&& Scene->ReflectionSceneData.CubemapArray.IsValid()
      		&& Scene->ReflectionSceneData.RegisteredReflectionCaptures.Num())
      	{
      		CubeArrayTexture = Scene->ReflectionSceneData.CubemapArray.GetRenderTarget().ShaderResourceTexture;
      	}
      
      	OutParameters.ReflectionCubemap = CubeArrayTexture;
      	OutParameters.ReflectionCubemapSampler = TStaticSamplerState<SF_Trilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
      
      	OutParameters.PreIntegratedGF = GSystemTextures.PreintegratedGF->GetRenderTargetItem().ShaderResourceTexture;
      	OutParameters.PreIntegratedGFSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
      }
      
      TUniformBufferRef<FReflectionUniformParameters> CreateReflectionUniformBuffer(const class FViewInfo& View, EUniformBufferUsage Usage)
      {
      	FReflectionUniformParameters ReflectionStruct;
      	SetupReflectionUniformParameters(View, ReflectionStruct);
      	return CreateUniformBufferImmediate(ReflectionStruct, Usage);
      }

  3.   D:\UnrealEngine426\Engine\Shaders\Private\ReflectionEnvironmentPixelShader.usf
    1. void ReflectionEnvironmentSkyLighting(
      	in float4 SvPosition : SV_Position,
      	out float4 OutColor : SV_Target0)
      {
      	float2 BufferUV = SvPositionToBufferUV(SvPosition);
      	float2 ScreenPosition = SvPositionToScreenPosition(SvPosition).xy;
      
      	// Sample scene textures.
      	FGBufferData GBuffer = GetGBufferDataFromSceneTextures(BufferUV);
      
      	float3 DiffuseColor = GBuffer.DiffuseColor;
      	float3 SpecularColor = GBuffer.SpecularColor;
      	RemapClearCoatDiffuseAndSpecularColor(GBuffer, ScreenPosition, DiffuseColor, SpecularColor);
      
      	// Sample the ambient occlusion that is dynamically generated every frame.
      	float AmbientOcclusion = AmbientOcclusionTexture.SampleLevel(AmbientOcclusionSampler, BufferUV, 0).r;
      	
      	uint ShadingModelID = GBuffer.ShadingModelID;
      	float3 BentNormal = GBuffer.WorldNormal;
      	#if APPLY_SKY_SHADOWING
      	{
      		BentNormal = UpsampleDFAO(BufferUV, GBuffer.Depth, GBuffer.WorldNormal);
      	}
      	#endif
      	
      	OutColor = 0.0f;
      
      	#if ENABLE_DYNAMIC_SKY_LIGHT
      	BRANCH
      	// Only light pixels marked as lit
      	if (ShadingModelID != SHADINGMODELID_UNLIT)
      	{
      		float CloudAmbientOcclusion = 1.0f;
      		// Ideally we would compute spatially how much of the sky+cloud is visible for each point in the world. But we evaluate the sky light only once at the sky light component position as of today.
      		// To add some spatial variation, we can affect the sky light diffuse contribution according to cloud occlusion from above.
      		// This is an approximation because clouds are also occluding the sky in the sky light capture (a bit of a double contribution then). but it does help by adding spatially varying details.
      #if 0	// DISABLED for now because it has artefact with specular not being affected (and thus looking too bright which can be confusing for users).
      		if (CloudSkyAOEnabled)
      		{
      			float3 WorldPosition = mul(float4(ScreenPosition * GBuffer.Depth, GBuffer.Depth, 1), View.ScreenToWorld).xyz;
      			float OutOpticalDepth = 0.0f;
      			CloudAmbientOcclusion = GetCloudVolumetricShadow(WorldPosition, CloudSkyAOWorldToLightClipMatrix, CloudSkyAOFarDepthKm, CloudSkyAOTexture, CloudSkyAOSampler, OutOpticalDepth);
      		}
      #endif
      
      		float3 SkyLighting = SkyLightDiffuse(GBuffer, AmbientOcclusion, BufferUV, ScreenPosition, BentNormal, DiffuseColor) * CloudAmbientOcclusion;
      
      		// Scene color alpha is used for ScreenSpaceSubsurfaceScattering (if that is not needed it can be disabled with SUBSURFACE_CHANNEL_MODE)
      		FLightAccumulator LightAccumulator = (FLightAccumulator)0;
      
      		const bool bNeedsSeparateSubsurfaceLightAccumulation = UseSubsurfaceProfile(ShadingModelID);
      
      		LightAccumulator_Add(LightAccumulator, SkyLighting, SkyLighting, 1.0f, bNeedsSeparateSubsurfaceLightAccumulation);
      		OutColor = LightAccumulator_GetResult(LightAccumulator);
      	}
      	#endif
      
      	BRANCH
      	if (ShadingModelID != SHADINGMODELID_UNLIT && ShadingModelID != SHADINGMODELID_HAIR)
      	{
      		OutColor.xyz += ReflectionEnvironment(GBuffer, AmbientOcclusion, BufferUV, ScreenPosition, SvPosition, BentNormal, SpecularColor);
      	}
      }

      1.  D:\UnrealEngine426\Engine\Shaders\Private\ReflectionEnvironmentPixelShader.usf

        1. 
          float3 SkyLightDiffuse(FGBufferData GBuffer, float AmbientOcclusion, float2 BufferUV, float2 ScreenPosition, float3 BentNormal, float3 DiffuseColor)
          {
          	float2 UV = BufferUV;
          	float3 Lighting = 0;
          
          	float SkyVisibility = 1;
          	float DotProductFactor = 1;
          	float3 SkyLightingNormal = GBuffer.WorldNormal;
          	BRANCH if( GBuffer.ShadingModelID == SHADINGMODELID_CLEAR_COAT && CLEAR_COAT_BOTTOM_NORMAL)
          	{
          		const float2 oct1 = ((float2(GBuffer.CustomData.a, GBuffer.CustomData.z) * 2) - (256.0/255.0)) + UnitVectorToOctahedron(GBuffer.WorldNormal);
          		SkyLightingNormal = OctahedronToUnitVector(oct1);			
          	}
          	
          #if APPLY_SKY_SHADOWING
          #define USE_DIRECTIONAL_OCCLUSION_ON_SKY_DIFFUSE 1
          
          #if USE_DIRECTIONAL_OCCLUSION_ON_SKY_DIFFUSE
          	{
          		SkyVisibility = length(BentNormal);
          		float3 NormalizedBentNormal = BentNormal / (max(SkyVisibility, .00001f));
          
          		// Use more bent normal in corners
          		float BentNormalWeightFactor = SkyVisibility;
          
          		SkyLightingNormal = lerp(NormalizedBentNormal, GBuffer.WorldNormal, BentNormalWeightFactor);
          		DotProductFactor = lerp(dot(NormalizedBentNormal, GBuffer.WorldNormal), 1, BentNormalWeightFactor);
          	}
          #else
          	{
          		SkyVisibility = length(BentNormal);
          	}
          #endif
          
          	float ContrastCurve = 1 / (1 + exp(-ContrastAndNormalizeMulAdd.x * (SkyVisibility * 10 - 5)));
          	SkyVisibility = saturate(ContrastCurve * ContrastAndNormalizeMulAdd.y + ContrastAndNormalizeMulAdd.z);
          
          #endif
          
          	// Apply DFAO controls
          	SkyVisibility = pow(SkyVisibility, OcclusionExponent);
          	SkyVisibility = lerp(SkyVisibility, 1, OcclusionTintAndMinOcclusion.w);
          
          	// Combine with other AO sources
          	if (OcclusionCombineMode == 0)
          	{
          		// Combine with min which nicely avoids over-occlusion in cases where strong DFAO is present along with strong SSAO (distant trees)
          		SkyVisibility = min(SkyVisibility, min(GBuffer.GBufferAO, AmbientOcclusion));
          	}
          	else
          	{
          		// Combine with mul, which continues to add SSAO depth even indoors.  SSAO will need to be tweaked to be less strong.
          		SkyVisibility = SkyVisibility * min(GBuffer.GBufferAO, AmbientOcclusion);
          	}
          
          	float ScalarFactors = SkyVisibility;
          
          	BRANCH
          	if (GBuffer.ShadingModelID == SHADINGMODELID_TWOSIDED_FOLIAGE)
          	{
          		float3 SubsurfaceLookup = GetSkySHDiffuse(-GBuffer.WorldNormal) * View.SkyLightColor.rgb;
          		float3 SubsurfaceColor = ExtractSubsurfaceColor(GBuffer);
          		Lighting += ScalarFactors * SubsurfaceLookup * SubsurfaceColor;
          	}
          
          	if (GBuffer.ShadingModelID == SHADINGMODELID_SUBSURFACE || GBuffer.ShadingModelID == SHADINGMODELID_PREINTEGRATED_SKIN)
          	{
          		float3 SubsurfaceColor = ExtractSubsurfaceColor(GBuffer);
          		// Add subsurface energy to diffuse
          		DiffuseColor += SubsurfaceColor;
          	}
          
          	BRANCH
          	if (GBuffer.ShadingModelID == SHADINGMODELID_HAIR)
          	{
          		float3 N = GBuffer.WorldNormal;
          		float3 V = -normalize(mul(float4(ScreenPosition, 1, 0), View.ScreenToWorld).xyz);
          		float3 L = normalize(V - N * dot(V, N));
          		SkyLightingNormal = L;
          		FHairTransmittanceData TransmittanceData = InitHairTransmittanceData(true);
          		DiffuseColor = PI * HairShading(GBuffer, L, V, N, 1, TransmittanceData, 0, 0.2, uint2(0, 0));
          	}
          
          	if (GBuffer.ShadingModelID == SHADINGMODELID_CLOTH)
          	{
          		float3 ClothFuzz = ExtractSubsurfaceColor(GBuffer);
          		DiffuseColor += ClothFuzz * GBuffer.CustomData.a;
          	}
          
          	// Compute the preconvolved incoming lighting with the bent normal direction
          	float3 DiffuseLookup = GetSkySHDiffuse(SkyLightingNormal) * View.SkyLightColor.rgb;
          
          	// Apply AO to the sky diffuse and account for darkening due to the geometry term
          	// apply the Diffuse color to the lighting (including OcclusionTintAndMinOcclusion as it's considered another light, that fixes SubsurfaceProfile being too dark)
          	Lighting += ((ScalarFactors * DotProductFactor) * DiffuseLookup + (1 - SkyVisibility) * OcclusionTintAndMinOcclusion.xyz) * DiffuseColor;
          
          #if USE_PREEXPOSURE
          	Lighting *= View.PreExposure;
          #endif
          
          	//Lighting = (Texture2DSampleLevel(BentNormalAOTexture, BentNormalAOSampler, UV, 0).xyz);
          
          	return Lighting;
          }
          

        2. D:\UnrealEngine426\Engine\Shaders\Private\ReflectionEnvironmentShared.ush

          1. 
            #if (FEATURE_LEVEL <= FEATURE_LEVEL_ES3_1)
            #define SkyIrradianceEnvironmentMap		View.MobileSkyIrradianceEnvironmentMap
            #else
            #define SkyIrradianceEnvironmentMap		View.SkyIrradianceEnvironmentMap
            #endif
            
            /** 
             * Computes sky diffuse lighting from the SH irradiance map.  
             * This has the SH basis evaluation and diffuse convolution weights combined for minimal ALU's - see "Stupid Spherical Harmonics (SH) Tricks" 
             */
            float3 GetSkySHDiffuse(float3 Normal)
            {
            	float4 NormalVector = float4(Normal, 1.0f); 
            
            	float3 Intermediate0, Intermediate1, Intermediate2;
            	Intermediate0.x = dot(SkyIrradianceEnvironmentMap[0], NormalVector);
            	Intermediate0.y = dot(SkyIrradianceEnvironmentMap[1], NormalVector);
            	Intermediate0.z = dot(SkyIrradianceEnvironmentMap[2], NormalVector);
            
            	float4 vB = NormalVector.xyzz * NormalVector.yzzx;
            	Intermediate1.x = dot(SkyIrradianceEnvironmentMap[3], vB);
            	Intermediate1.y = dot(SkyIrradianceEnvironmentMap[4], vB);
            	Intermediate1.z = dot(SkyIrradianceEnvironmentMap[5], vB);
            
            	float vC = NormalVector.x * NormalVector.x - NormalVector.y * NormalVector.y;
            	Intermediate2 = SkyIrradianceEnvironmentMap[6].xyz * vC;
            
            	// max to not get negative colors
            	return max(0, Intermediate0 + Intermediate1 + Intermediate2);
            }

    2.  D:\UnrealEngine426\Engine\Shaders\Private\ReflectionEnvironmentPixelShader.usf
      1. float3 ReflectionEnvironment(FGBufferData GBuffer, float AmbientOcclusion, float2 BufferUV, float2 ScreenPosition, float4 SvPosition, float3 BentNormal, float3 SpecularColor)
        {
        #if USE_PREEXPOSURE
        	const float PreExposure = View.PreExposure;
        #else
        	const float PreExposure = 1.f;
        #endif
        	
        	float4 Color = float4(0, 0, 0, 1);
        
        	float3 WorldPosition = mul(float4(ScreenPosition * GBuffer.Depth, GBuffer.Depth, 1), View.ScreenToWorld).xyz;
        	float3 CameraToPixel = normalize(WorldPosition - View.WorldCameraOrigin);
        	float3 ReflectionVector = reflect(CameraToPixel, GBuffer.WorldNormal);
        	float IndirectIrradiance = GBuffer.IndirectIrradiance;
        	
        #if ENABLE_SKY_LIGHT && ALLOW_STATIC_LIGHTING
        	BRANCH
        	// Add in diffuse contribution from dynamic skylights so reflection captures will have something to mix with
        	if (ReflectionStruct.SkyLightParameters.y > 0 && ReflectionStruct.SkyLightParameters.z > 0)
        	{
        		IndirectIrradiance += GetDynamicSkyIndirectIrradiance(BentNormal, GBuffer.WorldNormal);
        	}
        #endif
        
        	float3 N = GBuffer.WorldNormal;
        	float3 V = -CameraToPixel;
        
        	ModifyGGXAnisotropicNormalRoughness(GBuffer.WorldTangent, GBuffer.Anisotropy, GBuffer.Roughness, N, V);
        
        	float3 R = 2 * dot( V, N ) * N - V;
        	float NoV = saturate( dot( N, V ) );
        
        	// Point lobe in off-specular peak direction
        	R = GetOffSpecularPeakReflectionDir(N, R, GBuffer.Roughness);
        
        #if 1
        	// Note: this texture may also contain planar reflections
        	float4 SSR = Texture2DSample(ScreenSpaceReflectionsTexture, ScreenSpaceReflectionsSampler, BufferUV);
        	Color.rgb = SSR.rgb;
        	Color.a = 1 - SSR.a;
        #endif
        
        #if RAY_TRACED_REFLECTIONS
        	float4 SavedColor = Color;	// When a clear coat material is encountered, we save the reflection buffer color for it to not be affected by operations.
        #endif
        	if(GBuffer.ShadingModelID == SHADINGMODELID_CLEAR_COAT )
        	{
        #if RAY_TRACED_REFLECTIONS
        		Color = float4(0, 0, 0, 1); // Clear coat reflection is expected to be computed on a black background
        #endif
        		const float ClearCoat = GBuffer.CustomData.x;
        		Color = lerp( Color, float4(0,0,0,1), ClearCoat );
        
        #if CLEAR_COAT_BOTTOM_NORMAL
        		const float2 oct1 = ((float2(GBuffer.CustomData.a, GBuffer.CustomData.z) * 2) - (256.0/255.0)) + UnitVectorToOctahedron(GBuffer.WorldNormal);
        		const float3 ClearCoatUnderNormal = OctahedronToUnitVector(oct1);
        
        		const float3 BottomEffectiveNormal = ClearCoatUnderNormal;			
        		R = 2 * dot( V, ClearCoatUnderNormal ) * ClearCoatUnderNormal - V;
        #endif
        	}
        
        	float AO = GBuffer.GBufferAO * AmbientOcclusion;
        	float RoughnessSq = GBuffer.Roughness * GBuffer.Roughness;
        	float SpecularOcclusion = GetSpecularOcclusion(NoV, RoughnessSq, AO);
        	Color.a *= SpecularOcclusion;
        
        #if FEATURE_LEVEL >= FEATURE_LEVEL_SM5
        	float2 LocalPosition = SvPosition.xy - View.ViewRectMin.xy;
        
        	uint GridIndex = ComputeLightGridCellIndex(uint2(LocalPosition.x, LocalPosition.y), GBuffer.Depth);
        	uint NumCulledEntryIndex = (ForwardLightData.NumGridCells + GridIndex) * NUM_CULLED_LIGHTS_GRID_STRIDE;
        	uint NumCulledReflectionCaptures = min(ForwardLightData.NumCulledLightsGrid[NumCulledEntryIndex + 0], ForwardLightData.NumReflectionCaptures);
        	uint DataStartIndex = ForwardLightData.NumCulledLightsGrid[NumCulledEntryIndex + 1];
        #else
        	uint DataStartIndex = 0;
        	uint NumCulledReflectionCaptures = 0;
        #endif
        
        	//Top of regular reflection or bottom layer of clear coat.
        	Color.rgb += PreExposure * GatherRadiance(Color.a, WorldPosition, R, GBuffer.Roughness, BentNormal, IndirectIrradiance, GBuffer.ShadingModelID, NumCulledReflectionCaptures, DataStartIndex);
        
        	BRANCH
        	if( GBuffer.ShadingModelID == SHADINGMODELID_CLEAR_COAT)
        	{
        		const float ClearCoat			= GBuffer.CustomData.x;
        		const float ClearCoatRoughness	= GBuffer.CustomData.y;
        
        		// TODO EnvBRDF should have a mask param
        		float2 AB = PreIntegratedGF.SampleLevel( PreIntegratedGFSampler, float2( NoV, GBuffer.Roughness ), 0 ).rg;
        		Color.rgb *= SpecularColor * AB.x + AB.y * saturate( 50 * SpecularColor.g ) * (1 - ClearCoat);
        		
        		// F_Schlick
        		float F = EnvBRDF( 0.04, ClearCoatRoughness, NoV ).x;
        		
        		F *= ClearCoat;
        			
        		float LayerAttenuation = (1 - F);		
        		Color.rgb *= LayerAttenuation;
        		Color.a = F;
        		
        #if !RAY_TRACED_REFLECTIONS	
        		Color.rgb += SSR.rgb * F;
        		Color.a *= 1 - SSR.a;
        #endif
        			
        		Color.a *= SpecularOcclusion;
        
        		float3 TopLayerR = 2 * dot( V, N ) * N - V;
        		Color.rgb += PreExposure * GatherRadiance(Color.a, WorldPosition, TopLayerR, ClearCoatRoughness, BentNormal, IndirectIrradiance, GBuffer.ShadingModelID, NumCulledReflectionCaptures, DataStartIndex);
        
        	#if RAY_TRACED_REFLECTIONS
        		Color.rgb = SavedColor.rgb +  Color.rgb * SavedColor.a; // Compose default clear coat reflection over regular refelction (using Premultiplied alpha where SaveColor.a=transmittance)
        	#endif
        	}
        	else
        	{
        		Color.rgb *= EnvBRDF( SpecularColor, GBuffer.Roughness, NoV );
        	}
        
        	// Transform NaNs to black, transform negative colors to black.
        	return -min(-Color.rgb, 0.0);
        }
        
        float3 GatherRadiance(float CompositeAlpha, float3 WorldPosition, 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 CompositeReflectionCapturesAndSkylight(
        		CompositeAlpha, 
        		WorldPosition, 
        		RayDirection, 
        		Roughness, 
        		IndirectIrradiance, 
        		IndirectSpecularOcclusion, 
        		ExtraIndirectSpecular, 
        		NumCulledReflectionCaptures, 
        		CaptureDataStartIndex, 
        		0,
        		bCompositeSkylight);
        }

      2.  D:\UnrealEngine426\Engine\Shaders\Private\ReflectionEnvironmentComposite.ush

        1. // Copyright Epic Games, Inc. All Rights Reserved.
          
          /*=============================================================================
          	ReflectionEnvironmentComposite
          =============================================================================*/
          
          float3 CompositeReflectionCapturesAndSkylight(
          	float CompositeAlpha, 
          	float3 WorldPosition, 
          	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
          		BRANCH
          		if (EyeIndex == 0)
          		{
          	#endif
          	
          			CaptureIndex = ForwardLightData.CulledLightDataGrid[CaptureDataStartIndex + TileCaptureIndex];
          	
          	#if INSTANCED_STEREO
          		}
          		else
          		{
          			CaptureIndex = ForwardLightDataISR.CulledLightDataGrid[CaptureDataStartIndex + TileCaptureIndex];
          		}
          	#endif
          #endif
          
          			
          		float4 CapturePositionAndRadius = ReflectionCapture.PositionAndRadius[CaptureIndex];
          		float4 CaptureProperties = ReflectionCapture.CaptureProperties[CaptureIndex];
          
          		float3 CaptureVector = WorldPosition - CapturePositionAndRadius.xyz;
          		float CaptureVectorLength = sqrt(dot(CaptureVector, CaptureVector));		
          		float NormalizedDistanceToCapture = saturate(CaptureVectorLength / CapturePositionAndRadius.w);
          
          		BRANCH
          		if (CaptureVectorLength < CapturePositionAndRadius.w)
          		{
          			float3 ProjectedCaptureVector = RayDirection;
          			float4 CaptureOffsetAndAverageBrightness = ReflectionCapture.CaptureOffsetAndAverageBrightness[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, WorldPosition, CapturePositionAndRadius, ReflectionCapture.BoxTransform[CaptureIndex], ReflectionCapture.BoxScales[CaptureIndex], CaptureOffsetAndAverageBrightness.xyz, DistanceAlpha);
          					}
          				#endif
          
          				#if REFLECTION_COMPOSITE_HAS_SPHERE_CAPTURES
          					// Sphere
          					#if REFLECTION_COMPOSITE_HAS_BOX_CAPTURES
          					else
          					#endif
          					{
          						ProjectedCaptureVector = GetLookupVectorForSphereCapture(RayDirection, WorldPosition, CapturePositionAndRadius, 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;
          
          	float4 SingleCaptureOffsetAndAverageBrightness = ReflectionCapture.CaptureOffsetAndAverageBrightness[SingleCaptureIndex];
          	float4 SingleCapturePositionAndRadius = ReflectionCapture.PositionAndRadius[SingleCaptureIndex];
          	float SingleCaptureBrightness = ReflectionCapture.CaptureProperties[SingleCaptureIndex].x;
          	float SingleCaptureArrayIndex = ReflectionCapture.CaptureProperties[SingleCaptureIndex].y;
          
          	#define APPROXIMATE_CONTINUOUS_SINGLE_CAPTURE_PARALLAX 0
          	#if APPROXIMATE_CONTINUOUS_SINGLE_CAPTURE_PARALLAX
          		float3 CaptureVector = WorldPosition - SingleCapturePositionAndRadius.xyz;
          		float CaptureVectorLength = sqrt(dot(CaptureVector, CaptureVector));		
          		float NormalizedDistanceToCapture = saturate(CaptureVectorLength / SingleCapturePositionAndRadius.w);
          
          		float UnusedDistanceAlpha = 0;
          		ProjectedCaptureVector = GetLookupVectorForSphereCapture(RayDirection, WorldPosition, SingleCapturePositionAndRadius, 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.IndirectLightingColorScale;
          	CompositedAverageBrightness.x *= Luminance( View.IndirectLightingColorScale );
          
          #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
          		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;
          }
          
          float3 CompositeReflectionCapturesAndSkylight(
          	float CompositeAlpha, 
          	float3 WorldPosition, 
          	float3 RayDirection, 
          	float Roughness, 
          	float IndirectIrradiance, 
          	float IndirectSpecularOcclusion,
          	float3 ExtraIndirectSpecular,
          	uint NumCapturesAffectingTile,
          	uint CaptureDataStartIndex,
          	int SingleCaptureIndex,
          	bool bCompositeSkylight)
          {
          	return CompositeReflectionCapturesAndSkylight(
          		CompositeAlpha, 
          		WorldPosition, 
          		RayDirection, 
          		Roughness, 
          		IndirectIrradiance, 
          		IndirectSpecularOcclusion, 
          		ExtraIndirectSpecular, 
          		NumCapturesAffectingTile, 
          		CaptureDataStartIndex,
          		SingleCaptureIndex,
          		bCompositeSkylight,
          		0);
          }

        2. //

          1. // ReflectionStruct.SkyLightParameters: X = max mip, Y = 1 if sky light should be rendered, 0 otherwise, Z = 1 if sky light is dynamic, 0 otherwise, W = blend fraction. 
            
            float3 GetSkyLightReflection(float3 ReflectionVector, float Roughness, out float OutSkyAverageBrightness)
            {
            	float AbsoluteSpecularMip = ComputeReflectionCaptureMipFromRoughness(Roughness, ReflectionStruct.SkyLightParameters.x);
            	float3 Reflection = TextureCubeSampleLevel(ReflectionStruct.SkyLightCubemap, ReflectionStruct.SkyLightCubemapSampler, ReflectionVector, AbsoluteSpecularMip).rgb;
            
            	OutSkyAverageBrightness = ReflectionStruct.SkyLightCubemapBrightness * Luminance( View.SkyLightColor.rgb );
            	return Reflection * View.SkyLightColor.rgb;
            }
            
            float3 GetSkyLightReflectionSupportingBlend(float3 ReflectionVector, float Roughness, out float OutSkyAverageBrightness)
            {
            	float3 Reflection = GetSkyLightReflection(ReflectionVector, Roughness, OutSkyAverageBrightness);
            
            	BRANCH
            	if (ReflectionStruct.SkyLightParameters.w > 0)
            	{
            		float AbsoluteSpecularMip = ComputeReflectionCaptureMipFromRoughness(Roughness, ReflectionStruct.SkyLightParameters.x);
            		float3 BlendDestinationReflection = TextureCubeSampleLevel(ReflectionStruct.SkyLightBlendDestinationCubemap, ReflectionStruct.SkyLightBlendDestinationCubemapSampler, ReflectionVector, AbsoluteSpecularMip).rgb;
            
            		Reflection = lerp(Reflection, BlendDestinationReflection * View.SkyLightColor.rgb, ReflectionStruct.SkyLightParameters.w);
            	}
            
            	return Reflection;
            }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值