Scene:Translucency-Translucency(AfterDOF)

Engine/Source/Runtime/Renderer/Private/DeferredShadingRenderer.cpp

Render():

	// Draw translucency.
	TArray<FScreenPassTexture> TSRMoireInputTextures;
	if (!bHasRayTracedOverlay && TranslucencyViewsToRender != ETranslucencyView::None)
	{
		RDG_CSV_STAT_EXCLUSIVE_SCOPE(GraphBuilder, RenderTranslucency);
		SCOPE_CYCLE_COUNTER(STAT_TranslucencyDrawTime);

		RDG_EVENT_SCOPE(GraphBuilder, "Translucency");

		// Raytracing doesn't need the distortion effect.
		const bool bShouldRenderDistortion = TranslucencyViewsToRender != ETranslucencyView::RayTracing;

#if RHI_RAYTRACING
		if (EnumHasAnyFlags(TranslucencyViewsToRender, ETranslucencyView::RayTracing))
		{
			RenderRayTracingTranslucency(GraphBuilder, SceneTextures.Color);
			EnumRemoveFlags(TranslucencyViewsToRender, ETranslucencyView::RayTracing);
		}
#endif

		for (FViewInfo& View : Views)
		{
			if (GetViewPipelineState(View).ReflectionsMethod == EReflectionsMethod::Lumen)
			{
				RenderLumenFrontLayerTranslucencyReflections(GraphBuilder, View, SceneTextures, LumenFrameTemporaries);
			}
		}

		// Extract TSR's moire heuristic luminance before renderering translucency into the scene color.
		for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
		{
			FViewInfo& View = Views[ViewIndex];
			if (ITemporalUpscaler::GetMainTAAPassConfig(View) == EMainTAAPassConfig::TSR)
			{
				if (TSRMoireInputTextures.Num() == 0)
				{
					TSRMoireInputTextures.SetNum(Views.Num());
				}

				TSRMoireInputTextures[ViewIndex] = AddTSRComputeMoireLuma(GraphBuilder, View.ShaderMap, FScreenPassTexture(SceneTextures.Color.Target, View.ViewRect));
			}
		}

		// Sort objects' triangles
		for (FViewInfo& View : Views)
		{
			if (OIT::IsEnabled(EOITSortingType::SortedTriangles, View))
			{
				OIT::AddSortTrianglesPass(GraphBuilder, View, Scene->OITSceneData, FTriangleSortingOrder::BackToFront);
			}
		}

		// Render all remaining translucency views.
		GraphBuilder.SetCommandListStat(GET_STATID(STAT_CLM_Translucency));
		RenderTranslucency(GraphBuilder, SceneTextures, TranslucencyLightingVolumeTextures, &TranslucencyResourceMap, TranslucencyViewsToRender, InstanceCullingManager);
		TranslucencyViewsToRender = ETranslucencyView::None;

		// Compose hair before velocity/distortion pass since these pass write depth value, 
		// and this would make the hair composition fails in this cases.
		if (GetHairStrandsComposition() == EHairStrandsCompositionType::AfterTranslucent)
		{
			RDG_GPU_STAT_SCOPE(GraphBuilder, HairRendering);
			RenderHairComposition(GraphBuilder, Views, SceneTextures.Color.Target, SceneTextures.Depth.Target, SceneTextures.Velocity);
		}

		if (bShouldRenderDistortion)
		{
			GraphBuilder.SetCommandListStat(GET_STATID(STAT_CLM_Distortion));
			RenderDistortion(GraphBuilder, SceneTextures.Color.Target, SceneTextures.Depth.Target);
		}

		if (bShouldRenderVelocities)
		{
			const bool bRecreateSceneTextures = !HasBeenProduced(SceneTextures.Velocity);

			GraphBuilder.SetCommandListStat(GET_STATID(STAT_CLM_TranslucentVelocity));
			RenderVelocities(GraphBuilder, SceneTextures, EVelocityPass::Translucent, false);

			if (bRecreateSceneTextures)
			{
				// Rebuild scene textures to include newly allocated velocity.
				SceneTextures.UniformBuffer = CreateSceneTextureUniformBuffer(GraphBuilder, &SceneTextures, FeatureLevel, SceneTextures.SetupMode);
			}
		}

		GraphBuilder.SetCommandListStat(GET_STATID(STAT_CLM_AfterTranslucency));
	}
	else if (GetHairStrandsComposition() == EHairStrandsCompositionType::AfterTranslucent)
	{
		RDG_GPU_STAT_SCOPE(GraphBuilder, HairRendering);
		RenderHairComposition(GraphBuilder, Views, SceneTextures.Color.Target, SceneTextures.Depth.Target, SceneTextures.Velocity);
	}

Translucency(AfterDOF)

void FDeferredShadingSceneRenderer::RenderTranslucency(
	FRDGBuilder& GraphBuilder,
	const FSceneTextures& SceneTextures,
	const FTranslucencyLightingVolumeTextures& TranslucentLightingVolumeTextures,
	FTranslucencyPassResourcesMap* OutTranslucencyResourceMap,
	ETranslucencyView ViewsToRender,
	FInstanceCullingManager& InstanceCullingManager)
{
	if (!EnumHasAnyFlags(ViewsToRender, ETranslucencyView::UnderWater | ETranslucencyView::AboveWater))
	{
		return;
	}

	RDG_GPU_STAT_SCOPE(GraphBuilder, Translucency);
	DynamicRenderScaling::FRDGScope DynamicTranslucencyResolutionScope(GraphBuilder, GDynamicTranslucencyResolution);

	FRDGTextureRef SceneColorCopyTexture = nullptr;

	if (EnumHasAnyFlags(ViewsToRender, ETranslucencyView::AboveWater))
	{
		SceneColorCopyTexture = AddCopySceneColorPass(GraphBuilder, Views, SceneTextures.Color);
	}

	const auto ShouldRenderView = [&](const FViewInfo& View, ETranslucencyView TranslucencyView)
	{
		return View.ShouldRenderView() && EnumHasAnyFlags(TranslucencyView, ViewsToRender);
	};

	// Create a shared depth texture at the correct resolution.
	FRDGTextureMSAA SharedDepthTexture;
	const bool bIsScalingTranslucency = SeparateTranslucencyDimensions.Scale != 1.0f;
	if (bIsScalingTranslucency)
	{
		const FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
			SeparateTranslucencyDimensions.Extent,
			PF_DepthStencil,
			FClearValueBinding::DepthFar,
			TexCreate_DepthStencilTargetable | TexCreate_ShaderResource,
			1,
			SeparateTranslucencyDimensions.NumSamples);

		SharedDepthTexture = CreateTextureMSAA(
			GraphBuilder, Desc,
			TEXT("Translucency.Depth"),
			GFastVRamConfig.SeparateTranslucencyModulate); // TODO: this should be SeparateTranslucency, but is what the code was doing

		// Downscale the depth buffer for each individual view, but shared accross all translucencies.
		for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
		{
			FViewInfo& View = Views[ViewIndex];
			const ETranslucencyView TranslucencyView = GetTranslucencyView(View);

			if (!ShouldRenderView(View, TranslucencyView))
			{
				continue;
			}

			const FScreenPassTextureViewport SeparateTranslucencyViewport = SeparateTranslucencyDimensions.GetInstancedStereoViewport(View);
			AddDownsampleDepthPass(
				GraphBuilder, View,
				FScreenPassTexture(SceneTextures.Depth.Resolve, View.ViewRect),
				FScreenPassRenderTarget(SharedDepthTexture.Target, SeparateTranslucencyViewport.Rect, ViewIndex == 0 ? ERenderTargetLoadAction::EClear : ERenderTargetLoadAction::ELoad),
				EDownsampleDepthFilter::Point);
		}
	}
	else
	{
		// Uses the existing depth buffer for depth testing the translucency.
		SharedDepthTexture = SceneTextures.Depth;
	}

	if (ViewFamily.AllowTranslucencyAfterDOF())
	{
		RenderTranslucencyInner(GraphBuilder, SceneTextures, TranslucentLightingVolumeTextures, OutTranslucencyResourceMap, SharedDepthTexture, ViewsToRender, SceneColorCopyTexture, ETranslucencyPass::TPT_StandardTranslucency, InstanceCullingManager);
		if (GetHairStrandsComposition() == EHairStrandsCompositionType::AfterTranslucentBeforeTranslucentAfterDOF)
		{
			RenderHairComposition(GraphBuilder, Views, SceneTextures.Color.Target, SceneTextures.Depth.Target, SceneTextures.Velocity);
		}
		RenderTranslucencyInner(GraphBuilder, SceneTextures, TranslucentLightingVolumeTextures, OutTranslucencyResourceMap, SharedDepthTexture, ViewsToRender, SceneColorCopyTexture, ETranslucencyPass::TPT_TranslucencyAfterDOF, InstanceCullingManager);
		RenderTranslucencyInner(GraphBuilder, SceneTextures, TranslucentLightingVolumeTextures, OutTranslucencyResourceMap, SharedDepthTexture, ViewsToRender, SceneColorCopyTexture, ETranslucencyPass::TPT_TranslucencyAfterDOFModulate, InstanceCullingManager);
		RenderTranslucencyInner(GraphBuilder, SceneTextures, TranslucentLightingVolumeTextures, OutTranslucencyResourceMap, SharedDepthTexture, ViewsToRender, SceneColorCopyTexture, ETranslucencyPass::TPT_TranslucencyAfterMotionBlur, InstanceCullingManager);
	}
	else // Otherwise render translucent primitives in a single bucket.
	{
		RenderTranslucencyInner(GraphBuilder, SceneTextures, TranslucentLightingVolumeTextures, OutTranslucencyResourceMap, SharedDepthTexture, ViewsToRender, SceneColorCopyTexture, ETranslucencyPass::TPT_AllTranslucency, InstanceCullingManager);
	}

	bool bUpscalePostDOFTranslucency = true;
	FRDGTextureRef SharedUpscaledPostDOFTranslucencyColor = nullptr;
	if (bUpscalePostDOFTranslucency)
	{
		const FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
			SceneTextures.Color.Resolve->Desc.Extent,
			PF_FloatRGBA,
			FClearValueBinding::Black,
			TexCreate_RenderTargetable | TexCreate_ShaderResource);

		SharedUpscaledPostDOFTranslucencyColor = GraphBuilder.CreateTexture(
			Desc, TEXT("Translucency.PostDOF.UpscaledColor"));
	}

	// Upscale to full res.
	for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
	{
		FViewInfo& View = Views[ViewIndex];
		const ETranslucencyView TranslucencyView = GetTranslucencyView(View);

		if (!ShouldRenderView(View, TranslucencyView))
		{
			continue;
		}

		// Upscale the responsive AA into original depth buffer.
		bool bUpscaleResponsiveAA = (
			IsTemporalAccumulationBasedMethod(View.AntiAliasingMethod) &&
			SharedDepthTexture.Target != SceneTextures.Depth.Target);
		if (bUpscaleResponsiveAA)
		{
			const FScreenPassTextureViewport SeparateTranslucencyViewport = SeparateTranslucencyDimensions.GetInstancedStereoViewport(View);
			AddUpsampleResponsiveAAPass(
				GraphBuilder,
				View,
				FScreenPassTexture(SharedDepthTexture.Target, SeparateTranslucencyViewport.Rect),
				/* OutputDepthTexture = */ SceneTextures.Depth.Target);
		}

		FTranslucencyPassResources& TranslucencyPassResources = OutTranslucencyResourceMap->Get(ViewIndex, ETranslucencyPass::TPT_TranslucencyAfterDOF);
		if (SharedUpscaledPostDOFTranslucencyColor && TranslucencyPassResources.IsValid() && TranslucencyPassResources.ViewRect.Size() != View.ViewRect.Size() && ITemporalUpscaler::GetMainTAAPassConfig(View) != EMainTAAPassConfig::TSR)
		{
			FTranslucencyComposition TranslucencyComposition;
			TranslucencyComposition.Operation = FTranslucencyComposition::EOperation::UpscaleOnly;
			TranslucencyComposition.SceneDepth = FScreenPassTexture(SceneTextures.Depth.Resolve, View.ViewRect);
			TranslucencyComposition.OutputViewport = FScreenPassTextureViewport(SceneTextures.Depth.Resolve, View.ViewRect);

			FScreenPassTexture UpscaledTranslucency = TranslucencyComposition.AddPass(
				GraphBuilder, View, TranslucencyPassResources);

			TranslucencyPassResources.ViewRect = UpscaledTranslucency.ViewRect;
			TranslucencyPassResources.ColorTexture = FRDGTextureMSAA(UpscaledTranslucency.Texture);
			TranslucencyPassResources.DepthTexture = FRDGTextureMSAA();
		}
	}
}
void FDeferredShadingSceneRenderer::RenderTranslucencyInner(
	FRDGBuilder& GraphBuilder,
	const FMinimalSceneTextures& SceneTextures,
	const FTranslucencyLightingVolumeTextures& TranslucentLightingVolumeTextures,
	FTranslucencyPassResourcesMap* OutTranslucencyResourceMap,
	FRDGTextureMSAA SharedDepthTexture,
	ETranslucencyView ViewsToRender,
	FRDGTextureRef SceneColorCopyTexture,
	ETranslucencyPass::Type TranslucencyPass,
	FInstanceCullingManager& InstanceCullingManager)
{
	if (!ShouldRenderTranslucency(TranslucencyPass))
	{
		return;
	}

	RDG_WAIT_FOR_TASKS_CONDITIONAL(GraphBuilder, IsTranslucencyWaitForTasksEnabled());

	const bool bIsModulate = TranslucencyPass == ETranslucencyPass::TPT_TranslucencyAfterDOFModulate;
	const bool bDepthTest = TranslucencyPass != ETranslucencyPass::TPT_TranslucencyAfterMotionBlur;
	const bool bRenderInParallel = IsParallelTranslucencyEnabled();
	const bool bIsScalingTranslucency = SeparateTranslucencyDimensions.Scale < 1.0f;
	const bool bRenderInSeparateTranslucency = IsSeparateTranslucencyEnabled(TranslucencyPass, SeparateTranslucencyDimensions.Scale);

	// Can't reference scene color in scene textures. Scene color copy is used instead.
	ESceneTextureSetupMode SceneTextureSetupMode = ESceneTextureSetupMode::All;
	EnumRemoveFlags(SceneTextureSetupMode, ESceneTextureSetupMode::SceneColor);

	if (bRenderInSeparateTranslucency)
	{
		// Create resources shared by each view (each view data is tiled into each of the render target resources)
		FRDGTextureMSAA SharedColorTexture = CreatePostDOFTranslucentTexture(GraphBuilder, TranslucencyPass, SeparateTranslucencyDimensions, bIsModulate, ShaderPlatform);

		for (int32 ViewIndex = 0, NumProcessedViews = 0; ViewIndex < Views.Num(); ++ViewIndex)
		{
			FViewInfo& View = Views[ViewIndex];
			const ETranslucencyView TranslucencyView = GetTranslucencyView(View);

			if (!EnumHasAnyFlags(TranslucencyView, ViewsToRender))
			{
				continue;
			}

			RDG_GPU_MASK_SCOPE(GraphBuilder, View.GPUMask);
			RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Views.Num() > 1, "View%d", ViewIndex);

			FIntRect ScaledViewRect = GetScaledRect(View.ViewRect, SeparateTranslucencyDimensions.Scale);

			const FScreenPassTextureViewport SeparateTranslucencyViewport = SeparateTranslucencyDimensions.GetInstancedStereoViewport(View);
			const bool bCompositeBackToSceneColor = IsMainTranslucencyPass(TranslucencyPass) || EnumHasAnyFlags(TranslucencyView, ETranslucencyView::UnderWater);
			const bool bLumenGIEnabled = GetViewPipelineState(View).DiffuseIndirectMethod == EDiffuseIndirectMethod::Lumen;

			/** Separate translucency color is either composited immediately or later during post processing. If done immediately, it's because the view doesn't support
			 *  compositing (e.g. we're rendering an underwater view) or because we're downsampling the main translucency pass. In this case, we use a local set of
			 *  textures instead of the external ones passed in.
			 */
			FRDGTextureMSAA SeparateTranslucencyColorTexture = SharedColorTexture;

			// NOTE: No depth test on post-motionblur translucency
			FRDGTextureMSAA SeparateTranslucencyDepthTexture;
			if (bDepthTest)
			{
				SeparateTranslucencyDepthTexture = SharedDepthTexture;
			}

			const ERenderTargetLoadAction SeparateTranslucencyColorLoadAction = NumProcessedViews == 0 || View.Family->bMultiGPUForkAndJoin
				? ERenderTargetLoadAction::EClear
				: ERenderTargetLoadAction::ELoad;

			FOITData OITData = OIT::CreateOITData(GraphBuilder, View, OITPass_SeperateTranslucency);

			RenderTranslucencyViewInner(
				GraphBuilder,
				*this,
				View,
				SeparateTranslucencyViewport,
				SeparateTranslucencyDimensions.Scale,
				SeparateTranslucencyColorTexture,
				SeparateTranslucencyColorLoadAction,
				SeparateTranslucencyDepthTexture.Target,
				CreateTranslucentBasePassUniformBuffer(GraphBuilder, Scene, View, ViewIndex, TranslucentLightingVolumeTextures, SceneColorCopyTexture, SceneTextureSetupMode, bLumenGIEnabled, OITData),
				TranslucencyPass,
				!bCompositeBackToSceneColor,
				bRenderInParallel,
				InstanceCullingManager);

			{
				FTranslucencyPassResources& TranslucencyPassResources = OutTranslucencyResourceMap->Get(ViewIndex, TranslucencyPass);
				TranslucencyPassResources.ViewRect = ScaledViewRect;
				TranslucencyPassResources.ColorTexture = SharedColorTexture;
				TranslucencyPassResources.DepthTexture = SharedDepthTexture;
			}

			if (OITData.PassType & OITPass_SeperateTranslucency)
			{
				OIT::AddOITComposePass(GraphBuilder, View, OITData, SeparateTranslucencyColorTexture.Target);
			}

			if (bCompositeBackToSceneColor)
			{
				FRDGTextureRef SeparateTranslucencyDepthResolve = nullptr;
				FRDGTextureRef SceneDepthResolve = nullptr;
				if (TranslucencyPass != ETranslucencyPass::TPT_TranslucencyAfterMotionBlur)
				{
					::AddResolveSceneDepthPass(GraphBuilder, View, SeparateTranslucencyDepthTexture);

					SeparateTranslucencyDepthResolve = SeparateTranslucencyDepthTexture.Resolve;
					SceneDepthResolve = SceneTextures.Depth.Resolve;
				}

				FTranslucencyPassResources& TranslucencyPassResources = OutTranslucencyResourceMap->Get(ViewIndex, TranslucencyPass);

				FTranslucencyComposition TranslucencyComposition;
				TranslucencyComposition.Operation = FTranslucencyComposition::EOperation::ComposeToExistingSceneColor;
				TranslucencyComposition.SceneColor = FScreenPassTexture(SceneTextures.Color.Target, View.ViewRect);
				TranslucencyComposition.SceneDepth = FScreenPassTexture(SceneTextures.Depth.Resolve, View.ViewRect);
				TranslucencyComposition.OutputViewport = FScreenPassTextureViewport(SceneTextures.Depth.Resolve, View.ViewRect);

				FScreenPassTexture UpscaledTranslucency = TranslucencyComposition.AddPass(
					GraphBuilder, View, TranslucencyPassResources);

				ensure(View.ViewRect == UpscaledTranslucency.ViewRect);
				ensure(UpscaledTranslucency.Texture == SceneTextures.Color.Target);

				//Invalidate.
				TranslucencyPassResources = FTranslucencyPassResources();
				TranslucencyPassResources.Pass = TranslucencyPass;
			}
			else
			{
				if (TranslucencyPass == ETranslucencyPass::TPT_TranslucencyAfterDOFModulate)
				{
					FTranslucencyPassResources& TranslucencyPassResources = OutTranslucencyResourceMap->Get(ViewIndex, ETranslucencyPass::TPT_TranslucencyAfterDOF);
					ensure(TranslucencyPassResources.ViewRect == ScaledViewRect);
					ensure(TranslucencyPassResources.DepthTexture == SharedDepthTexture);
					TranslucencyPassResources.ColorModulateTexture = SharedColorTexture;
				}
				else
				{
					check(!bIsModulate);
				}
			}

			++NumProcessedViews;
		}
	}
	else
	{
		for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
		{
			FViewInfo& View = Views[ViewIndex];
			const ETranslucencyView TranslucencyView = GetTranslucencyView(View);

			if (!EnumHasAnyFlags(TranslucencyView, ViewsToRender))
			{
				continue;
			}

			RDG_GPU_MASK_SCOPE(GraphBuilder, View.GPUMask);
			RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Views.Num() > 1, "View%d", ViewIndex);

			const ERenderTargetLoadAction SceneColorLoadAction = ERenderTargetLoadAction::ELoad;
			const FScreenPassTextureViewport Viewport(SceneTextures.Color.Target, View.ViewRect);
			const float ViewportScale = 1.0f;
			const bool bResolveColorTexture = false;
			const bool bLumenGIEnabled = GetViewPipelineState(View).DiffuseIndirectMethod == EDiffuseIndirectMethod::Lumen;

			FOITData OITData = OIT::CreateOITData(GraphBuilder, View, OITPass_RegularTranslucency);

			RenderTranslucencyViewInner(
				GraphBuilder,
				*this,
				View,
				Viewport,
				ViewportScale,
				SceneTextures.Color,
				SceneColorLoadAction,
				SceneTextures.Depth.Target,
				CreateTranslucentBasePassUniformBuffer(GraphBuilder, Scene, View, ViewIndex, TranslucentLightingVolumeTextures, SceneColorCopyTexture, SceneTextureSetupMode, bLumenGIEnabled, OITData),
				TranslucencyPass,
				bResolveColorTexture,
				bRenderInParallel,
				InstanceCullingManager);

			if (OITData.PassType & OITPass_RegularTranslucency)
			{
				OIT::AddOITComposePass(GraphBuilder, View, OITData, SceneTextures.Color.Target);
			}
		}
	}
}

TRDGUniformBufferRef<FTranslucentBasePassUniformParameters> CreateTranslucentBasePassUniformBuffer(
	FRDGBuilder& GraphBuilder,
	const FScene* Scene,
	const FViewInfo& View,
	const int32 ViewIndex,
	const FTranslucencyLightingVolumeTextures& TranslucencyLightingVolumeTextures,
	FRDGTextureRef SceneColorCopyTexture,
	const ESceneTextureSetupMode SceneTextureSetupMode,
	bool bLumenGIEnabled,
	const FOITData& OITData)
{
	FTranslucentBasePassUniformParameters& BasePassParameters = *GraphBuilder.AllocParameters<FTranslucentBasePassUniformParameters>();

	const auto GetRDG = [&](const TRefCountPtr<IPooledRenderTarget>& PooledRenderTarget, ERDGTextureFlags Flags = ERDGTextureFlags::None)
	{
		return GraphBuilder.RegisterExternalTexture(PooledRenderTarget, Flags);
	};

	SetupSharedBasePassParameters(GraphBuilder, View, bLumenGIEnabled, BasePassParameters.Shared);
	SetupSceneTextureUniformParameters(GraphBuilder, View.GetSceneTexturesChecked(), View.FeatureLevel, SceneTextureSetupMode, BasePassParameters.SceneTextures);
	Strata::BindStrataForwardPasslUniformParameters(GraphBuilder, View, BasePassParameters.Strata);

	const FLightSceneProxy* SelectedForwardDirectionalLightProxy = View.ForwardLightingResources.SelectedForwardDirectionalLightProxy;
	SetupLightCloudTransmittanceParameters(GraphBuilder, Scene, View, SelectedForwardDirectionalLightProxy ? SelectedForwardDirectionalLightProxy->GetLightSceneInfo() : nullptr, BasePassParameters.ForwardDirLightCloudShadow);

	const FRDGSystemTextures& SystemTextures = FRDGSystemTextures::Get(GraphBuilder);

	// Material SSR
	{
		float PrevSceneColorPreExposureInvValue = 1.0f / View.PreExposure;

		if (View.HZB)
		{
			BasePassParameters.HZBTexture = View.HZB;
			BasePassParameters.HZBSampler = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();

			FRDGTextureRef PrevSceneColorTexture = SystemTextures.Black;
			FIntRect PrevSceneColorViewRect = FIntRect(0, 0, 1, 1);

			if (View.PrevViewInfo.CustomSSRInput.IsValid())
			{
				PrevSceneColorTexture = GetRDG(View.PrevViewInfo.CustomSSRInput.RT[0]);
				PrevSceneColorViewRect = View.PrevViewInfo.CustomSSRInput.ViewportRect;
				PrevSceneColorPreExposureInvValue = 1.0f / View.PrevViewInfo.SceneColorPreExposure;
			}
			else if (View.PrevViewInfo.TemporalAAHistory.IsValid())
			{
				PrevSceneColorTexture = GetRDG(View.PrevViewInfo.TemporalAAHistory.RT[0]);
				PrevSceneColorViewRect = View.PrevViewInfo.TemporalAAHistory.ViewportRect;
				PrevSceneColorPreExposureInvValue = 1.0f / View.PrevViewInfo.SceneColorPreExposure;
			}
			else if (View.PrevViewInfo.ScreenSpaceRayTracingInput.IsValid())
			{
				PrevSceneColorTexture = GetRDG(View.PrevViewInfo.ScreenSpaceRayTracingInput);
				PrevSceneColorViewRect = View.PrevViewInfo.ViewRect;
				PrevSceneColorPreExposureInvValue = 1.0f / View.PrevViewInfo.SceneColorPreExposure;
			}

			BasePassParameters.PrevSceneColor = PrevSceneColorTexture;
			BasePassParameters.PrevSceneColorSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();

			FScreenPassTextureViewportParameters PrevSceneColorParameters = GetScreenPassTextureViewportParameters(FScreenPassTextureViewport(PrevSceneColorTexture, PrevSceneColorViewRect));
			BasePassParameters.PrevSceneColorBilinearUVMin = PrevSceneColorParameters.UVViewportBilinearMin;
			BasePassParameters.PrevSceneColorBilinearUVMax = PrevSceneColorParameters.UVViewportBilinearMax;

			const FVector2f HZBUvFactor(
				float(View.ViewRect.Width()) / float(2 * View.HZBMipmap0Size.X),
				float(View.ViewRect.Height()) / float(2 * View.HZBMipmap0Size.Y)
			);
			const FVector4f HZBUvFactorAndInvFactorValue(
				HZBUvFactor.X,
				HZBUvFactor.Y,
				1.0f / HZBUvFactor.X,
				1.0f / HZBUvFactor.Y
			);

			BasePassParameters.HZBUvFactorAndInvFactor = HZBUvFactorAndInvFactorValue;
		}
		else
		{
			BasePassParameters.HZBTexture = SystemTextures.Black;
			BasePassParameters.HZBSampler = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
			BasePassParameters.PrevSceneColor = SystemTextures.Black;
			BasePassParameters.PrevSceneColorSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
			BasePassParameters.PrevSceneColorBilinearUVMin = FVector2f(0.0f, 0.0f);
			BasePassParameters.PrevSceneColorBilinearUVMax = FVector2f(1.0f, 1.0f);
		}

		BasePassParameters.ApplyVolumetricCloudOnTransparent = 0.0f;
		BasePassParameters.VolumetricCloudColor = nullptr;
		BasePassParameters.VolumetricCloudDepth = nullptr;
		BasePassParameters.VolumetricCloudColorSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
		BasePassParameters.VolumetricCloudDepthSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
		if (IsVolumetricRenderTargetEnabled() && View.ViewState)
		{
			TRefCountPtr<IPooledRenderTarget> VolumetricReconstructRT = View.ViewState->VolumetricCloudRenderTarget.GetDstVolumetricReconstructRT();
			if (VolumetricReconstructRT.IsValid())
			{
				TRefCountPtr<IPooledRenderTarget> VolumetricReconstructRTDepth = View.ViewState->VolumetricCloudRenderTarget.GetDstVolumetricReconstructRTDepth();

				BasePassParameters.VolumetricCloudColor = VolumetricReconstructRT->GetRHI();
				BasePassParameters.VolumetricCloudDepth = VolumetricReconstructRTDepth->GetRHI();
				BasePassParameters.ApplyVolumetricCloudOnTransparent = 1.0f;
			}
		}
		if (BasePassParameters.VolumetricCloudColor == nullptr)
		{
			BasePassParameters.VolumetricCloudColor = GSystemTextures.BlackAlphaOneDummy->GetRHI();
			BasePassParameters.VolumetricCloudDepth = GSystemTextures.BlackDummy->GetRHI();
		}

		FIntPoint ViewportOffset = View.ViewRect.Min;
		FIntPoint ViewportExtent = View.ViewRect.Size();

		// Scene render targets might not exist yet; avoids NaNs.
		FIntPoint EffectiveBufferSize = View.GetSceneTexturesConfig().Extent;
		EffectiveBufferSize.X = FMath::Max(EffectiveBufferSize.X, 1);
		EffectiveBufferSize.Y = FMath::Max(EffectiveBufferSize.Y, 1);

		if (View.PrevViewInfo.CustomSSRInput.IsValid())
		{
			ViewportOffset = View.PrevViewInfo.CustomSSRInput.ViewportRect.Min;
			ViewportExtent = View.PrevViewInfo.CustomSSRInput.ViewportRect.Size();
			EffectiveBufferSize = View.PrevViewInfo.CustomSSRInput.RT[0]->GetDesc().Extent;
		}
		else if (View.PrevViewInfo.TemporalAAHistory.IsValid())
		{
			ViewportOffset = View.PrevViewInfo.TemporalAAHistory.ViewportRect.Min;
			ViewportExtent = View.PrevViewInfo.TemporalAAHistory.ViewportRect.Size();
			EffectiveBufferSize = View.PrevViewInfo.TemporalAAHistory.RT[0]->GetDesc().Extent;
		}
		else if (View.PrevViewInfo.ScreenSpaceRayTracingInput.IsValid())
		{
			ViewportOffset = View.PrevViewInfo.ViewRect.Min;
			ViewportExtent = View.PrevViewInfo.ViewRect.Size();
			EffectiveBufferSize = View.PrevViewInfo.ScreenSpaceRayTracingInput->GetDesc().Extent;
		}

		FVector2f InvBufferSize(1.0f / float(EffectiveBufferSize.X), 1.0f / float(EffectiveBufferSize.Y));

		FVector4f ScreenPosToPixelValue(
			ViewportExtent.X * 0.5f * InvBufferSize.X,
			-ViewportExtent.Y * 0.5f * InvBufferSize.Y,
			(ViewportExtent.X * 0.5f + ViewportOffset.X) * InvBufferSize.X,
			(ViewportExtent.Y * 0.5f + ViewportOffset.Y) * InvBufferSize.Y);

		BasePassParameters.PrevScreenPositionScaleBias = ScreenPosToPixelValue;
		BasePassParameters.PrevSceneColorPreExposureInv = PrevSceneColorPreExposureInvValue;
		BasePassParameters.SSRQuality = ShouldRenderTranslucencyScreenSpaceReflections(View) ? GetSSRQuality() : 0;
	}

	// Translucency Lighting Volume
	BasePassParameters.TranslucencyLightingVolume = GetTranslucencyLightingVolumeParameters(GraphBuilder, TranslucencyLightingVolumeTextures, View);
	BasePassParameters.LumenParameters = GetLumenTranslucencyLightingParameters(GraphBuilder, View.LumenTranslucencyGIVolume, View.LumenFrontLayerTranslucency);

	const bool bLumenGIHandlingSkylight = bLumenGIEnabled
		&& BasePassParameters.LumenParameters.TranslucencyGIGridSize.Z > 0;

	BasePassParameters.Shared.UseBasePassSkylight = bLumenGIHandlingSkylight ? 0 : 1;

	BasePassParameters.SceneColorCopyTexture = SystemTextures.Black;
	BasePassParameters.SceneColorCopySampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();

	if (SceneColorCopyTexture)
	{
		BasePassParameters.SceneColorCopyTexture = SceneColorCopyTexture;
	}

	BasePassParameters.EyeAdaptationTexture = GetEyeAdaptationTexture(GraphBuilder, View);
	BasePassParameters.PreIntegratedGFTexture = GSystemTextures.PreintegratedGF->GetRHI();
	BasePassParameters.PreIntegratedGFSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();

	OIT::SetOITParameters(GraphBuilder, View, BasePassParameters.OIT, OITData);

	return GraphBuilder.CreateUniformBuffer(&BasePassParameters);
}
static void RenderTranslucencyViewInner(
	FRDGBuilder& GraphBuilder,
	const FSceneRenderer& SceneRenderer,
	FViewInfo& View,
	FScreenPassTextureViewport Viewport,
	float ViewportScale,
	FRDGTextureMSAA SceneColorTexture,
	ERenderTargetLoadAction SceneColorLoadAction,
	FRDGTextureRef SceneDepthTexture,
	TRDGUniformBufferRef<FTranslucentBasePassUniformParameters> BasePassParameters,
	ETranslucencyPass::Type TranslucencyPass,
	bool bResolveColorTexture,
	bool bRenderInParallel,
	FInstanceCullingManager& InstanceCullingManager)
{
	if (!View.ShouldRenderView())
	{
		return;
	}

	if (SceneColorLoadAction == ERenderTargetLoadAction::EClear)
	{
		AddClearRenderTargetPass(GraphBuilder, SceneColorTexture.Target);
	}

	View.BeginRenderView();

	FTranslucentBasePassParameters* PassParameters = GraphBuilder.AllocParameters<FTranslucentBasePassParameters>();
	PassParameters->View = GetSeparateTranslucencyViewParameters(View, Viewport.Extent, ViewportScale, TranslucencyPass);
	PassParameters->ReflectionCapture = View.ReflectionCaptureUniformBuffer;
	PassParameters->BasePass = BasePassParameters;
	PassParameters->VirtualShadowMapSamplingParameters = SceneRenderer.VirtualShadowMapArray.GetSamplingParameters(GraphBuilder);
	PassParameters->RenderTargets[0] = FRenderTargetBinding(SceneColorTexture.Target, ERenderTargetLoadAction::ELoad);
	if (TranslucencyPass != ETranslucencyPass::TPT_TranslucencyAfterMotionBlur)
	{
		PassParameters->RenderTargets.DepthStencil = FDepthStencilBinding(SceneDepthTexture, ERenderTargetLoadAction::ELoad, ERenderTargetLoadAction::ELoad, FExclusiveDepthStencil::DepthRead_StencilWrite);
	}
	PassParameters->RenderTargets.ShadingRateTexture = GVRSImageManager.GetVariableRateShadingImage(GraphBuilder, SceneRenderer.ViewFamily, nullptr);
	PassParameters->RenderTargets.ResolveRect = FResolveRect(Viewport.Rect);

	const EMeshPass::Type MeshPass = TranslucencyPassToMeshPass(TranslucencyPass);
	View.ParallelMeshDrawCommandPasses[MeshPass].BuildRenderingCommands(GraphBuilder, SceneRenderer.Scene->GPUScene, PassParameters->InstanceCullingDrawParams);

	if (bRenderInParallel)
	{
		GraphBuilder.AddPass(
			RDG_EVENT_NAME("Translucency(%s Parallel) %dx%d",
				TranslucencyPassToString(TranslucencyPass),
				int32(View.ViewRect.Width() * ViewportScale),
				int32(View.ViewRect.Height() * ViewportScale)),
			PassParameters,
			ERDGPassFlags::Raster | ERDGPassFlags::SkipRenderPass,
			[&SceneRenderer, &View, PassParameters, ViewportScale, Viewport, TranslucencyPass](const FRDGPass* InPass, FRHICommandListImmediate& RHICmdList)
		{
			FRDGParallelCommandListSet ParallelCommandListSet(InPass, RHICmdList, GET_STATID(STAT_CLP_Translucency), SceneRenderer, View, FParallelCommandListBindings(PassParameters), ViewportScale);
			RenderViewTranslucencyInner(RHICmdList, SceneRenderer, View, Viewport, ViewportScale, TranslucencyPass, &ParallelCommandListSet, PassParameters->InstanceCullingDrawParams);
		});
	}
	else
	{
		GraphBuilder.AddPass(
			RDG_EVENT_NAME("Translucency(%s) %dx%d",
				TranslucencyPassToString(TranslucencyPass),
				int32(View.ViewRect.Width() * ViewportScale),
				int32(View.ViewRect.Height() * ViewportScale)),
			PassParameters,
			ERDGPassFlags::Raster,
			[&SceneRenderer, &View, ViewportScale, Viewport, TranslucencyPass, PassParameters](FRHICommandList& RHICmdList)
		{
			RenderViewTranslucencyInner(RHICmdList, SceneRenderer, View, Viewport, ViewportScale, TranslucencyPass, nullptr, PassParameters->InstanceCullingDrawParams);
		});
	}

	if (bResolveColorTexture)
	{
		AddResolveSceneColorPass(GraphBuilder, View, SceneColorTexture);
	}
}



static void RenderViewTranslucencyInner(
	FRHICommandList& RHICmdList,
	const FSceneRenderer& SceneRenderer,
	const FViewInfo& View,
	const FScreenPassTextureViewport Viewport,
	const float ViewportScale,
	ETranslucencyPass::Type TranslucencyPass,
	FRDGParallelCommandListSet* ParallelCommandListSet,
	const FInstanceCullingDrawParams& InstanceCullingDrawParams)
{
	FMeshPassProcessorRenderState DrawRenderState;
	if (TranslucencyPass == ETranslucencyPass::TPT_TranslucencyAfterMotionBlur)
	{
		// No depth test in post-motionblur translucency
		DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
	}
	else
	{
		DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI());
	}
	
	SceneRenderer.SetStereoViewport(RHICmdList, View, ViewportScale);

	if (!View.Family->UseDebugViewPS())
	{
		QUICK_SCOPE_CYCLE_COUNTER(RenderTranslucencyParallel_Start_FDrawSortedTransAnyThreadTask);

		const EMeshPass::Type MeshPass = TranslucencyPassToMeshPass(TranslucencyPass);
		View.ParallelMeshDrawCommandPasses[MeshPass].DispatchDraw(ParallelCommandListSet, RHICmdList, &InstanceCullingDrawParams);
	}

}
void FParallelMeshDrawCommandPass::DispatchDraw(FParallelCommandListSet* ParallelCommandListSet, FRHICommandList& RHICmdList, const FInstanceCullingDrawParams* InstanceCullingDrawParams) const
{
	TRACE_CPUPROFILER_EVENT_SCOPE(ParallelMdcDispatchDraw);
	if (MaxNumDraws <= 0)
	{
		return;
	}

	FMeshDrawCommandOverrideArgs OverrideArgs; 
	if (InstanceCullingDrawParams)
	{
		OverrideArgs = GetMeshDrawCommandOverrideArgs(*InstanceCullingDrawParams);
	}

	if (ParallelCommandListSet)
	{
		const ENamedThreads::Type RenderThread = ENamedThreads::GetRenderThread();

		FGraphEventArray Prereqs;
		if (ParallelCommandListSet->GetPrereqs())
		{
			Prereqs.Append(*ParallelCommandListSet->GetPrereqs());
		}
		if (TaskEventRef.IsValid())
		{
			Prereqs.Add(TaskEventRef);
		}

		// Distribute work evenly to the available task graph workers based on NumEstimatedDraws.
		// Every task will then adjust it's working range based on FVisibleMeshDrawCommandProcessTask results.
		const int32 NumThreads = FMath::Min<int32>(FTaskGraphInterface::Get().GetNumWorkerThreads(), ParallelCommandListSet->Width);
		const int32 NumTasks = FMath::Min<int32>(NumThreads, FMath::DivideAndRoundUp(MaxNumDraws, ParallelCommandListSet->MinDrawsPerCommandList));
		const int32 NumDrawsPerTask = FMath::DivideAndRoundUp(MaxNumDraws, NumTasks);

		for (int32 TaskIndex = 0; TaskIndex < NumTasks; TaskIndex++)
		{
			const int32 StartIndex = TaskIndex * NumDrawsPerTask;
			const int32 NumDraws = FMath::Min(NumDrawsPerTask, MaxNumDraws - StartIndex);
			checkSlow(NumDraws > 0);

			FRHICommandList* CmdList = ParallelCommandListSet->NewParallelCommandList();

			FGraphEventRef AnyThreadCompletionEvent = TGraphTask<FDrawVisibleMeshCommandsAnyThreadTask>::CreateTask(&Prereqs, RenderThread)
				.ConstructAndDispatchWhenReady(*CmdList, TaskContext.InstanceCullingContext, TaskContext.MeshDrawCommands, TaskContext.MinimalPipelineStatePassSet,
					OverrideArgs,
					TaskContext.InstanceFactor,
					TaskIndex, NumTasks);

			ParallelCommandListSet->AddParallelCommandList(CmdList, AnyThreadCompletionEvent, NumDraws);
		}
	}
	else
	{
		QUICK_SCOPE_CYCLE_COUNTER(STAT_MeshPassDrawImmediate);

		WaitForMeshPassSetupTask(IsInActualRenderingThread() ? EWaitThread::Render : EWaitThread::Task);

		if (TaskContext.bUseGPUScene)
		{
			if (TaskContext.MeshDrawCommands.Num() > 0)
			{
				TaskContext.InstanceCullingContext.SubmitDrawCommands(
					TaskContext.MeshDrawCommands,
					TaskContext.MinimalPipelineStatePassSet,
					OverrideArgs,
					0,
					TaskContext.MeshDrawCommands.Num(),
					TaskContext.InstanceFactor,
					RHICmdList);
			}
		}
		else
		{
			SubmitMeshDrawCommandsRange(TaskContext.MeshDrawCommands, TaskContext.MinimalPipelineStatePassSet, nullptr, 0, 0, TaskContext.bDynamicInstancing, 0, TaskContext.MeshDrawCommands.Num(), TaskContext.InstanceFactor, RHICmdList);
		}
	}
}

  Shader Code

void FPixelShaderInOut_MainPS(
	FVertexFactoryInterpolantsVSToPS Interpolants,
	FSharedBasePassInterpolants  BasePassInterpolants,
	in FPixelShaderIn In,
	inout FPixelShaderOut Out)
{

	const uint EyeIndex = 0;
	ResolvedView = ResolveView();

	float4 OutVelocity = 0;

	float4 OutGBufferD = 0;

	float4 OutGBufferE = 0;

	FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(Interpolants, In.SvPosition);
	FPixelMaterialInputs PixelMaterialInputs;

	float  LightmapVTPageTableResult = ( float )0.0f;

	{
		CalcMaterialParameters(MaterialParameters, PixelMaterialInputs, In.SvPosition, In.bIsFrontFace);
	}

	const bool bEditorWeightedZBuffering = false;

	if (!bEditorWeightedZBuffering)
	{

		GetMaterialCoverageAndClipping(MaterialParameters, PixelMaterialInputs);

	}


	const float Dither = InterleavedGradientNoise(MaterialParameters.SvPosition.xy, View_StateFrameIndexMod8);

	float3  BaseColor = GetMaterialBaseColor(PixelMaterialInputs);
	float  Metallic = GetMaterialMetallic(PixelMaterialInputs);
	float  Specular = GetMaterialSpecular(PixelMaterialInputs);

	float Roughness = GetMaterialRoughness(PixelMaterialInputs);
	float Anisotropy = GetMaterialAnisotropy(PixelMaterialInputs);
	uint ShadingModel = GetMaterialShadingModel(PixelMaterialInputs);
	float  Opacity = GetMaterialOpacity(PixelMaterialInputs);

	float MaterialAO = GetMaterialAmbientOcclusion(PixelMaterialInputs);

	float3 SubsurfaceColor = 0;

	float SubsurfaceProfile = 0;

	float DBufferOpacity = 1.0f;

	const float BaseMaterialCoverageOverWater = Opacity;
	const float WaterVisibility = 1.0 - BaseMaterialCoverageOverWater;

	float3 VolumetricLightmapBrickTextureUVs;

	FGBufferData GBuffer = (FGBufferData)0;

	GBuffer.GBufferAO = MaterialAO;
	GBuffer.PerObjectGBufferData = GetPrimitive_PerObjectGBufferData(MaterialParameters.PrimitiveId);
	GBuffer.Depth = MaterialParameters.ScreenPosition.w;
	GBuffer.PrecomputedShadowFactors = GetPrecomputedShadowMasks(LightmapVTPageTableResult, Interpolants, MaterialParameters, VolumetricLightmapBrickTextureUVs);

	SetGBufferForShadingModel(
		GBuffer,
		MaterialParameters,
		Opacity,
		BaseColor,
		Metallic,
		Specular,
		Roughness,
		Anisotropy,
		SubsurfaceColor,
		SubsurfaceProfile,
		Dither,
		ShadingModel
		);

	const bool bChecker = CheckerFromPixelPos(MaterialParameters.SvPosition.xy);

	if(GBuffer.ShadingModelID ==  12 )
	{
		float3 FinalDiffuseColor = GBuffer.BaseColor;
	}


	if(GBuffer.ShadingModelID ==  12 )
	{

		GBuffer.SpecularColor = SubsurfaceColor;
	}
	else
	{
		GBuffer.SpecularColor = ComputeF0(Specular, BaseColor, Metallic);
	}


	if(GBuffer.ShadingModelID ==  12 )
	{
		GBuffer.DiffuseColor = BaseColor;
	}
	else
	{
		GBuffer.DiffuseColor = BaseColor - BaseColor * Metallic;
	}


	{

		GBuffer.DiffuseColor = GBuffer.DiffuseColor * View_DiffuseOverrideParameter.w + View_DiffuseOverrideParameter.xyz;
		GBuffer.SpecularColor = GBuffer.SpecularColor * View_SpecularOverrideParameter.w + View_SpecularOverrideParameter.xyz;
	}



	if (View_RenderingReflectionCaptureMask)

	{
		EnvBRDFApproxFullyRough(GBuffer.DiffuseColor, GBuffer.SpecularColor);

	}

	float3 InputBentNormal = MaterialParameters.WorldNormal;


	[branch]  if( GBuffer.ShadingModelID ==  4  &&  0 )
	{
		const float2 oct1 = ((float2(GBuffer.CustomData.a, GBuffer.CustomData.z) * 4) - (512.0/255.0)) + UnitVectorToOctahedron(GBuffer.WorldNormal);
		InputBentNormal = OctahedronToUnitVector(oct1);
	}

	const FShadingOcclusion ShadingOcclusion = ApplyBentNormal(MaterialParameters.CameraVector, InputBentNormal, GetWorldBentNormalZero(MaterialParameters), GBuffer.Roughness, MaterialAO);


	GBuffer.GBufferAO = AOMultiBounce( Luminance( GBuffer.SpecularColor ), ShadingOcclusion.SpecOcclusion ).g;

	GBuffer.DiffuseIndirectSampleOcclusion = GetDiffuseIndirectSampleOcclusion(GBuffer, MaterialParameters.CameraVector, MaterialParameters.WorldNormal, GetWorldBentNormalZero(MaterialParameters), In.SvPosition.xy, MaterialAO);

	float3  DiffuseColor = 0;
	float3  Color = 0;
	float IndirectIrradiance = 0;

	float3  ColorSeparateSpecular = 0;
	float3  ColorSeparateEmissive = 0;

	float3 DiffuseIndirectLighting = 0;
	float3 SubsurfaceIndirectLighting = 0;

	bool bSeparateWaterMainDirLightLuminance =  ( 0 )  > 0 && View_SeparateWaterMainDirLightLuminance > 0.0f;
	float3 SeparatedWaterMainDirLightLuminance = float3(0, 0, 0);

		float3 DiffuseDir = ShadingOcclusion.BentNormal;
		float3 DiffuseColorForIndirect = GBuffer.DiffuseColor;

		const bool bEvaluateBackface = GetShadingModelRequiresBackfaceLighting(GBuffer.ShadingModelID);
		GetPrecomputedIndirectLightingAndSkyLight(MaterialParameters, Interpolants, BasePassInterpolants, LightmapVTPageTableResult, bEvaluateBackface, DiffuseDir, VolumetricLightmapBrickTextureUVs, DiffuseIndirectLighting, SubsurfaceIndirectLighting, IndirectIrradiance);

		float IndirectOcclusion = 1.0f;
		float2 NearestResolvedDepthScreenUV = 0;
		float DirectionalLightShadow = 1.0f;
		float DirectionalLightCloudShadow = 1.0f;

		DiffuseColor += (DiffuseIndirectLighting * DiffuseColorForIndirect + SubsurfaceIndirectLighting * SubsurfaceColor) * AOMultiBounce( GBuffer.BaseColor, ShadingOcclusion.DiffOcclusion );

		float4 HeightFogging = BasePassInterpolants.VertexFog;

	float4 Fogging = HeightFogging;


	if ( TranslucentBasePass_Shared_Fog_ApplyVolumetricFog  > 0)
	{
		float3 VolumeUV = ComputeVolumeUV(MaterialParameters.AbsoluteWorldPosition, ResolvedView.WorldToClip);
		Fogging = CombineVolumetricFog(HeightFogging, VolumeUV, EyeIndex, GBuffer.Depth);
	}


	float3  Emissive = 0;

	if (GBuffer.ShadingModelID ==  1  || GBuffer.ShadingModelID ==  2 )
	{
		Color += GetTranslucencyVolumeLighting(MaterialParameters, PixelMaterialInputs, BasePassInterpolants, GBuffer, IndirectIrradiance);
	}

		float3 GBufferDiffuseColor = GBuffer.DiffuseColor;
		float3 GBufferSpecularColor = GBuffer.SpecularColor;
		EnvBRDFApproxFullyRough(GBufferDiffuseColor, GBufferSpecularColor);
		Color = lerp(Color, GBufferDiffuseColor, View_UnlitViewmodeMask);


	Emissive = GetMaterialEmissive(PixelMaterialInputs);

	float3 OutOfBoundsMaskLuminance = 0;

		[branch]
		if (View_OutOfBoundsMask > 0)
		{
			FPrimitiveSceneData PrimitiveData = GetPrimitiveData(MaterialParameters);

			float3 ObjectBounds =
				float3(
					PrimitiveData.ObjectBoundsX,
					PrimitiveData.ObjectBoundsY,
					PrimitiveData.ObjectBoundsZ
				);

			if (any(abs(LWCToFloat(LWCSubtract(MaterialParameters.AbsoluteWorldPosition, PrimitiveData.ObjectWorldPosition))) > ObjectBounds + 1))
			{
				float Gradient = LWCFrac(LWCDivide(LWCDot(MaterialParameters.AbsoluteWorldPosition, float3(.577f, .577f, .577f)), 500.0f));
				OutOfBoundsMaskLuminance = lerp(float3(1,1,0), float3(0,1,1), Gradient.xxx > .5f);
				Emissive = OutOfBoundsMaskLuminance;
				Opacity = 1;
			}
		}

	Color += DiffuseColor;

	Color += Emissive;

	bool bStrataSubsurfaceEnable = false;

		Out.MRT[0] =  float4 (Color * Fogging.a + Fogging.rgb, Opacity);
		Out.MRT[0] =  ( Out.MRT[0] ) ;

			Out.MRT[1] = OutVelocity;

	if(bEditorWeightedZBuffering)
	{
		Out.MRT[0].a = 1;

			clip(Out.MRT[0].a - GetMaterialOpacityMaskClipValue());

	}


	const float ViewPreExposure = View_PreExposure;

		Out.MRT[0].rgb *= ViewPreExposure;

}
/** Calculates lighting for translucency. */
float3 GetTranslucencyVolumeLighting(
	FMaterialPixelParameters MaterialParameters, 
	FPixelMaterialInputs PixelMaterialInputs,
	FBasePassInterpolantsVSToPS BasePassInterpolants, 
	FGBufferData GBuffer, 
	float IndirectIrradiance)
{
	float4 VolumeLighting;
	float3 InterpolatedLighting = 0;

	float3 InnerVolumeUVs;
	float3 OuterVolumeUVs;
	float FinalLerpFactor;
	ComputeVolumeUVs(MaterialParameters.WorldPosition_CamRelative, MaterialParameters.LightingPositionOffset, InnerVolumeUVs, OuterVolumeUVs, FinalLerpFactor);

	#if TRANSLUCENCY_LIGHTING_VOLUMETRIC_PERVERTEX_DIRECTIONAL

		GetVolumeLightingDirectional(float4(BasePassInterpolants.AmbientLightingVector, 1), BasePassInterpolants.DirectionalLightingVector, MaterialParameters.WorldNormal, GBuffer.DiffuseColor, InterpolatedLighting, VolumeLighting);

	#elif TRANSLUCENCY_LIGHTING_VOLUMETRIC_PERVERTEX_NONDIRECTIONAL

		GetVolumeLightingNonDirectional(float4(BasePassInterpolants.AmbientLightingVector, 1), GBuffer.DiffuseColor, InterpolatedLighting, VolumeLighting);

	#elif TRANSLUCENCY_LIGHTING_VOLUMETRIC_DIRECTIONAL || TRANSLUCENCY_LIGHTING_SURFACE_LIGHTINGVOLUME
	
		float4 AmbientLightingVector = GetAmbientLightingVectorFromTranslucentLightingVolume(InnerVolumeUVs, OuterVolumeUVs, FinalLerpFactor);
		float3 DirectionalLightingVector = GetDirectionalLightingVectorFromTranslucentLightingVolume(InnerVolumeUVs, OuterVolumeUVs, FinalLerpFactor);
		GetVolumeLightingDirectional(AmbientLightingVector, DirectionalLightingVector, MaterialParameters.WorldNormal, GBuffer.DiffuseColor, InterpolatedLighting, VolumeLighting);

	#elif TRANSLUCENCY_LIGHTING_VOLUMETRIC_NONDIRECTIONAL

		float4 AmbientLightingVector = GetAmbientLightingVectorFromTranslucentLightingVolume(InnerVolumeUVs, OuterVolumeUVs, FinalLerpFactor);
		GetVolumeLightingNonDirectional(AmbientLightingVector, GBuffer.DiffuseColor, InterpolatedLighting, VolumeLighting);

	#endif

	return InterpolatedLighting;
}

void GetVolumeLightingNonDirectional(float4 AmbientLightingVector, float3 DiffuseColor, inout float3 InterpolatedLighting, out float4 VolumeLighting)
{
	// Normal is not taken into account with non directional lighting, and only the ambient term of the SH coefficients are needed
	FOneBandSHVectorRGB TranslucentLighting;
	TranslucentLighting.R.V.x = AmbientLightingVector.r;
	TranslucentLighting.G.V.x = AmbientLightingVector.g;
	TranslucentLighting.B.V.x = AmbientLightingVector.b;

	FOneBandSHVector DiffuseTransferSH = CalcDiffuseTransferSH1(1);
	VolumeLighting = float4(DotSH1(TranslucentLighting, DiffuseTransferSH), AmbientLightingVector.a);
	InterpolatedLighting = DiffuseColor * VolumeLighting.rgb;
}

FOneBandSHVector CalcDiffuseTransferSH1(half Exponent)
{
	FOneBandSHVector Result = SHBasisFunction1();

	// These formula are scaling factors for each SH band that convolve a SH with the circularly symmetric function
	// max(0,cos(theta))^Exponent
	half L0 =					2 * PI / (1 + 1 * Exponent							);

	// Multiply the coefficients in each band with the appropriate band scaling factor.
	Result.V *= L0;

	return Result;
}

FOneBandSHVector SHBasisFunction1()
{
	FOneBandSHVector Result;
	// These are derived from simplifying SHBasisFunction in C++
	Result.V = 0.282095f; 
	return Result;
}

float4 GetAmbientLightingVectorFromTranslucentLightingVolume(float3 InnerVolumeUVs, float3 OuterVolumeUVs, float FinalLerpFactor)
{
	// Lookup the inner and outer cascade ambient lighting values
	float4 InnerLighting = Texture3DSampleLevel(TranslucentBasePass.TranslucencyLightingVolumeAmbientInner, SharedAmbientInnerSampler, InnerVolumeUVs, 0);
	float4 OuterLighting = Texture3DSampleLevel(TranslucentBasePass.TranslucencyLightingVolumeAmbientOuter, SharedAmbientOuterSampler, OuterVolumeUVs, 0);

	// Lerp between cascades
	return lerp(OuterLighting, InnerLighting, FinalLerpFactor);
}

void GetPrecomputedIndirectLightingAndSkyLight(
	FMaterialPixelParameters MaterialParameters,
	FVertexFactoryInterpolantsVSToPS Interpolants,
	FSharedBasePassInterpolants  BasePassInterpolants,
	float  LightmapVTPageTableResult,
	bool bEvaluateBackface,
	float3 DiffuseDir,
	float3 VolumetricLightmapBrickTextureUVs,
	out float3 OutDiffuseLighting,
	out float3 OutSubsurfaceLighting,
	out float OutIndirectIrradiance)
{
	OutIndirectIrradiance = 0;
	OutDiffuseLighting = 0;
	OutSubsurfaceLighting = 0;
	float2  SkyOcclusionUV = ( float2 )0;
	uint SkyOcclusionDataIndex = 0u;

	OutDiffuseLighting *= View_PrecomputedIndirectLightingColorScale;
	OutSubsurfaceLighting *= View_PrecomputedIndirectLightingColorScale;

	float3 SkyDiffuseLighting;
	float3 SkySubsurfaceLighting;
	GetSkyLighting(MaterialParameters, LightmapVTPageTableResult, bEvaluateBackface, DiffuseDir, SkyOcclusionUV, SkyOcclusionDataIndex, VolumetricLightmapBrickTextureUVs, SkyDiffuseLighting, SkySubsurfaceLighting);

	OutSubsurfaceLighting += SkySubsurfaceLighting;
	OutDiffuseLighting += SkyDiffuseLighting;

}

void GetSkyLighting(FMaterialPixelParameters MaterialParameters,  float  LightmapVTPageTableResult, bool bEvaluateBackface, float3 WorldNormal,  float2  LightmapUV, uint LightmapDataIndex, float3 SkyOcclusionUV3D, out float3 OutDiffuseLighting, out float3 OutSubsurfaceLighting)
{
	OutDiffuseLighting = 0;
	OutSubsurfaceLighting = 0;


	if (IsLumenTranslucencyGIEnabled())
	{

		FTwoBandSHVectorRGB TranslucencyGISH = GetTranslucencyGIVolumeLighting(MaterialParameters.AbsoluteWorldPosition, ResolvedView.WorldToClip, true);

			FOneBandSHVectorRGB TranslucencyGISH1;
			TranslucencyGISH1.R.V = TranslucencyGISH.R.V.x;
			TranslucencyGISH1.G.V = TranslucencyGISH.G.V.x;
			TranslucencyGISH1.B.V = TranslucencyGISH.B.V.x;

			FOneBandSHVector DiffuseTransferSH = CalcDiffuseTransferSH1(1);
			OutDiffuseLighting += max(float3(0,0,0), DotSH1(TranslucencyGISH1, DiffuseTransferSH)) / PI;

	}
	
}

FTwoBandSHVectorRGB GetTranslucencyGIVolumeLighting(FLWCVector3 WorldPosition, FLWCInverseMatrix WorldToClip, bool bTemporalFiltered)
{
	float3 VolumeUV = ComputeTranslucencyGIVolumeUV(WorldPosition, WorldToClip);

	float3 AmbientLightingVector;
	float3 DirectionalLightingVector;

	if (bTemporalFiltered)
	{
		AmbientLightingVector = Texture3DSampleLevel( TranslucentBasePass_TranslucencyGIVolumeHistory0 ,  TranslucentBasePass_TranslucencyGIVolumeSampler , VolumeUV, 0).xyz;
		DirectionalLightingVector = Texture3DSampleLevel( TranslucentBasePass_TranslucencyGIVolumeHistory1 ,  TranslucentBasePass_TranslucencyGIVolumeSampler , VolumeUV, 0).xyz;
	}
	else
	{
		AmbientLightingVector = Texture3DSampleLevel( TranslucentBasePass_TranslucencyGIVolume0 ,  TranslucentBasePass_TranslucencyGIVolumeSampler , VolumeUV, 0).xyz;
		DirectionalLightingVector = Texture3DSampleLevel( TranslucentBasePass_TranslucencyGIVolume1 ,  TranslucentBasePass_TranslucencyGIVolumeSampler , VolumeUV, 0).xyz;
	}


	FTwoBandSHVectorRGB TranslucentLighting;
	TranslucentLighting.R.V.x = AmbientLightingVector.r;
	TranslucentLighting.G.V.x = AmbientLightingVector.g;
	TranslucentLighting.B.V.x = AmbientLightingVector.b;
	float3 NormalizedAmbientColor = AmbientLightingVector.rgb / ( Luminance( AmbientLightingVector.rgb ) + 0.00001f );


	TranslucentLighting.R.V.yzw = DirectionalLightingVector.rgb * NormalizedAmbientColor.r;
	TranslucentLighting.G.V.yzw = DirectionalLightingVector.rgb * NormalizedAmbientColor.g;
	TranslucentLighting.B.V.yzw = DirectionalLightingVector.rgb * NormalizedAmbientColor.b;
	return TranslucentLighting;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值