Files
UnrealEngineUWP/Engine/Source/Runtime/Renderer/Private/BasePassRendering.cpp
charles derousiers f499a215a2 Remove RenderLight from DeferredRendering, and change it to a standalone static/internal function to light rendering to ease its refactor to RDG.
#rb none
#jira none

#ROBOMERGE-AUTHOR: charles.derousiers
#ROBOMERGE-SOURCE: CL 18404002 in //UE5/Release-5.0/... via CL 18404004
#ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469)

[CL 18404006 by charles derousiers in ue5-release-engine-test branch]
2021-12-08 03:54:06 -05:00

2044 lines
83 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "BasePassRendering.h"
#include "DeferredShadingRenderer.h"
#include "DistortionRendering.h"
#include "DynamicPrimitiveDrawing.h"
#include "ScenePrivate.h"
#include "MeshPassProcessor.inl"
#include "EditorPrimitivesRendering.h"
#include "TranslucentRendering.h"
#include "SingleLayerWaterRendering.h"
#include "Rendering/SkyAtmosphereCommonData.h"
#include "SceneTextureParameters.h"
#include "CompositionLighting/CompositionLighting.h"
#include "CompositionLighting/PostProcessAmbientOcclusion.h"
#include "SceneViewExtension.h"
#include "VariableRateShadingImageManager.h"
#include "OneColorShader.h"
#include "ClearQuad.h"
#include "ProfilingDebugging/CpuProfilerTrace.h"
#include "DebugProbeRendering.h"
#include "AnisotropyRendering.h"
#include "Nanite/NaniteVisualize.h"
// Changing this causes a full shader recompile
static TAutoConsoleVariable<int32> CVarSelectiveBasePassOutputs(
TEXT("r.SelectiveBasePassOutputs"),
0,
TEXT("Enables shaders to only export to relevant rendertargets.\n") \
TEXT(" 0: Export in all rendertargets.\n") \
TEXT(" 1: Export only into relevant rendertarget.\n"),
ECVF_ReadOnly | ECVF_RenderThreadSafe);
// Changing this causes a full shader recompile
static TAutoConsoleVariable<int32> CVarGlobalClipPlane(
TEXT("r.AllowGlobalClipPlane"),
0,
TEXT("Enables mesh shaders to support a global clip plane, needed for planar reflections, which adds about 15% BasePass GPU cost on PS4."),
ECVF_ReadOnly | ECVF_RenderThreadSafe);
// Changing this causes a full shader recompile
static TAutoConsoleVariable<int32> CVarVertexFoggingForOpaque(
TEXT("r.VertexFoggingForOpaque"),
1,
TEXT("Causes opaque materials to use per-vertex fogging, which costs less and integrates properly with MSAA. Only supported with forward shading."),
ECVF_ReadOnly | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarRHICmdFlushRenderThreadTasksBasePass(
TEXT("r.RHICmdFlushRenderThreadTasksBasePass"),
0,
TEXT("Wait for completion of parallel render thread tasks at the end of the base pass. A more granular version of r.RHICmdFlushRenderThreadTasks. If either r.RHICmdFlushRenderThreadTasks or r.RHICmdFlushRenderThreadTasksBasePass is > 0 we will flush."));
static TAutoConsoleVariable<int32> CVarSupportStationarySkylight(
TEXT("r.SupportStationarySkylight"),
1,
TEXT("Enables Stationary and Dynamic Skylight shader permutations."),
ECVF_ReadOnly | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarSupportLowQualityLightmaps(
TEXT("r.SupportLowQualityLightmaps"),
1,
TEXT("Support low quality lightmap shader permutations"),
ECVF_ReadOnly | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarSupportAllShaderPermutations(
TEXT("r.SupportAllShaderPermutations"),
0,
TEXT("Local user config override to force all shader permutation features on."),
ECVF_ReadOnly | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarParallelBasePass(
TEXT("r.ParallelBasePass"),
1,
TEXT("Toggles parallel base pass rendering. Parallel rendering must be enabled for this to have an effect."),
ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarClearGBufferDBeforeBasePass(
TEXT("r.ClearGBufferDBeforeBasePass"),
1,
TEXT("Whether to clear GBuffer D before basepass"),
ECVF_RenderThreadSafe);
// Scene color alpha is used during scene captures and planar reflections. 1 indicates background should be shown, 0 indicates foreground is fully present.
static const float kSceneColorClearAlpha = 1.0f;
IMPLEMENT_GLOBAL_SHADER_PARAMETER_STRUCT(FSharedBasePassUniformParameters, "BasePass");
IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT(FOpaqueBasePassUniformParameters, "OpaqueBasePass", SceneTextures);
IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT(FTranslucentBasePassUniformParameters, "TranslucentBasePass", SceneTextures);
// Typedef is necessary because the C preprocessor thinks the comma in the template parameter list is a comma in the macro parameter list.
#define IMPLEMENT_BASEPASS_VERTEXSHADER_TYPE(LightMapPolicyType,LightMapPolicyName) \
typedef TBasePassVS< LightMapPolicyType > TBasePassVS##LightMapPolicyName ; \
IMPLEMENT_MATERIAL_SHADER_TYPE(template<>,TBasePassVS##LightMapPolicyName,TEXT("/Engine/Private/BasePassVertexShader.usf"),TEXT("Main"),SF_Vertex);
#define IMPLEMENT_BASEPASS_PIXELSHADER_TYPE(LightMapPolicyType,LightMapPolicyName,bEnableSkyLight,SkyLightName) \
typedef TBasePassPS<LightMapPolicyType, bEnableSkyLight> TBasePassPS##LightMapPolicyName##SkyLightName; \
IMPLEMENT_MATERIAL_SHADER_TYPE(template<>,TBasePassPS##LightMapPolicyName##SkyLightName,TEXT("/Engine/Private/BasePassPixelShader.usf"),TEXT("MainPS"),SF_Pixel);
// Implement a pixel shader type for skylights and one without, and one vertex shader that will be shared between them
#define IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE(LightMapPolicyType,LightMapPolicyName) \
IMPLEMENT_BASEPASS_VERTEXSHADER_TYPE(LightMapPolicyType,LightMapPolicyName) \
IMPLEMENT_BASEPASS_PIXELSHADER_TYPE(LightMapPolicyType,LightMapPolicyName,true,Skylight) \
IMPLEMENT_BASEPASS_PIXELSHADER_TYPE(LightMapPolicyType,LightMapPolicyName,false,);
// Implement shader types per lightmap policy
// If renaming or refactoring these, remember to update FMaterialResource::GetRepresentativeInstructionCounts and FPreviewMaterial::ShouldCache().
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( FSelfShadowedTranslucencyPolicy, FSelfShadowedTranslucencyPolicy );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( FSelfShadowedCachedPointIndirectLightingPolicy, FSelfShadowedCachedPointIndirectLightingPolicy );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( FSelfShadowedVolumetricLightmapPolicy, FSelfShadowedVolumetricLightmapPolicy );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( TUniformLightMapPolicy<LMP_NO_LIGHTMAP>, FNoLightMapPolicy );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( TUniformLightMapPolicy<LMP_PRECOMPUTED_IRRADIANCE_VOLUME_INDIRECT_LIGHTING>, FPrecomputedVolumetricLightmapLightingPolicy );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( TUniformLightMapPolicy<LMP_CACHED_VOLUME_INDIRECT_LIGHTING>, FCachedVolumeIndirectLightingPolicy );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( TUniformLightMapPolicy<LMP_CACHED_POINT_INDIRECT_LIGHTING>, FCachedPointIndirectLightingPolicy );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( TUniformLightMapPolicy<LMP_SIMPLE_NO_LIGHTMAP>, FSimpleNoLightmapLightingPolicy );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( TUniformLightMapPolicy<LMP_SIMPLE_LIGHTMAP_ONLY_LIGHTING>, FSimpleLightmapOnlyLightingPolicy );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( TUniformLightMapPolicy<LMP_SIMPLE_DIRECTIONAL_LIGHT_LIGHTING>, FSimpleDirectionalLightLightingPolicy );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( TUniformLightMapPolicy<LMP_SIMPLE_STATIONARY_PRECOMPUTED_SHADOW_LIGHTING>, FSimpleStationaryLightPrecomputedShadowsLightingPolicy );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( TUniformLightMapPolicy<LMP_SIMPLE_STATIONARY_SINGLESAMPLE_SHADOW_LIGHTING>, FSimpleStationaryLightSingleSampleShadowsLightingPolicy );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( TUniformLightMapPolicy<LMP_SIMPLE_STATIONARY_VOLUMETRICLIGHTMAP_SHADOW_LIGHTING>, FSimpleStationaryLightVolumetricLightmapShadowsLightingPolicy );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( TUniformLightMapPolicy<LMP_LQ_LIGHTMAP>, TLightMapPolicyLQ );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( TUniformLightMapPolicy<LMP_HQ_LIGHTMAP>, TLightMapPolicyHQ );
IMPLEMENT_BASEPASS_LIGHTMAPPED_SHADER_TYPE( TUniformLightMapPolicy<LMP_DISTANCE_FIELD_SHADOWS_AND_HQ_LIGHTMAP>, TDistanceFieldShadowsAndLightMapPolicyHQ );
IMPLEMENT_MATERIAL_SHADER_TYPE(, F128BitRTBasePassPS, TEXT("/Engine/Private/BasePassPixelShader.usf"), TEXT("MainPS"), SF_Pixel);
DEFINE_GPU_DRAWCALL_STAT(Basepass);
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer ClearGBufferAtMaxZ"), STAT_FDeferredShadingSceneRenderer_ClearGBufferAtMaxZ, STATGROUP_SceneRendering);
DECLARE_CYCLE_STAT(TEXT("DeferredShadingSceneRenderer ViewExtensionPostRenderBasePass"), STAT_FDeferredShadingSceneRenderer_ViewExtensionPostRenderBasePass, STATGROUP_SceneRendering);
DECLARE_CYCLE_STAT(TEXT("BasePass"), STAT_CLM_BasePass, STATGROUP_CommandListMarkers);
DECLARE_CYCLE_STAT(TEXT("AfterBasePass"), STAT_CLM_AfterBasePass, STATGROUP_CommandListMarkers);
DECLARE_CYCLE_STAT(TEXT("AnisotropyPass"), STAT_CLM_AnisotropyPass, STATGROUP_CommandListMarkers);
DECLARE_CYCLE_STAT(TEXT("AfterAnisotropyPass"), STAT_CLM_AfterAnisotropyPass, STATGROUP_CommandListMarkers);
DECLARE_CYCLE_STAT(TEXT("BasePass"), STAT_CLP_BasePass, STATGROUP_ParallelCommandListMarkers);
static bool IsBasePassWaitForTasksEnabled()
{
return CVarRHICmdFlushRenderThreadTasksBasePass.GetValueOnRenderThread() > 0 || CVarRHICmdFlushRenderThreadTasks.GetValueOnRenderThread() > 0;
}
void SetTranslucentRenderState(FMeshPassProcessorRenderState& DrawRenderState, const FMaterial& Material, const EShaderPlatform Platform, ETranslucencyPass::Type InTranslucencyPassType)
{
// STRATA_TODO IsStrataMaterial will be removed when all materials are unified to use premultipled alpha
if (Material.GetShadingModels().HasShadingModel(MSM_ThinTranslucent) || Material.IsStrataMaterial())
{
// Special case for dual blending, which is not exposed as a parameter in the material editor
if (Material.IsDualBlendingEnabled(Platform))
{
if (InTranslucencyPassType == ETranslucencyPass::TPT_StandardTranslucency || InTranslucencyPassType == ETranslucencyPass::TPT_AllTranslucency)
{
// If we are in the transparancy pass (before DoF) we do standard dual blending, and the alpha gets ignored
// Blend by putting add in target 0 and multiply by background in target 1.
DrawRenderState.SetBlendState(TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_Source1Color, BO_Add, BF_One, BF_Source1Alpha>::GetRHI());
}
else if (InTranslucencyPassType == ETranslucencyPass::TPT_TranslucencyAfterDOF)
{
// In the separate pass (after DoF), we want let alpha pass through, and then multiply our color modulation in the after DoF Modulation pass.
// Alpha is BF_Zero for source and BF_One for dest, which leaves alpha unchanged
DrawRenderState.SetBlendState(TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_Source1Color, BO_Add, BF_Zero, BF_One>::GetRHI());
}
else if (InTranslucencyPassType == ETranslucencyPass::TPT_TranslucencyAfterDOFModulate)
{
// In the separate pass (after DoF) modulate, we want to only darken the target by our multiplication term, and ignore the addition term.
// For regular dual blending, our function is:
// FrameBuffer = MRT0 + MRT1 * FrameBuffer;
// So we can just remove the MRT0 component and it will modulate as expected.
// Alpha we will leave unchanged.
DrawRenderState.SetBlendState(TStaticBlendState<CW_RGBA, BO_Add, BF_Zero, BF_Source1Color, BO_Add, BF_Zero, BF_One>::GetRHI());
}
else if (InTranslucencyPassType == ETranslucencyPass::TPT_TranslucencyAfterMotionBlur)
{
// We don't actually currently support color modulation in the post-motion blur pass at the moment, so just do the same as post-DOF for now
DrawRenderState.SetBlendState(TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_Source1Color, BO_Add, BF_Zero, BF_One>::GetRHI());
}
}
else
{
// If unsupported, use the same as translucent, but with color multiplied by BF_One instead of BF_SourceAlpha.
// The shader will use the variation that approximates color modulation using alpha
DrawRenderState.SetBlendState(TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_InverseSourceAlpha, BO_Add, BF_Zero, BF_InverseSourceAlpha>::GetRHI());
}
}
else
{
switch (Material.GetBlendMode())
{
default:
case BLEND_Opaque:
// Opaque materials are rendered together in the base pass, where the blend state is set at a higher level
break;
case BLEND_Masked:
// Masked materials are rendered together in the base pass, where the blend state is set at a higher level
break;
case BLEND_Translucent:
// Note: alpha channel used by separate translucency, storing how much of the background should be added when doing the final composite
// The Alpha channel is also used by non-separate translucency when rendering to scene captures, which store the final opacity
DrawRenderState.SetBlendState(TStaticBlendState<CW_RGBA, BO_Add, BF_SourceAlpha, BF_InverseSourceAlpha, BO_Add, BF_Zero, BF_InverseSourceAlpha>::GetRHI());
break;
case BLEND_Additive:
// Add to the existing scene color
// Note: alpha channel used by separate translucency, storing how much of the background should be added when doing the final composite
// The Alpha channel is also used by non-separate translucency when rendering to scene captures, which store the final opacity
DrawRenderState.SetBlendState(TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_One, BO_Add, BF_Zero, BF_InverseSourceAlpha>::GetRHI());
break;
case BLEND_Modulate:
// Modulate with the existing scene color, preserve destination alpha.
DrawRenderState.SetBlendState(TStaticBlendState<CW_RGB, BO_Add, BF_DestColor, BF_Zero>::GetRHI());
break;
case BLEND_AlphaComposite:
// Blend with existing scene color. New color is already pre-multiplied by alpha.
DrawRenderState.SetBlendState(TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_InverseSourceAlpha, BO_Add, BF_Zero, BF_InverseSourceAlpha>::GetRHI());
break;
case BLEND_AlphaHoldout:
// Blend by holding out the matte shape of the source alpha
DrawRenderState.SetBlendState(TStaticBlendState<CW_RGBA, BO_Add, BF_Zero, BF_InverseSourceAlpha, BO_Add, BF_One, BF_InverseSourceAlpha>::GetRHI());
break;
};
}
const bool bDisableDepthTest = Material.ShouldDisableDepthTest();
const bool bEnableResponsiveAA = Material.ShouldEnableResponsiveAA();
const bool bIsPostMotionBlur = Material.IsTranslucencyAfterMotionBlurEnabled();
if (bEnableResponsiveAA && !bIsPostMotionBlur)
{
if (bDisableDepthTest)
{
DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<
false, CF_Always,
true, CF_Always, SO_Keep, SO_Keep, SO_Replace,
false, CF_Always, SO_Keep, SO_Keep, SO_Keep,
STENCIL_TEMPORAL_RESPONSIVE_AA_MASK, STENCIL_TEMPORAL_RESPONSIVE_AA_MASK
>::GetRHI());
DrawRenderState.SetStencilRef(STENCIL_TEMPORAL_RESPONSIVE_AA_MASK);
}
else
{
DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<
false, CF_DepthNearOrEqual,
true, CF_Always, SO_Keep, SO_Keep, SO_Replace,
false, CF_Always, SO_Keep, SO_Keep, SO_Keep,
STENCIL_TEMPORAL_RESPONSIVE_AA_MASK, STENCIL_TEMPORAL_RESPONSIVE_AA_MASK
>::GetRHI());
DrawRenderState.SetStencilRef(STENCIL_TEMPORAL_RESPONSIVE_AA_MASK);
}
}
else if (bDisableDepthTest)
{
DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
}
}
FMeshDrawCommandSortKey CalculateTranslucentMeshStaticSortKey(const FPrimitiveSceneProxy* RESTRICT PrimitiveSceneProxy, uint16 MeshIdInPrimitive)
{
uint16 SortKeyPriority = 0;
float DistanceOffset = 0.0f;
if (PrimitiveSceneProxy)
{
const FPrimitiveSceneInfo* PrimitiveSceneInfo = PrimitiveSceneProxy->GetPrimitiveSceneInfo();
SortKeyPriority = (uint16)((int32)PrimitiveSceneInfo->Proxy->GetTranslucencySortPriority() - (int32)SHRT_MIN);
DistanceOffset = PrimitiveSceneInfo->Proxy->GetTranslucencySortDistanceOffset();
}
FMeshDrawCommandSortKey SortKey;
SortKey.Translucent.MeshIdInPrimitive = MeshIdInPrimitive;
SortKey.Translucent.Priority = SortKeyPriority;
SortKey.Translucent.Distance = *(uint32*)(&DistanceOffset); // View specific, so will be filled later inside VisibleMeshCommands.
return SortKey;
}
FMeshDrawCommandSortKey CalculateBasePassMeshStaticSortKey(EDepthDrawingMode EarlyZPassMode, EBlendMode BlendMode, const FMeshMaterialShader* VertexShader, const FMeshMaterialShader* PixelShader)
{
FMeshDrawCommandSortKey SortKey;
SortKey.BasePass.VertexShaderHash = (VertexShader ? VertexShader->GetSortKey() : 0) & 0xFFFF;
SortKey.BasePass.PixelShaderHash = PixelShader ? PixelShader->GetSortKey() : 0;
if (EarlyZPassMode != DDM_None)
{
SortKey.BasePass.Masked = BlendMode == EBlendMode::BLEND_Masked ? 0 : 1;
}
else
{
SortKey.BasePass.Masked = BlendMode == EBlendMode::BLEND_Masked ? 1 : 0;
}
return SortKey;
}
void SetDepthStencilStateForBasePass(
const FSceneView* ViewIfDynamicMeshCommand,
FMeshPassProcessorRenderState& DrawRenderState,
ERHIFeatureLevel::Type FeatureLevel,
const FMeshBatch& Mesh,
int32 StaticMeshId,
const FPrimitiveSceneProxy* PrimitiveSceneProxy,
const FMaterial& MaterialResource,
bool bEnableReceiveDecalOutput)
{
const bool bMaskedInEarlyPass = (MaterialResource.IsMasked() || Mesh.bDitheredLODTransition) && MaskedInEarlyPass(GShaderPlatformForFeatureLevel[FeatureLevel]);
if (bEnableReceiveDecalOutput)
{
// Set stencil value for this draw call
// This is effectively extending the GBuffer using the stencil bits
const uint8 StencilValue = GET_STENCIL_BIT_MASK(RECEIVE_DECAL, PrimitiveSceneProxy ? !!PrimitiveSceneProxy->ReceivesDecals() : 0x00)
| GET_STENCIL_BIT_MASK(DISTANCE_FIELD_REPRESENTATION, PrimitiveSceneProxy ? PrimitiveSceneProxy->HasDistanceFieldRepresentation() : 0x00)
| STENCIL_LIGHTING_CHANNELS_MASK(PrimitiveSceneProxy ? PrimitiveSceneProxy->GetLightingChannelStencilValue() : 0x00);
if (bMaskedInEarlyPass)
{
DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<
false, CF_Equal,
true, CF_Always, SO_Keep, SO_Keep, SO_Replace,
false, CF_Always, SO_Keep, SO_Keep, SO_Keep,
0xFF, GET_STENCIL_BIT_MASK(RECEIVE_DECAL, 1) | GET_STENCIL_BIT_MASK(DISTANCE_FIELD_REPRESENTATION, 1) | STENCIL_LIGHTING_CHANNELS_MASK(0x7)
>::GetRHI());
DrawRenderState.SetStencilRef(StencilValue);
}
else if (DrawRenderState.GetDepthStencilAccess() & FExclusiveDepthStencil::DepthWrite)
{
DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<
true, CF_GreaterEqual,
true, CF_Always, SO_Keep, SO_Keep, SO_Replace,
false, CF_Always, SO_Keep, SO_Keep, SO_Keep,
0xFF, GET_STENCIL_BIT_MASK(RECEIVE_DECAL, 1) | GET_STENCIL_BIT_MASK(DISTANCE_FIELD_REPRESENTATION, 1) | STENCIL_LIGHTING_CHANNELS_MASK(0x7)
>::GetRHI());
DrawRenderState.SetStencilRef(StencilValue);
}
else
{
DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<
false, CF_GreaterEqual,
true, CF_Always, SO_Keep, SO_Keep, SO_Replace,
false, CF_Always, SO_Keep, SO_Keep, SO_Keep,
0xFF, GET_STENCIL_BIT_MASK(RECEIVE_DECAL, 1) | GET_STENCIL_BIT_MASK(DISTANCE_FIELD_REPRESENTATION, 1) | STENCIL_LIGHTING_CHANNELS_MASK(0x7)
>::GetRHI());
DrawRenderState.SetStencilRef(StencilValue);
}
}
else if (bMaskedInEarlyPass)
{
DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<false, CF_Equal>::GetRHI());
}
if (ViewIfDynamicMeshCommand && StaticMeshId >= 0 && Mesh.bDitheredLODTransition)
{
checkSlow(ViewIfDynamicMeshCommand->bIsViewInfo);
const FViewInfo* ViewInfo = static_cast<const FViewInfo*>(ViewIfDynamicMeshCommand);
if (ViewInfo->bAllowStencilDither)
{
if (ViewInfo->StaticMeshFadeOutDitheredLODMap[StaticMeshId] || ViewInfo->StaticMeshFadeInDitheredLODMap[StaticMeshId])
{
const uint32 RestoreStencilRef = DrawRenderState.GetStencilRef();
DrawRenderState.SetDepthStencilState(
TStaticDepthStencilState<
false, CF_Equal,
true, CF_Always, SO_Keep, SO_Keep, SO_Replace,
false, CF_Always, SO_Keep, SO_Keep, SO_Keep,
0xFF, GET_STENCIL_BIT_MASK(RECEIVE_DECAL, 1) | GET_STENCIL_BIT_MASK(DISTANCE_FIELD_REPRESENTATION, 1) | STENCIL_LIGHTING_CHANNELS_MASK(0x7)
>::GetRHI());
DrawRenderState.SetStencilRef(RestoreStencilRef);
}
}
}
}
void SetupBasePassState(FExclusiveDepthStencil::Type BasePassDepthStencilAccess, const bool bShaderComplexity, FMeshPassProcessorRenderState& DrawRenderState)
{
DrawRenderState.SetDepthStencilAccess(BasePassDepthStencilAccess);
if (bShaderComplexity)
{
// Additive blending when shader complexity viewmode is enabled.
DrawRenderState.SetBlendState(TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_One, BO_Add, BF_Zero, BF_One>::GetRHI());
// Disable depth writes as we have a full depth prepass.
DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI());
}
else
{
// Opaque blending for all G buffer targets, depth tests and writes.
static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.BasePassOutputsVelocityDebug"));
if (CVar && CVar->GetValueOnRenderThread() == 2)
{
DrawRenderState.SetBlendState(TStaticBlendStateWriteMask<CW_RGBA, CW_RGBA, CW_RGBA, CW_RGBA, CW_RGBA, CW_RGBA, CW_NONE>::GetRHI());
}
else
{
DrawRenderState.SetBlendState(TStaticBlendStateWriteMask<CW_RGBA, CW_RGBA, CW_RGBA, CW_RGBA>::GetRHI());
}
if (DrawRenderState.GetDepthStencilAccess() & FExclusiveDepthStencil::DepthWrite)
{
DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<true, CF_DepthNearOrEqual>::GetRHI());
}
else
{
DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI());
}
}
}
/**
* Get shader templates allowing to redirect between compatible shaders.
*/
template <ELightMapPolicyType Policy>
bool GetUniformBasePassShaders(
const FMaterial& Material,
FVertexFactoryType* VertexFactoryType,
ERHIFeatureLevel::Type FeatureLevel,
bool bEnableSkyLight,
bool bUse128bitRT,
TShaderRef<TBasePassVertexShaderPolicyParamType<FUniformLightMapPolicy>>* VertexShader,
TShaderRef<TBasePassPixelShaderPolicyParamType<FUniformLightMapPolicy>>* PixelShader
)
{
FMaterialShaderTypes ShaderTypes;
if(VertexShader)
{
ShaderTypes.AddShaderType<TBasePassVS<TUniformLightMapPolicy<Policy>>>();
}
if(PixelShader)
{
if (bEnableSkyLight)
{
ShaderTypes.AddShaderType<TBasePassPS<TUniformLightMapPolicy<Policy>, true>>();
}
else
{
if (bUse128bitRT && (Policy == LMP_NO_LIGHTMAP))
{
ShaderTypes.AddShaderType<F128BitRTBasePassPS>();
}
else
{
ShaderTypes.AddShaderType<TBasePassPS<TUniformLightMapPolicy<Policy>, false>>();
}
}
}
FMaterialShaders Shaders;
if (!Material.TryGetShaders(ShaderTypes, VertexFactoryType, Shaders))
{
return false;
}
Shaders.TryGetVertexShader(VertexShader);
Shaders.TryGetPixelShader(PixelShader);
return true;
}
template <>
bool GetBasePassShaders<FUniformLightMapPolicy>(
const FMaterial& Material,
FVertexFactoryType* VertexFactoryType,
FUniformLightMapPolicy LightMapPolicy,
ERHIFeatureLevel::Type FeatureLevel,
bool bEnableSkyLight,
bool bUse128bitRT,
TShaderRef<TBasePassVertexShaderPolicyParamType<FUniformLightMapPolicy>>* VertexShader,
TShaderRef<TBasePassPixelShaderPolicyParamType<FUniformLightMapPolicy>>* PixelShader
)
{
switch (LightMapPolicy.GetIndirectPolicy())
{
case LMP_PRECOMPUTED_IRRADIANCE_VOLUME_INDIRECT_LIGHTING:
return GetUniformBasePassShaders<LMP_PRECOMPUTED_IRRADIANCE_VOLUME_INDIRECT_LIGHTING>(Material, VertexFactoryType, FeatureLevel, bEnableSkyLight, bUse128bitRT, VertexShader, PixelShader);
case LMP_CACHED_VOLUME_INDIRECT_LIGHTING:
return GetUniformBasePassShaders<LMP_CACHED_VOLUME_INDIRECT_LIGHTING>(Material, VertexFactoryType, FeatureLevel, bEnableSkyLight, bUse128bitRT, VertexShader, PixelShader);
case LMP_CACHED_POINT_INDIRECT_LIGHTING:
return GetUniformBasePassShaders<LMP_CACHED_POINT_INDIRECT_LIGHTING>(Material, VertexFactoryType, FeatureLevel, bEnableSkyLight, bUse128bitRT, VertexShader, PixelShader);
case LMP_SIMPLE_DIRECTIONAL_LIGHT_LIGHTING:
return GetUniformBasePassShaders<LMP_SIMPLE_DIRECTIONAL_LIGHT_LIGHTING>(Material, VertexFactoryType, FeatureLevel, bEnableSkyLight, bUse128bitRT, VertexShader, PixelShader);
case LMP_SIMPLE_NO_LIGHTMAP:
return GetUniformBasePassShaders<LMP_SIMPLE_NO_LIGHTMAP>(Material, VertexFactoryType, FeatureLevel, bEnableSkyLight, bUse128bitRT, VertexShader, PixelShader);
case LMP_SIMPLE_LIGHTMAP_ONLY_LIGHTING:
return GetUniformBasePassShaders<LMP_SIMPLE_LIGHTMAP_ONLY_LIGHTING>(Material, VertexFactoryType, FeatureLevel, bEnableSkyLight, bUse128bitRT, VertexShader, PixelShader);
case LMP_SIMPLE_STATIONARY_PRECOMPUTED_SHADOW_LIGHTING:
return GetUniformBasePassShaders<LMP_SIMPLE_STATIONARY_PRECOMPUTED_SHADOW_LIGHTING>(Material, VertexFactoryType, FeatureLevel, bEnableSkyLight, bUse128bitRT, VertexShader, PixelShader);
case LMP_SIMPLE_STATIONARY_SINGLESAMPLE_SHADOW_LIGHTING:
return GetUniformBasePassShaders<LMP_SIMPLE_STATIONARY_SINGLESAMPLE_SHADOW_LIGHTING>(Material, VertexFactoryType, FeatureLevel, bEnableSkyLight, bUse128bitRT, VertexShader, PixelShader);
case LMP_SIMPLE_STATIONARY_VOLUMETRICLIGHTMAP_SHADOW_LIGHTING:
return GetUniformBasePassShaders<LMP_SIMPLE_STATIONARY_VOLUMETRICLIGHTMAP_SHADOW_LIGHTING>(Material, VertexFactoryType, FeatureLevel, bEnableSkyLight, bUse128bitRT, VertexShader, PixelShader);
case LMP_LQ_LIGHTMAP:
return GetUniformBasePassShaders<LMP_LQ_LIGHTMAP>(Material, VertexFactoryType, FeatureLevel, bEnableSkyLight, bUse128bitRT, VertexShader, PixelShader);
case LMP_HQ_LIGHTMAP:
return GetUniformBasePassShaders<LMP_HQ_LIGHTMAP>(Material, VertexFactoryType, FeatureLevel, bEnableSkyLight, bUse128bitRT, VertexShader, PixelShader);
case LMP_DISTANCE_FIELD_SHADOWS_AND_HQ_LIGHTMAP:
return GetUniformBasePassShaders<LMP_DISTANCE_FIELD_SHADOWS_AND_HQ_LIGHTMAP>(Material, VertexFactoryType, FeatureLevel, bEnableSkyLight, bUse128bitRT, VertexShader, PixelShader);
case LMP_NO_LIGHTMAP:
return GetUniformBasePassShaders<LMP_NO_LIGHTMAP>(Material, VertexFactoryType, FeatureLevel, bEnableSkyLight, bUse128bitRT, VertexShader, PixelShader);
default:
check(false);
return false;
}
}
void SetupSharedBasePassParameters(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
FSharedBasePassUniformParameters& SharedParameters)
{
SharedParameters.Forward = View.ForwardLightingResources->ForwardLightData;
SetupFogUniformParameters(GraphBuilder, View, SharedParameters.Fog);
if (View.IsInstancedStereoPass())
{
const FSceneView& RightEye = *View.Family->Views[1];
SharedParameters.ForwardISR = RightEye.ForwardLightingResources->ForwardLightData;
SetupFogUniformParameters(GraphBuilder, (FViewInfo&)RightEye, SharedParameters.FogISR);
}
else
{
SharedParameters.ForwardISR = View.ForwardLightingResources->ForwardLightData;
SharedParameters.FogISR = SharedParameters.Fog;
}
const FScene* Scene = View.Family->Scene ? View.Family->Scene->GetRenderScene() : nullptr;
const FPlanarReflectionSceneProxy* ReflectionSceneProxy = Scene ? Scene->GetForwardPassGlobalPlanarReflection() : nullptr;
SetupReflectionUniformParameters(View, SharedParameters.Reflection);
SetupPlanarReflectionUniformParameters(View, ReflectionSceneProxy, SharedParameters.PlanarReflection);
// Skip base pass skylight if Lumen GI is enabled, as Lumen handles the skylight.
// Ideally we would choose a different shader permutation to skip skylight, but Lumen GI is only known per-view
SharedParameters.UseBasePassSkylight = View.FinalPostProcessSettings.DynamicGlobalIlluminationMethod == EDynamicGlobalIlluminationMethod::Lumen ? 0 : 1;
}
TRDGUniformBufferRef<FOpaqueBasePassUniformParameters> CreateOpaqueBasePassUniformBuffer(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const int32 ViewIndex,
const FForwardBasePassTextures& ForwardBasePassTextures,
const FDBufferTextures& DBufferTextures,
const FSceneWithoutWaterTextures* SceneWithoutWaterTextures)
{
FOpaqueBasePassUniformParameters& BasePassParameters = *GraphBuilder.AllocParameters<FOpaqueBasePassUniformParameters>();
SetupSharedBasePassParameters(GraphBuilder, View, BasePassParameters.Shared);
const FRDGSystemTextures& SystemTextures = FRDGSystemTextures::Get(GraphBuilder);
// Forward shading
{
BasePassParameters.UseForwardScreenSpaceShadowMask = 0;
BasePassParameters.ForwardScreenSpaceShadowMaskTexture = SystemTextures.White;
BasePassParameters.IndirectOcclusionTexture = SystemTextures.White;
BasePassParameters.ResolvedSceneDepthTexture = SystemTextures.White;
if (ForwardBasePassTextures.ScreenSpaceShadowMask)
{
BasePassParameters.UseForwardScreenSpaceShadowMask = 1;
BasePassParameters.ForwardScreenSpaceShadowMaskTexture = ForwardBasePassTextures.ScreenSpaceShadowMask;
}
if (HasBeenProduced(ForwardBasePassTextures.ScreenSpaceAO))
{
BasePassParameters.IndirectOcclusionTexture = ForwardBasePassTextures.ScreenSpaceAO;
}
if (ForwardBasePassTextures.SceneDepthIfResolved)
{
BasePassParameters.ResolvedSceneDepthTexture = ForwardBasePassTextures.SceneDepthIfResolved;
}
}
// DBuffer Decals
BasePassParameters.DBuffer = GetDBufferParameters(GraphBuilder, DBufferTextures, View.GetShaderPlatform());
// Single Layer Water
BasePassParameters.SceneWithoutSingleLayerWaterMinMaxUV = FVector4f(0.0f, 0.0f, 1.0f, 1.0f);
BasePassParameters.SceneColorWithoutSingleLayerWaterTexture = SystemTextures.Black;
BasePassParameters.SceneDepthWithoutSingleLayerWaterTexture = SystemTextures.Black;
BasePassParameters.SceneColorWithoutSingleLayerWaterSampler = TStaticSamplerState<SF_Bilinear>::GetRHI();
BasePassParameters.SceneDepthWithoutSingleLayerWaterSampler = TStaticSamplerState<SF_Point>::GetRHI();
if (SceneWithoutWaterTextures)
{
BasePassParameters.SceneWithoutSingleLayerWaterMinMaxUV = SceneWithoutWaterTextures->Views[ViewIndex].MinMaxUV;
BasePassParameters.SceneColorWithoutSingleLayerWaterTexture = SceneWithoutWaterTextures->ColorTexture;
BasePassParameters.SceneDepthWithoutSingleLayerWaterTexture = SceneWithoutWaterTextures->DepthTexture;
}
BasePassParameters.PreIntegratedGFTexture = GSystemTextures.PreintegratedGF->GetShaderResourceRHI();
BasePassParameters.PreIntegratedGFSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
SetupDistortionParams(BasePassParameters.DistortionParams, View);
// Strata
Strata::BindStrataBasePassUniformParameters(GraphBuilder, View.StrataSceneData, BasePassParameters.Strata);
// Misc
BasePassParameters.EyeAdaptationTexture = GetEyeAdaptationTexture(GraphBuilder, View);
return GraphBuilder.CreateUniformBuffer(&BasePassParameters);
}
static void ClearGBufferAtMaxZ(
FRDGBuilder& GraphBuilder,
TArrayView<const FViewInfo> Views,
const FRenderTargetBindingSlots& BasePassRenderTargets,
FLinearColor ClearColor0)
{
check(Views.Num() > 0);
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_ClearGBufferAtMaxZ);
RDG_EVENT_SCOPE(GraphBuilder, "ClearGBufferAtMaxZ");
const uint32 ActiveTargetCount = BasePassRenderTargets.GetActiveCount();
FGlobalShaderMap* ShaderMap = Views[0].ShaderMap;
TShaderMapRef<TOneColorVS<true> > VertexShader(ShaderMap);
TOneColorPixelShaderMRT::FPermutationDomain PermutationVector;
PermutationVector.Set<TOneColorPixelShaderMRT::TOneColorPixelShaderNumOutputs>(ActiveTargetCount);
TShaderMapRef<TOneColorPixelShaderMRT>PixelShader(ShaderMap, PermutationVector);
auto* PassParameters = GraphBuilder.AllocParameters<FRenderTargetParameters>();
PassParameters->RenderTargets = BasePassRenderTargets;
// Clear each viewport by drawing background color at MaxZ depth
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
{
const FViewInfo& View = Views[ViewIndex];
RDG_GPU_MASK_SCOPE(GraphBuilder, View.GPUMask);
RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Views.Num() > 1, "View%d", ViewIndex);
GraphBuilder.AddPass(
{},
PassParameters,
ERDGPassFlags::Raster,
[&View, VertexShader, PixelShader, ActiveTargetCount, ClearColor0](FRHICommandListImmediate& RHICmdList)
{
const FLinearColor ClearColors[MaxSimultaneousRenderTargets] =
{
ClearColor0,
FLinearColor(0.5f,0.5f,0.5f,0),
FLinearColor(0,0,0,1),
FLinearColor(0,0,0,0),
FLinearColor(0,1,1,1),
FLinearColor(1,1,1,1),
FLinearColor::Transparent,
FLinearColor::Transparent
};
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
// Opaque rendering, depth test but no depth writes
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<FM_Solid, CM_None>::GetRHI();
GraphicsPSOInit.BlendState = TStaticBlendStateWriteMask<>::GetRHI();
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI();
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GetVertexDeclarationFVector4();
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
GraphicsPSOInit.PrimitiveType = PT_TriangleStrip;
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0);
VertexShader->SetDepthParameter(RHICmdList, float(ERHIZBuffer::FarPlane));
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1);
PixelShader->SetColors(RHICmdList, ClearColors, ActiveTargetCount);
RHICmdList.SetStreamSource(0, GClearVertexBuffer.VertexBufferRHI, 0);
RHICmdList.DrawPrimitive(0, 2, 1);
});
}
}
BEGIN_SHADER_PARAMETER_STRUCT(FPostBasePassViewExtensionParameters, )
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneTextureUniformParameters, SceneTextures)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
void FDeferredShadingSceneRenderer::RenderBasePass(
FRDGBuilder& GraphBuilder,
FSceneTextures& SceneTextures,
const FDBufferTextures& DBufferTextures,
FExclusiveDepthStencil::Type BasePassDepthStencilAccess,
FRDGTextureRef ForwardShadowMaskTexture,
FInstanceCullingManager& InstanceCullingManager,
bool bNaniteEnabled,
const TArrayView<Nanite::FRasterResults>& NaniteRasterResults)
{
TRACE_CPUPROFILER_EVENT_SCOPE(FDeferredShadingSceneRenderer::RenderBasePass);
const bool bEnableParallelBasePasses = GRHICommandList.UseParallelAlgorithms() && CVarParallelBasePass.GetValueOnRenderThread();
static const auto ClearMethodCVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.ClearSceneMethod"));
bool bRequiresRHIClear = true;
bool bRequiresFarZQuadClear = false;
if (ClearMethodCVar)
{
int32 ClearMethod = ClearMethodCVar->GetValueOnRenderThread();
if (ClearMethod == 0 && !ViewFamily.EngineShowFlags.Game)
{
// Do not clear the scene only if the view family is in game mode.
ClearMethod = 1;
}
switch (ClearMethod)
{
case 0: // No clear
bRequiresRHIClear = false;
bRequiresFarZQuadClear = false;
break;
case 1: // RHICmdList.Clear
bRequiresRHIClear = true;
bRequiresFarZQuadClear = false;
break;
case 2: // Clear using far-z quad
bRequiresFarZQuadClear = true;
bRequiresRHIClear = false;
break;
}
}
// Always perform a full buffer clear for wireframe, shader complexity view mode, and stationary light overlap viewmode.
if (ViewFamily.EngineShowFlags.Wireframe || ViewFamily.EngineShowFlags.ShaderComplexity || ViewFamily.EngineShowFlags.StationaryLightOverlap)
{
bRequiresRHIClear = true;
bRequiresFarZQuadClear = false;
}
const bool bIsWireframeRenderpass = ViewFamily.EngineShowFlags.Wireframe && FSceneRenderer::ShouldCompositeEditorPrimitives(Views[0]);
const bool bDebugViewMode = ViewFamily.UseDebugViewPS();
const bool bRenderLightmapDensity = ViewFamily.EngineShowFlags.LightMapDensity && AllowDebugViewmodes();
const bool bRenderSkyAtmosphereEditorNotifications = ShouldRenderSkyAtmosphereEditorNotifications();
const bool bDoParallelBasePass = bEnableParallelBasePasses && !bDebugViewMode && !bRenderLightmapDensity; // DebugView and LightmapDensity are non-parallel substitutions inside BasePass
const bool bNeedsBeginRender = AllowDebugViewmodes() &&
(ViewFamily.EngineShowFlags.RequiredTextureResolution ||
ViewFamily.EngineShowFlags.VirtualTexturePendingMips ||
ViewFamily.EngineShowFlags.MaterialTextureScaleAccuracy ||
ViewFamily.EngineShowFlags.MeshUVDensityAccuracy ||
ViewFamily.EngineShowFlags.PrimitiveDistanceAccuracy ||
ViewFamily.EngineShowFlags.ShaderComplexity ||
ViewFamily.EngineShowFlags.LODColoration ||
ViewFamily.EngineShowFlags.HLODColoration);
const bool bForwardShadingEnabled = IsForwardShadingEnabled(SceneTextures.Config.ShaderPlatform);
const FExclusiveDepthStencil ExclusiveDepthStencil(BasePassDepthStencilAccess);
TStaticArray<FTextureRenderTargetBinding, MaxSimultaneousRenderTargets> BasePassTextures;
uint32 BasePassTextureCount = SceneTextures.GetGBufferRenderTargets(BasePassTextures);
Strata::AppendStrataMRTs(*this, BasePassTextureCount, BasePassTextures);
TArrayView<FTextureRenderTargetBinding> BasePassTexturesView = MakeArrayView(BasePassTextures.GetData(), BasePassTextureCount);
FRDGTextureRef BasePassDepthTexture = SceneTextures.Depth.Target;
FLinearColor SceneColorClearValue;
if (bRequiresRHIClear)
{
if (ViewFamily.EngineShowFlags.ShaderComplexity && SceneTextures.QuadOverdraw)
{
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(SceneTextures.QuadOverdraw), FUintVector4(0, 0, 0, 0));
}
if (ViewFamily.EngineShowFlags.ShaderComplexity || ViewFamily.EngineShowFlags.StationaryLightOverlap)
{
SceneColorClearValue = FLinearColor(0, 0, 0, kSceneColorClearAlpha);
}
else
{
SceneColorClearValue = FLinearColor(Views[0].BackgroundColor.R, Views[0].BackgroundColor.G, Views[0].BackgroundColor.B, kSceneColorClearAlpha);
}
ERenderTargetLoadAction ColorLoadAction = ERenderTargetLoadAction::ELoad;
if (SceneTextures.Color.Target->Desc.ClearValue.GetClearColor() == SceneColorClearValue)
{
ColorLoadAction = ERenderTargetLoadAction::EClear;
}
else
{
ColorLoadAction = ERenderTargetLoadAction::ENoAction;
}
auto* PassParameters = GraphBuilder.AllocParameters<FRenderTargetParameters>();
PassParameters->RenderTargets = GetRenderTargetBindings(ColorLoadAction, BasePassTexturesView);
if (!CVarClearGBufferDBeforeBasePass.GetValueOnRenderThread() && SceneTextures.Config.GBufferD.Index > 0 && SceneTextures.Config.GBufferD.Index < (int32)BasePassTextureCount)
{
PassParameters->RenderTargets[SceneTextures.Config.GBufferD.Index].SetLoadAction(ERenderTargetLoadAction::ENoAction);
}
GraphBuilder.AddPass(RDG_EVENT_NAME("GBufferClear"), PassParameters, ERDGPassFlags::Raster,
[PassParameters, ColorLoadAction, SceneColorClearValue](FRHICommandList& RHICmdList)
{
// If no fast-clear action was used, we need to do an MRT shader clear.
if (ColorLoadAction == ERenderTargetLoadAction::ENoAction)
{
const FRenderTargetBindingSlots& RenderTargets = PassParameters->RenderTargets;
FLinearColor ClearColors[MaxSimultaneousRenderTargets];
FRHITexture* Textures[MaxSimultaneousRenderTargets];
int32 TextureIndex = 0;
RenderTargets.Enumerate([&](const FRenderTargetBinding& RenderTarget)
{
FRHITexture* TextureRHI = RenderTarget.GetTexture()->GetRHI();
ClearColors[TextureIndex] = TextureIndex == 0 ? SceneColorClearValue : TextureRHI->GetClearColor();
Textures[TextureIndex] = TextureRHI;
++TextureIndex;
});
// Clear color only; depth-stencil is fast cleared.
DrawClearQuadMRT(RHICmdList, true, TextureIndex, ClearColors, false, 0, false, 0);
}
});
if (bRenderSkyAtmosphereEditorNotifications)
{
// We only render this warning text when bRequiresRHIClear==true to make sure the scene color buffer is allocated at this stage.
// When false, the option specifies that all pixels must be written to by a sky dome anyway.
RenderSkyAtmosphereEditorNotifications(GraphBuilder, SceneTextures.Color.Target);
}
}
#if WITH_EDITOR
if (ViewFamily.EngineShowFlags.Wireframe)
{
checkf(ExclusiveDepthStencil.IsDepthWrite(), TEXT("Wireframe base pass requires depth-write, but it is set to read-only."));
BasePassTextureCount = 1;
BasePassTextures[0] = SceneTextures.EditorPrimitiveColor;
BasePassTexturesView = MakeArrayView(BasePassTextures.GetData(), BasePassTextureCount);
BasePassDepthTexture = SceneTextures.EditorPrimitiveDepth;
auto* PassParameters = GraphBuilder.AllocParameters<FRenderTargetParameters>();
PassParameters->RenderTargets = GetRenderTargetBindings(ERenderTargetLoadAction::EClear, BasePassTexturesView);
PassParameters->RenderTargets.DepthStencil = FDepthStencilBinding(BasePassDepthTexture, ERenderTargetLoadAction::EClear, ERenderTargetLoadAction::EClear, ExclusiveDepthStencil);
GraphBuilder.AddPass(RDG_EVENT_NAME("WireframeClear"), PassParameters, ERDGPassFlags::Raster, [](FRHICommandList&) {});
}
#endif
// Render targets bindings should remain constant at this point.
FRenderTargetBindingSlots BasePassRenderTargets = GetRenderTargetBindings(ERenderTargetLoadAction::ELoad, BasePassTexturesView);
BasePassRenderTargets.DepthStencil = FDepthStencilBinding(BasePassDepthTexture, ERenderTargetLoadAction::ELoad, ERenderTargetLoadAction::ELoad, ExclusiveDepthStencil);
BasePassRenderTargets.ShadingRateTexture = GVRSImageManager.GetVariableRateShadingImage(GraphBuilder, ViewFamily, nullptr, EVRSType::None);
FForwardBasePassTextures ForwardBasePassTextures{};
if (bForwardShadingEnabled)
{
ForwardBasePassTextures.SceneDepthIfResolved = SceneTextures.Depth.IsSeparate() ? SceneTextures.Depth.Resolve : nullptr;
ForwardBasePassTextures.ScreenSpaceAO = SceneTextures.ScreenSpaceAO;
ForwardBasePassTextures.ScreenSpaceShadowMask = ForwardShadowMaskTexture;
}
GraphBuilder.SetCommandListStat(GET_STATID(STAT_CLM_BasePass));
RenderBasePassInternal(GraphBuilder, SceneTextures, BasePassRenderTargets, BasePassDepthStencilAccess, ForwardBasePassTextures, DBufferTextures, bDoParallelBasePass, bRenderLightmapDensity, InstanceCullingManager, bNaniteEnabled, NaniteRasterResults);
GraphBuilder.SetCommandListStat(GET_STATID(STAT_CLM_AfterBasePass));
if (ViewFamily.ViewExtensions.Num() > 0)
{
SCOPE_CYCLE_COUNTER(STAT_FDeferredShadingSceneRenderer_ViewExtensionPostRenderBasePass);
RDG_EVENT_SCOPE(GraphBuilder, "BasePass_ViewExtensions");
auto* PassParameters = GraphBuilder.AllocParameters<FPostBasePassViewExtensionParameters>();
PassParameters->RenderTargets = BasePassRenderTargets;
PassParameters->SceneTextures = CreateSceneTextureUniformBuffer(GraphBuilder, FeatureLevel, ESceneTextureSetupMode::None);
GraphBuilder.AddPass(
{},
PassParameters,
ERDGPassFlags::Raster,
[this](FRHICommandListImmediate& RHICmdList)
{
for (auto& ViewExtension : ViewFamily.ViewExtensions)
{
for (FViewInfo& View : Views)
{
SCOPED_GPU_MASK(RHICmdList, View.GPUMask);
ViewExtension->PostRenderBasePass_RenderThread(RHICmdList, View);
}
}
});
}
if (bRequiresFarZQuadClear)
{
ClearGBufferAtMaxZ(GraphBuilder, Views, BasePassRenderTargets, SceneColorClearValue);
}
if (ShouldRenderAnisotropyPass(Views))
{
GraphBuilder.SetCommandListStat(GET_STATID(STAT_CLM_AnisotropyPass));
RenderAnisotropyPass(GraphBuilder, SceneTextures, bEnableParallelBasePasses);
GraphBuilder.SetCommandListStat(GET_STATID(STAT_CLM_AfterAnisotropyPass));
}
#if !(UE_BUILD_SHIPPING)
if (!bForwardShadingEnabled)
{
StampDeferredDebugProbeMaterialPS(GraphBuilder, Views, BasePassRenderTargets, SceneTextures);
}
#endif
Strata::PostBasePass(GraphBuilder, Views);
}
BEGIN_SHADER_PARAMETER_STRUCT(FOpaqueBasePassParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FViewShaderParameters, View)
SHADER_PARAMETER_STRUCT_REF(FReflectionCaptureShaderData, ReflectionCapture)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FOpaqueBasePassUniformParameters, BasePass)
SHADER_PARAMETER_STRUCT_INCLUDE(FInstanceCullingDrawParams, InstanceCullingDrawParams)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
static void RenderEditorPrimitivesForDPG(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
FOpaqueBasePassParameters* PassParameters,
const FMeshPassProcessorRenderState& DrawRenderState,
ESceneDepthPriorityGroup DepthPriorityGroup,
FInstanceCullingManager& InstanceCullingManager)
{
const FScene* Scene = View.Family->Scene->GetRenderScene();
GraphBuilder.AddPass(
RDG_EVENT_NAME("%s", *UEnum::GetValueAsString(DepthPriorityGroup)),
PassParameters,
ERDGPassFlags::Raster,
[&View, DrawRenderState, DepthPriorityGroup](FRHICommandListImmediate& RHICmdList)
{
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f);
View.SimpleElementCollector.DrawBatchedElements(RHICmdList, DrawRenderState, View, EBlendModeFilter::OpaqueAndMasked, DepthPriorityGroup);
if (!View.Family->EngineShowFlags.CompositeEditorPrimitives)
{
const bool bNeedToSwitchVerticalAxis = RHINeedsToSwitchVerticalAxis(View.GetShaderPlatform());
DrawDynamicMeshPass(View, RHICmdList,
[&View, &DrawRenderState](FDynamicPassMeshDrawListContext* DynamicMeshPassContext)
{
FEditorPrimitivesBasePassMeshProcessor PassMeshProcessor(
View.Family->Scene->GetRenderScene(),
View.GetFeatureLevel(),
&View,
DrawRenderState,
false,
DynamicMeshPassContext);
const uint64 DefaultBatchElementMask = ~0ull;
for (int32 MeshIndex = 0; MeshIndex < View.ViewMeshElements.Num(); MeshIndex++)
{
const FMeshBatch& MeshBatch = View.ViewMeshElements[MeshIndex];
PassMeshProcessor.AddMeshBatch(MeshBatch, DefaultBatchElementMask, nullptr);
}
});
const FBatchedElements& BatchedViewElements = DepthPriorityGroup == SDPG_World ? View.BatchedViewElements : View.TopBatchedViewElements;
DrawDynamicMeshPass(View, RHICmdList,
[&View, &DrawRenderState](FDynamicPassMeshDrawListContext* DynamicMeshPassContext)
{
FEditorPrimitivesBasePassMeshProcessor PassMeshProcessor(
View.Family->Scene->GetRenderScene(),
View.GetFeatureLevel(),
&View,
DrawRenderState,
false,
DynamicMeshPassContext);
const uint64 DefaultBatchElementMask = ~0ull;
for (int32 MeshIndex = 0; MeshIndex < View.TopViewMeshElements.Num(); MeshIndex++)
{
const FMeshBatch& MeshBatch = View.TopViewMeshElements[MeshIndex];
PassMeshProcessor.AddMeshBatch(MeshBatch, DefaultBatchElementMask, nullptr);
}
});
// Draw the view's batched simple elements(lines, sprites, etc).
View.TopBatchedViewElements.Draw(RHICmdList, DrawRenderState, View.GetFeatureLevel(), bNeedToSwitchVerticalAxis, View, false);
}
});
}
static bool HasEditorPrimitivesForDPG(const FViewInfo& View, ESceneDepthPriorityGroup DepthPriorityGroup)
{
bool bHasPrimitives = View.SimpleElementCollector.HasPrimitives(DepthPriorityGroup);
if (!View.Family->EngineShowFlags.CompositeEditorPrimitives)
{
const TIndirectArray<FMeshBatch>& ViewMeshElementList = (DepthPriorityGroup == SDPG_Foreground ? View.TopViewMeshElements : View.ViewMeshElements);
bHasPrimitives |= ViewMeshElementList.Num() > 0;
const FBatchedElements& BatchedViewElements = DepthPriorityGroup == SDPG_World ? View.BatchedViewElements : View.TopBatchedViewElements;
bHasPrimitives |= BatchedViewElements.HasPrimsToDraw();
}
return bHasPrimitives;
}
static void RenderEditorPrimitives(
FRDGBuilder& GraphBuilder,
FOpaqueBasePassParameters* PassParameters,
const FViewInfo& View,
const FMeshPassProcessorRenderState& DrawRenderState,
FInstanceCullingManager& InstanceCullingManager)
{
RDG_EVENT_SCOPE(GraphBuilder, "EditorPrimitives");
RenderEditorPrimitivesForDPG(GraphBuilder, View, PassParameters, DrawRenderState, SDPG_World, InstanceCullingManager);
if (HasEditorPrimitivesForDPG(View, SDPG_Foreground))
{
// Write foreground primitives into depth buffer without testing
{
auto* DepthWritePassParameters = GraphBuilder.AllocParameters<FOpaqueBasePassParameters>();
*DepthWritePassParameters = *PassParameters;
// Change to depth writable
DepthWritePassParameters->RenderTargets.DepthStencil.SetDepthStencilAccess(FExclusiveDepthStencil::DepthWrite_StencilWrite);
FMeshPassProcessorRenderState NoDepthTestDrawRenderState(DrawRenderState);
NoDepthTestDrawRenderState.SetDepthStencilState(TStaticDepthStencilState<true, CF_Always>::GetRHI());
NoDepthTestDrawRenderState.SetDepthStencilAccess(FExclusiveDepthStencil::DepthWrite_StencilWrite);
RenderEditorPrimitivesForDPG(GraphBuilder, View, DepthWritePassParameters, NoDepthTestDrawRenderState, SDPG_Foreground, InstanceCullingManager);
}
// Render foreground primitives with depth testing
RenderEditorPrimitivesForDPG(GraphBuilder, View, PassParameters, DrawRenderState, SDPG_Foreground, InstanceCullingManager);
}
}
void FDeferredShadingSceneRenderer::RenderBasePassInternal(
FRDGBuilder& GraphBuilder,
const FSceneTextures& SceneTextures,
const FRenderTargetBindingSlots& BasePassRenderTargets,
FExclusiveDepthStencil::Type BasePassDepthStencilAccess,
const FForwardBasePassTextures& ForwardBasePassTextures,
const FDBufferTextures& DBufferTextures,
bool bParallelBasePass,
bool bRenderLightmapDensity,
FInstanceCullingManager& InstanceCullingManager,
bool bNaniteEnabled,
const TArrayView<Nanite::FRasterResults>& NaniteRasterResults)
{
RDG_CSV_STAT_EXCLUSIVE_SCOPE(GraphBuilder, RenderBasePass);
SCOPED_NAMED_EVENT(FDeferredShadingSceneRenderer_RenderBasePass, FColor::Emerald);
#if WITH_DEBUG_VIEW_MODES
Nanite::EDebugViewMode NaniteDebugViewMode = Nanite::EDebugViewMode::None;
if (ViewFamily.EngineShowFlags.Wireframe)
{
NaniteDebugViewMode = Nanite::EDebugViewMode::Wireframe;
}
else if (bRenderLightmapDensity)
{
NaniteDebugViewMode = Nanite::EDebugViewMode::LightmapDensity;
}
else if (ViewFamily.UseDebugViewPS())
{
switch (ViewFamily.GetDebugViewShaderMode())
{
case DVSM_ShaderComplexity: // Default shader complexity viewmode
case DVSM_ShaderComplexityContainedQuadOverhead: // Show shader complexity with quad overdraw scaling the PS instruction count.
case DVSM_ShaderComplexityBleedingQuadOverhead: // Show shader complexity with quad overdraw bleeding the PS instruction count over the quad.
case DVSM_QuadComplexity: // Show quad overdraw only.
NaniteDebugViewMode = Nanite::EDebugViewMode::ShaderComplexity;
break;
default:
break;
}
}
#endif
FRDGTextureRef NaniteColorTarget = SceneTextures.Color.Target;
FRDGTextureRef NaniteDepthTarget = SceneTextures.Depth.Target;
#if WITH_EDITOR && WITH_DEBUG_VIEW_MODES
if (NaniteDebugViewMode == Nanite::EDebugViewMode::Wireframe)
{
NaniteColorTarget = SceneTextures.EditorPrimitiveColor;
NaniteDepthTarget = SceneTextures.EditorPrimitiveDepth;
}
#endif
auto RenderNaniteDepthPass = [&](FViewInfo& View, int32 ViewIndex)
{
// Emit Nanite depth if there was not an earlier depth pre-pass
if (!ShouldRenderPrePass())
{
Nanite::FRasterResults& RasterResults = NaniteRasterResults[ViewIndex];
// Emit velocity with depth if not writing it in base pass.
FRDGTexture* VelocityBuffer = !IsUsingBasePassVelocity(ShaderPlatform) ? SceneTextures.Velocity : nullptr;
const bool bEmitStencilMask = NANITE_MATERIAL_STENCIL != 0;
Nanite::EmitDepthTargets(
GraphBuilder,
*Scene,
View,
RasterResults.PageConstants,
RasterResults.VisibleClustersSWHW,
RasterResults.ViewsBuffer,
SceneTextures.Depth.Target,
RasterResults.VisBuffer64,
VelocityBuffer,
RasterResults.MaterialDepth,
RasterResults.MaterialResolve,
ShouldRenderPrePass(),
bEmitStencilMask
);
}
};
auto RenderNaniteBasePass = [&](FViewInfo& View, int32 ViewIndex)
{
Nanite::FRasterResults& RasterResults = NaniteRasterResults[ViewIndex];
#if WITH_DEBUG_VIEW_MODES
if (NaniteDebugViewMode != Nanite::EDebugViewMode::None)
{
Nanite::RenderDebugViewMode(
GraphBuilder,
NaniteDebugViewMode,
*Scene,
View,
ViewFamily,
RasterResults,
NaniteColorTarget,
NaniteDepthTarget,
SceneTextures.QuadOverdraw
);
}
else
#endif
{
Nanite::DrawBasePass(
GraphBuilder,
View.NaniteMaterialPassCommands,
*this,
SceneTextures,
DBufferTextures,
*Scene,
View,
RasterResults
);
}
};
if (bRenderLightmapDensity || ViewFamily.UseDebugViewPS())
{
if (bRenderLightmapDensity)
{
// Override the base pass with the lightmap density pass if the viewmode is enabled.
RenderLightMapDensities(GraphBuilder, Views, BasePassRenderTargets);
}
else if (ViewFamily.UseDebugViewPS())
{
// Override the base pass with one of the debug view shader mode (see EDebugViewShaderMode) if required.
RenderDebugViewMode(GraphBuilder, Views, SceneTextures.QuadOverdraw, BasePassRenderTargets);
}
// Debug view support for Nanite
if (bNaniteEnabled)
{
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
{
FViewInfo& View = Views[ViewIndex];
RDG_GPU_MASK_SCOPE(GraphBuilder, View.GPUMask);
RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Views.Num() > 1, "View%d", ViewIndex);
RenderNaniteDepthPass(View, ViewIndex);
RenderNaniteBasePass(View, ViewIndex);
}
}
}
else
{
SCOPE_CYCLE_COUNTER(STAT_BasePassDrawTime);
RDG_EVENT_SCOPE(GraphBuilder, "BasePass");
RDG_GPU_STAT_SCOPE(GraphBuilder, Basepass);
const bool bNeedsPrePass = ShouldRenderPrePass();
if (bParallelBasePass)
{
RDG_WAIT_FOR_TASKS_CONDITIONAL(GraphBuilder, IsBasePassWaitForTasksEnabled());
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
{
FViewInfo& View = Views[ViewIndex];
RDG_GPU_MASK_SCOPE(GraphBuilder, View.GPUMask);
RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Views.Num() > 1, "View%d", ViewIndex);
View.BeginRenderView();
FMeshPassProcessorRenderState DrawRenderState;
SetupBasePassState(BasePassDepthStencilAccess, ViewFamily.EngineShowFlags.ShaderComplexity, DrawRenderState);
FOpaqueBasePassParameters* PassParameters = GraphBuilder.AllocParameters<FOpaqueBasePassParameters>();
PassParameters->View = View.GetShaderParameters();
PassParameters->ReflectionCapture = View.ReflectionCaptureUniformBuffer;
PassParameters->BasePass = CreateOpaqueBasePassUniformBuffer(GraphBuilder, View, ViewIndex, ForwardBasePassTextures, DBufferTextures, nullptr);
PassParameters->RenderTargets = BasePassRenderTargets;
const bool bShouldRenderView = View.ShouldRenderView();
if (bShouldRenderView)
{
View.ParallelMeshDrawCommandPasses[EMeshPass::BasePass].BuildRenderingCommands(GraphBuilder, Scene->GPUScene, PassParameters->InstanceCullingDrawParams);
GraphBuilder.AddPass(
RDG_EVENT_NAME("BasePassParallel"),
PassParameters,
ERDGPassFlags::Raster | ERDGPassFlags::SkipRenderPass,
[this, &View, PassParameters](FRHICommandListImmediate& RHICmdList)
{
FRDGParallelCommandListSet ParallelCommandListSet(RHICmdList, GET_STATID(STAT_CLP_BasePass), *this, View, FParallelCommandListBindings(PassParameters));
View.ParallelMeshDrawCommandPasses[EMeshPass::BasePass].DispatchDraw(&ParallelCommandListSet, RHICmdList, &PassParameters->InstanceCullingDrawParams);
});
}
if (bNaniteEnabled)
{
RenderNaniteDepthPass(View, ViewIndex);
RenderNaniteBasePass(View, ViewIndex);
}
RenderEditorPrimitives(GraphBuilder, PassParameters, View, DrawRenderState, InstanceCullingManager);
if (bShouldRenderView && View.Family->EngineShowFlags.Atmosphere)
{
FOpaqueBasePassParameters* SkyPassPassParameters = GraphBuilder.AllocParameters<FOpaqueBasePassParameters>();
SkyPassPassParameters->BasePass = PassParameters->BasePass;
SkyPassPassParameters->RenderTargets = BasePassRenderTargets;
SkyPassPassParameters->View = View.GetShaderParameters();
SkyPassPassParameters->ReflectionCapture = View.ReflectionCaptureUniformBuffer;
View.ParallelMeshDrawCommandPasses[EMeshPass::SkyPass].BuildRenderingCommands(GraphBuilder, Scene->GPUScene, SkyPassPassParameters->InstanceCullingDrawParams);
GraphBuilder.AddPass(
RDG_EVENT_NAME("SkyPassParallel"),
SkyPassPassParameters,
ERDGPassFlags::Raster | ERDGPassFlags::SkipRenderPass,
[this, &View, SkyPassPassParameters](FRHICommandListImmediate& RHICmdList)
{
FRDGParallelCommandListSet ParallelCommandListSet(RHICmdList, GET_STATID(STAT_CLP_BasePass), *this, View, FParallelCommandListBindings(SkyPassPassParameters));
View.ParallelMeshDrawCommandPasses[EMeshPass::SkyPass].DispatchDraw(&ParallelCommandListSet, RHICmdList, &SkyPassPassParameters->InstanceCullingDrawParams);
});
}
}
}
else
{
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex)
{
FViewInfo& View = Views[ViewIndex];
RDG_GPU_MASK_SCOPE(GraphBuilder, View.GPUMask);
RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Views.Num() > 1, "View%d", ViewIndex);
View.BeginRenderView();
FMeshPassProcessorRenderState DrawRenderState;
SetupBasePassState(BasePassDepthStencilAccess, ViewFamily.EngineShowFlags.ShaderComplexity, DrawRenderState);
FOpaqueBasePassParameters* PassParameters = GraphBuilder.AllocParameters<FOpaqueBasePassParameters>();
PassParameters->View = View.GetShaderParameters();
PassParameters->ReflectionCapture = View.ReflectionCaptureUniformBuffer;
PassParameters->BasePass = CreateOpaqueBasePassUniformBuffer(GraphBuilder, View, ViewIndex, ForwardBasePassTextures, DBufferTextures, nullptr);
PassParameters->RenderTargets = BasePassRenderTargets;
const bool bShouldRenderView = View.ShouldRenderView();
if (bShouldRenderView)
{
View.ParallelMeshDrawCommandPasses[EMeshPass::BasePass].BuildRenderingCommands(GraphBuilder, Scene->GPUScene, PassParameters->InstanceCullingDrawParams);
GraphBuilder.AddPass(
RDG_EVENT_NAME("BasePass"),
PassParameters,
ERDGPassFlags::Raster,
[this, &View, PassParameters](FRHICommandList& RHICmdList)
{
SetStereoViewport(RHICmdList, View, 1.0f);
View.ParallelMeshDrawCommandPasses[EMeshPass::BasePass].DispatchDraw(nullptr, RHICmdList, &PassParameters->InstanceCullingDrawParams);
}
);
}
if (bNaniteEnabled)
{
RenderNaniteDepthPass(View, ViewIndex);
RenderNaniteBasePass(View, ViewIndex);
}
RenderEditorPrimitives(GraphBuilder, PassParameters, View, DrawRenderState, InstanceCullingManager);
if (bShouldRenderView && View.Family->EngineShowFlags.Atmosphere)
{
FOpaqueBasePassParameters* SkyPassParameters = GraphBuilder.AllocParameters<FOpaqueBasePassParameters>();
SkyPassParameters->BasePass = PassParameters->BasePass;
SkyPassParameters->RenderTargets = BasePassRenderTargets;
SkyPassParameters->View = View.GetShaderParameters();
SkyPassParameters->ReflectionCapture = View.ReflectionCaptureUniformBuffer;
View.ParallelMeshDrawCommandPasses[EMeshPass::SkyPass].BuildRenderingCommands(GraphBuilder, Scene->GPUScene, SkyPassParameters->InstanceCullingDrawParams);
GraphBuilder.AddPass(
RDG_EVENT_NAME("SkyPass"),
SkyPassParameters,
ERDGPassFlags::Raster,
[this, &View, SkyPassParameters](FRHICommandList& RHICmdList)
{
SetStereoViewport(RHICmdList, View, 1.0f);
View.ParallelMeshDrawCommandPasses[EMeshPass::SkyPass].DispatchDraw(nullptr, RHICmdList, &SkyPassParameters->InstanceCullingDrawParams);
}
);
}
}
}
}
}
template<typename LightMapPolicyType>
bool FBasePassMeshProcessor::Process(
const FMeshBatch& RESTRICT MeshBatch,
uint64 BatchElementMask,
int32 StaticMeshId,
const FPrimitiveSceneProxy* RESTRICT PrimitiveSceneProxy,
const FMaterialRenderProxy& RESTRICT MaterialRenderProxy,
const FMaterial& RESTRICT MaterialResource,
EBlendMode BlendMode,
FMaterialShadingModelField ShadingModels,
const LightMapPolicyType& RESTRICT LightMapPolicy,
const typename LightMapPolicyType::ElementDataType& RESTRICT LightMapElementData,
ERasterizerFillMode MeshFillMode,
ERasterizerCullMode MeshCullMode)
{
const FVertexFactory* VertexFactory = MeshBatch.VertexFactory;
const bool bRenderSkylight = Scene && Scene->ShouldRenderSkylightInBasePass(BlendMode) && ShadingModels.IsLit();
TMeshProcessorShaders<
TBasePassVertexShaderPolicyParamType<LightMapPolicyType>,
TBasePassPixelShaderPolicyParamType<LightMapPolicyType>> BasePassShaders;
if (!GetBasePassShaders<LightMapPolicyType>(
MaterialResource,
VertexFactory->GetType(),
LightMapPolicy,
FeatureLevel,
bRenderSkylight,
Get128BitRequirement(),
&BasePassShaders.VertexShader,
&BasePassShaders.PixelShader
))
{
return false;
}
FMeshPassProcessorRenderState DrawRenderState(PassDrawRenderState);
SetDepthStencilStateForBasePass(
ViewIfDynamicMeshCommand,
DrawRenderState,
FeatureLevel,
MeshBatch,
StaticMeshId,
PrimitiveSceneProxy,
MaterialResource,
bEnableReceiveDecalOutput);
if (bTranslucentBasePass)
{
SetTranslucentRenderState(DrawRenderState, MaterialResource, GShaderPlatformForFeatureLevel[FeatureLevel], TranslucencyPassType);
}
TBasePassShaderElementData<LightMapPolicyType> ShaderElementData(LightMapElementData);
ShaderElementData.InitializeMeshMaterialData(ViewIfDynamicMeshCommand, PrimitiveSceneProxy, MeshBatch, StaticMeshId, true);
FMeshDrawCommandSortKey SortKey = FMeshDrawCommandSortKey::Default;
if (bTranslucentBasePass)
{
SortKey = CalculateTranslucentMeshStaticSortKey(PrimitiveSceneProxy, MeshBatch.MeshIdInPrimitive);
}
else
{
SortKey = CalculateBasePassMeshStaticSortKey(EarlyZPassMode, BlendMode, BasePassShaders.VertexShader.GetShader(), BasePassShaders.PixelShader.GetShader());
}
BuildMeshDrawCommands(
MeshBatch,
BatchElementMask,
PrimitiveSceneProxy,
MaterialRenderProxy,
MaterialResource,
DrawRenderState,
BasePassShaders,
MeshFillMode,
MeshCullMode,
SortKey,
EMeshPassFeatures::Default,
ShaderElementData);
return true;
}
bool FBasePassMeshProcessor::AddMeshBatchForSimpleForwardShading(
const FMeshBatch& RESTRICT MeshBatch,
uint64 BatchElementMask,
int32 StaticMeshId,
const FPrimitiveSceneProxy* RESTRICT PrimitiveSceneProxy,
const FMaterialRenderProxy& MaterialRenderProxy,
const FMaterial& Material,
const FLightMapInteraction& LightMapInteraction,
bool bIsLitMaterial,
bool bAllowStaticLighting,
bool bUseVolumetricLightmap,
bool bAllowIndirectLightingCache,
ERasterizerFillMode MeshFillMode,
ERasterizerCullMode MeshCullMode)
{
const EBlendMode BlendMode = Material.GetBlendMode();
const FMaterialShadingModelField ShadingModels = Material.GetShadingModels();
bool bResult = false;
if (bAllowStaticLighting && LightMapInteraction.GetType() == LMIT_Texture)
{
const FShadowMapInteraction ShadowMapInteraction = (MeshBatch.LCI && bIsLitMaterial)
? MeshBatch.LCI->GetShadowMapInteraction(FeatureLevel)
: FShadowMapInteraction();
if (ShadowMapInteraction.GetType() == SMIT_Texture)
{
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_SIMPLE_STATIONARY_PRECOMPUTED_SHADOW_LIGHTING),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
else
{
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_SIMPLE_LIGHTMAP_ONLY_LIGHTING),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
}
else if (bIsLitMaterial
&& bAllowStaticLighting
&& bUseVolumetricLightmap
&& PrimitiveSceneProxy)
{
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_SIMPLE_STATIONARY_VOLUMETRICLIGHTMAP_SHADOW_LIGHTING),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
else if (bIsLitMaterial
&& IsIndirectLightingCacheAllowed(FeatureLevel)
&& bAllowIndirectLightingCache
&& PrimitiveSceneProxy)
{
const FIndirectLightingCacheAllocation* IndirectLightingCacheAllocation = PrimitiveSceneProxy->GetPrimitiveSceneInfo()->IndirectLightingCacheAllocation;
const bool bPrimitiveIsMovable = PrimitiveSceneProxy->IsMovable();
const bool bPrimitiveUsesILC = PrimitiveSceneProxy->GetIndirectLightingCacheQuality() != ILCQ_Off;
// Use the indirect lighting cache shaders if the object has a cache allocation
// This happens for objects with unbuilt lighting
if (bPrimitiveUsesILC &&
((IndirectLightingCacheAllocation && IndirectLightingCacheAllocation->IsValid())
// Use the indirect lighting cache shaders if the object is movable, it may not have a cache allocation yet because that is done in InitViews
// And movable objects are sometimes rendered in the static draw lists
|| bPrimitiveIsMovable))
{
// Use a lightmap policy that supports reading indirect lighting from a single SH sample
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_SIMPLE_STATIONARY_SINGLESAMPLE_SHADOW_LIGHTING),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
else
{
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_SIMPLE_NO_LIGHTMAP),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
}
else if (bIsLitMaterial)
{
// Always choosing shaders to support dynamic directional even if one is not present
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_SIMPLE_DIRECTIONAL_LIGHT_LIGHTING),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
else
{
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_SIMPLE_NO_LIGHTMAP),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
return bResult;
}
void FBasePassMeshProcessor::AddMeshBatch(const FMeshBatch& RESTRICT MeshBatch, uint64 BatchElementMask, const FPrimitiveSceneProxy* RESTRICT PrimitiveSceneProxy, int32 StaticMeshId)
{
if (MeshBatch.bUseForMaterial)
{
// Determine the mesh's material and blend mode.
const FMaterialRenderProxy* MaterialRenderProxy = MeshBatch.MaterialRenderProxy;
while (MaterialRenderProxy)
{
const FMaterial* Material = MaterialRenderProxy->GetMaterialNoFallback(FeatureLevel);
if (Material && Material->GetRenderingThreadShaderMap())
{
if (TryAddMeshBatch(MeshBatch, BatchElementMask, PrimitiveSceneProxy, StaticMeshId, *MaterialRenderProxy, *Material))
{
break;
}
}
MaterialRenderProxy = MaterialRenderProxy->GetFallback(FeatureLevel);
}
}
}
bool FBasePassMeshProcessor::TryAddMeshBatch(const FMeshBatch& RESTRICT MeshBatch, uint64 BatchElementMask, const FPrimitiveSceneProxy* RESTRICT PrimitiveSceneProxy, int32 StaticMeshId, const FMaterialRenderProxy& MaterialRenderProxy, const FMaterial& Material)
{
// Determine the mesh's material and blend mode.
const EBlendMode BlendMode = Material.GetBlendMode();
const FMaterialShadingModelField ShadingModels = Material.GetShadingModels();
const bool bIsTranslucent = IsTranslucentBlendMode(BlendMode);
const FMeshDrawingPolicyOverrideSettings OverrideSettings = ComputeMeshOverrideSettings(MeshBatch);
const ERasterizerFillMode MeshFillMode = ComputeMeshFillMode(MeshBatch, Material, OverrideSettings);
const ERasterizerCullMode MeshCullMode = ComputeMeshCullMode(MeshBatch, Material, OverrideSettings);
bool bShouldDraw = false;
if (bTranslucentBasePass)
{
if (bIsTranslucent && !Material.IsDeferredDecal())
{
switch (TranslucencyPassType)
{
case ETranslucencyPass::TPT_StandardTranslucency:
bShouldDraw = !Material.IsTranslucencyAfterDOFEnabled() && !Material.IsTranslucencyAfterMotionBlurEnabled();
break;
case ETranslucencyPass::TPT_TranslucencyAfterDOF:
bShouldDraw = Material.IsTranslucencyAfterDOFEnabled();
break;
// only dual blended or modulate surfaces need background modulation
case ETranslucencyPass::TPT_TranslucencyAfterDOFModulate:
bShouldDraw = Material.IsTranslucencyAfterDOFEnabled() && (Material.IsDualBlendingEnabled(GetFeatureLevelShaderPlatform(FeatureLevel)) || BlendMode == BLEND_Modulate);
break;
case ETranslucencyPass::TPT_TranslucencyAfterMotionBlur:
bShouldDraw = Material.IsTranslucencyAfterMotionBlurEnabled();
break;
case ETranslucencyPass::TPT_AllTranslucency:
bShouldDraw = true;
break;
}
}
}
else
{
bShouldDraw = !bIsTranslucent;
}
// Only draw opaque materials.
bool bResult = true;
if (bShouldDraw
&& (!PrimitiveSceneProxy || PrimitiveSceneProxy->ShouldRenderInMainPass())
&& ShouldIncludeDomainInMeshPass(Material.GetMaterialDomain())
&& ShouldIncludeMaterialInDefaultOpaquePass(Material))
{
// Check for a cached light-map.
const bool bIsLitMaterial = ShadingModels.IsLit();
static const auto AllowStaticLightingVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.AllowStaticLighting"));
const bool bAllowStaticLighting = (!AllowStaticLightingVar || AllowStaticLightingVar->GetValueOnRenderThread() != 0);
const FLightMapInteraction LightMapInteraction = (bAllowStaticLighting && MeshBatch.LCI && bIsLitMaterial)
? MeshBatch.LCI->GetLightMapInteraction(FeatureLevel)
: FLightMapInteraction();
// force LQ lightmaps based on system settings
const bool bPlatformAllowsHighQualityLightMaps = AllowHighQualityLightmaps(FeatureLevel);
const bool bAllowHighQualityLightMaps = bPlatformAllowsHighQualityLightMaps && LightMapInteraction.AllowsHighQualityLightmaps();
const bool bAllowIndirectLightingCache = Scene && Scene->PrecomputedLightVolumes.Num() > 0;
const bool bUseVolumetricLightmap = Scene && Scene->VolumetricLightmapSceneData.HasData();
FMeshMaterialShaderElementData MeshMaterialShaderElementData;
MeshMaterialShaderElementData.InitializeMeshMaterialData(ViewIfDynamicMeshCommand, PrimitiveSceneProxy, MeshBatch, StaticMeshId, true);
if (IsSimpleForwardShadingEnabled(GetFeatureLevelShaderPlatform(FeatureLevel)))
{
// Only compiling simple lighting shaders for HQ lightmaps to save on permutations
check(bPlatformAllowsHighQualityLightMaps);
bResult = AddMeshBatchForSimpleForwardShading(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
LightMapInteraction,
bIsLitMaterial,
bAllowStaticLighting,
bUseVolumetricLightmap,
bAllowIndirectLightingCache,
MeshFillMode,
MeshCullMode);
}
// Render volumetric translucent self-shadowing only for >= SM4 and fallback to non-shadowed for lesser shader models
else if (bIsLitMaterial
&& bIsTranslucent
&& PrimitiveSceneProxy
&& PrimitiveSceneProxy->CastsVolumetricTranslucentShadow())
{
checkSlow(ViewIfDynamicMeshCommand && ViewIfDynamicMeshCommand->bIsViewInfo);
const FViewInfo* ViewInfo = (FViewInfo*)ViewIfDynamicMeshCommand;
const int32 PrimitiveIndex = PrimitiveSceneProxy->GetPrimitiveSceneInfo()->GetIndex();
const FUniformBufferRHIRef* UniformBufferPtr = ViewInfo->TranslucentSelfShadowUniformBufferMap.Find(PrimitiveIndex);
FSelfShadowLightCacheElementData ElementData;
ElementData.LCI = MeshBatch.LCI;
ElementData.SelfShadowTranslucencyUniformBuffer = UniformBufferPtr ? (*UniformBufferPtr).GetReference() : GEmptyTranslucentSelfShadowUniformBuffer.GetUniformBufferRHI();
if (bIsLitMaterial
&& bAllowStaticLighting
&& bUseVolumetricLightmap
&& PrimitiveSceneProxy)
{
bResult = Process< FSelfShadowedVolumetricLightmapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FSelfShadowedVolumetricLightmapPolicy(),
ElementData,
MeshFillMode,
MeshCullMode);
}
else if (IsIndirectLightingCacheAllowed(FeatureLevel)
&& bAllowIndirectLightingCache
&& PrimitiveSceneProxy)
{
// Apply cached point indirect lighting as well as self shadowing if needed
bResult = Process< FSelfShadowedCachedPointIndirectLightingPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FSelfShadowedCachedPointIndirectLightingPolicy(),
ElementData,
MeshFillMode,
MeshCullMode);
}
else
{
bResult = Process< FSelfShadowedTranslucencyPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FSelfShadowedTranslucencyPolicy(),
ElementData.SelfShadowTranslucencyUniformBuffer,
MeshFillMode,
MeshCullMode);
}
}
else
{
static const auto CVarSupportLowQualityLightmap = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.SupportLowQualityLightmaps"));
const bool bAllowLowQualityLightMaps = (!CVarSupportLowQualityLightmap) || (CVarSupportLowQualityLightmap->GetValueOnAnyThread() != 0);
switch (LightMapInteraction.GetType())
{
case LMIT_Texture:
if (bAllowHighQualityLightMaps)
{
const FShadowMapInteraction ShadowMapInteraction = (bAllowStaticLighting && MeshBatch.LCI && bIsLitMaterial)
? MeshBatch.LCI->GetShadowMapInteraction(FeatureLevel)
: FShadowMapInteraction();
if (ShadowMapInteraction.GetType() == SMIT_Texture)
{
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_DISTANCE_FIELD_SHADOWS_AND_HQ_LIGHTMAP),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
else
{
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_HQ_LIGHTMAP),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
}
else if (bAllowLowQualityLightMaps)
{
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_LQ_LIGHTMAP),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
else
{
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_NO_LIGHTMAP),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
break;
default:
if (bIsLitMaterial
&& bAllowStaticLighting
&& Scene
&& Scene->VolumetricLightmapSceneData.HasData()
&& PrimitiveSceneProxy
&& (PrimitiveSceneProxy->IsMovable()
|| PrimitiveSceneProxy->NeedsUnbuiltPreviewLighting()
|| PrimitiveSceneProxy->GetLightmapType() == ELightmapType::ForceVolumetric))
{
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_PRECOMPUTED_IRRADIANCE_VOLUME_INDIRECT_LIGHTING),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
else if (bIsLitMaterial
&& IsIndirectLightingCacheAllowed(FeatureLevel)
&& Scene
&& Scene->PrecomputedLightVolumes.Num() > 0
&& PrimitiveSceneProxy)
{
const FIndirectLightingCacheAllocation* IndirectLightingCacheAllocation = PrimitiveSceneProxy->GetPrimitiveSceneInfo()->IndirectLightingCacheAllocation;
const bool bPrimitiveIsMovable = PrimitiveSceneProxy->IsMovable();
const bool bPrimitiveUsesILC = PrimitiveSceneProxy->GetIndirectLightingCacheQuality() != ILCQ_Off;
// Use the indirect lighting cache shaders if the object has a cache allocation
// This happens for objects with unbuilt lighting
if (bPrimitiveUsesILC &&
((IndirectLightingCacheAllocation && IndirectLightingCacheAllocation->IsValid())
// Use the indirect lighting cache shaders if the object is movable, it may not have a cache allocation yet because that is done in InitViews
// And movable objects are sometimes rendered in the static draw lists
|| bPrimitiveIsMovable))
{
if (CanIndirectLightingCacheUseVolumeTexture(FeatureLevel)
// Translucency forces point sample for pixel performance
&& !bIsTranslucent
&& ((IndirectLightingCacheAllocation && !IndirectLightingCacheAllocation->bPointSample)
|| (bPrimitiveIsMovable && PrimitiveSceneProxy->GetIndirectLightingCacheQuality() == ILCQ_Volume)))
{
// Use a lightmap policy that supports reading indirect lighting from a volume texture for dynamic objects
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_CACHED_VOLUME_INDIRECT_LIGHTING),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
else
{
// Use a lightmap policy that supports reading indirect lighting from a single SH sample
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_CACHED_POINT_INDIRECT_LIGHTING),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
}
else
{
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_NO_LIGHTMAP),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
}
else
{
bResult = Process< FUniformLightMapPolicy >(
MeshBatch,
BatchElementMask,
StaticMeshId,
PrimitiveSceneProxy,
MaterialRenderProxy,
Material,
BlendMode,
ShadingModels,
FUniformLightMapPolicy(LMP_NO_LIGHTMAP),
MeshBatch.LCI,
MeshFillMode,
MeshCullMode);
}
break;
};
}
}
return bResult;
}
FBasePassMeshProcessor::FBasePassMeshProcessor(
const FScene* Scene,
ERHIFeatureLevel::Type InFeatureLevel,
const FSceneView* InViewIfDynamicMeshCommand,
const FMeshPassProcessorRenderState& InDrawRenderState,
FMeshPassDrawListContext* InDrawListContext,
EFlags Flags,
ETranslucencyPass::Type InTranslucencyPassType)
: FMeshPassProcessor(Scene, InFeatureLevel, InViewIfDynamicMeshCommand, InDrawListContext)
, PassDrawRenderState(InDrawRenderState)
, TranslucencyPassType(InTranslucencyPassType)
, bTranslucentBasePass(InTranslucencyPassType != ETranslucencyPass::TPT_MAX)
, bEnableReceiveDecalOutput((Flags & EFlags::CanUseDepthStencil) == EFlags::CanUseDepthStencil)
, EarlyZPassMode(Scene ? Scene->EarlyZPassMode : DDM_None)
, bRequiresExplicit128bitRT((Flags & EFlags::bRequires128bitRT) == EFlags::bRequires128bitRT)
{
}
FMeshPassProcessor* CreateBasePassProcessor(const FScene* Scene, const FSceneView* InViewIfDynamicMeshCommand, FMeshPassDrawListContext* InDrawListContext)
{
FMeshPassProcessorRenderState PassDrawRenderState;
SetupBasePassState(Scene->DefaultBasePassDepthStencilAccess, false, PassDrawRenderState);
const FBasePassMeshProcessor::EFlags Flags = FBasePassMeshProcessor::EFlags::CanUseDepthStencil;
return new(FMemStack::Get()) FBasePassMeshProcessor(Scene, Scene->GetFeatureLevel(), InViewIfDynamicMeshCommand, PassDrawRenderState, InDrawListContext, Flags);
}
FMeshPassProcessor* CreateTranslucencyStandardPassProcessor(const FScene* Scene, const FSceneView* InViewIfDynamicMeshCommand, FMeshPassDrawListContext* InDrawListContext)
{
FMeshPassProcessorRenderState PassDrawRenderState;
PassDrawRenderState.SetDepthStencilState(TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI());
const FBasePassMeshProcessor::EFlags Flags = FBasePassMeshProcessor::EFlags::CanUseDepthStencil;
return new(FMemStack::Get()) FBasePassMeshProcessor(Scene, Scene->GetFeatureLevel(), InViewIfDynamicMeshCommand, PassDrawRenderState, InDrawListContext, Flags, ETranslucencyPass::TPT_StandardTranslucency);
}
FMeshPassProcessor* CreateTranslucencyAfterDOFProcessor(const FScene* Scene, const FSceneView* InViewIfDynamicMeshCommand, FMeshPassDrawListContext* InDrawListContext)
{
FMeshPassProcessorRenderState PassDrawRenderState;
PassDrawRenderState.SetDepthStencilState(TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI());
const FBasePassMeshProcessor::EFlags Flags = FBasePassMeshProcessor::EFlags::CanUseDepthStencil;
return new(FMemStack::Get()) FBasePassMeshProcessor(Scene, Scene->GetFeatureLevel(), InViewIfDynamicMeshCommand, PassDrawRenderState, InDrawListContext, Flags, ETranslucencyPass::TPT_TranslucencyAfterDOF);
}
FMeshPassProcessor* CreateTranslucencyAfterDOFModulateProcessor(const FScene* Scene, const FSceneView* InViewIfDynamicMeshCommand, FMeshPassDrawListContext* InDrawListContext)
{
FMeshPassProcessorRenderState PassDrawRenderState;
PassDrawRenderState.SetDepthStencilState(TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI());
const FBasePassMeshProcessor::EFlags Flags = FBasePassMeshProcessor::EFlags::CanUseDepthStencil;
return new(FMemStack::Get()) FBasePassMeshProcessor(Scene, Scene->GetFeatureLevel(), InViewIfDynamicMeshCommand, PassDrawRenderState, InDrawListContext, Flags, ETranslucencyPass::TPT_TranslucencyAfterDOFModulate);
}
FMeshPassProcessor* CreateTranslucencyAfterMotionBlurProcessor(const FScene* Scene, const FSceneView* InViewIfDynamicMeshCommand, FMeshPassDrawListContext* InDrawListContext)
{
FMeshPassProcessorRenderState PassDrawRenderState;
PassDrawRenderState.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
PassDrawRenderState.SetDepthStencilAccess(FExclusiveDepthStencil::DepthNop_StencilNop);
const FBasePassMeshProcessor::EFlags Flags = FBasePassMeshProcessor::EFlags::None;
return new(FMemStack::Get()) FBasePassMeshProcessor(Scene, Scene->GetFeatureLevel(), InViewIfDynamicMeshCommand, PassDrawRenderState, InDrawListContext, Flags, ETranslucencyPass::TPT_TranslucencyAfterMotionBlur);
}
FMeshPassProcessor* CreateTranslucencyAllPassProcessor(const FScene* Scene, const FSceneView* InViewIfDynamicMeshCommand, FMeshPassDrawListContext* InDrawListContext)
{
FMeshPassProcessorRenderState PassDrawRenderState;
PassDrawRenderState.SetDepthStencilState(TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI());
const FBasePassMeshProcessor::EFlags Flags = FBasePassMeshProcessor::EFlags::CanUseDepthStencil;
return new(FMemStack::Get()) FBasePassMeshProcessor(Scene, Scene->GetFeatureLevel(), InViewIfDynamicMeshCommand, PassDrawRenderState, InDrawListContext, Flags, ETranslucencyPass::TPT_AllTranslucency);
}
FRegisterPassProcessorCreateFunction RegisterBasePass(&CreateBasePassProcessor, EShadingPath::Deferred, EMeshPass::BasePass, EMeshPassFlags::CachedMeshCommands | EMeshPassFlags::MainView);
FRegisterPassProcessorCreateFunction RegisterTranslucencyStandardPass(&CreateTranslucencyStandardPassProcessor, EShadingPath::Deferred, EMeshPass::TranslucencyStandard, EMeshPassFlags::MainView);
FRegisterPassProcessorCreateFunction RegisterTranslucencyAfterDOFPass(&CreateTranslucencyAfterDOFProcessor, EShadingPath::Deferred, EMeshPass::TranslucencyAfterDOF, EMeshPassFlags::MainView);
FRegisterPassProcessorCreateFunction RegisterTranslucencyAfterDOFModulatePass(&CreateTranslucencyAfterDOFModulateProcessor, EShadingPath::Deferred, EMeshPass::TranslucencyAfterDOFModulate, EMeshPassFlags::MainView);
FRegisterPassProcessorCreateFunction RegisterTranslucencyAfterMotionBlurPass(&CreateTranslucencyAfterMotionBlurProcessor, EShadingPath::Deferred, EMeshPass::TranslucencyAfterMotionBlur, EMeshPassFlags::MainView);
FRegisterPassProcessorCreateFunction RegisterTranslucencyAllPass(&CreateTranslucencyAllPassProcessor, EShadingPath::Deferred, EMeshPass::TranslucencyAll, EMeshPassFlags::MainView);