// Copyright Epic Games, Inc. All Rights Reserved. /*============================================================================= MobileBasePassRendering.cpp: Base pass rendering implementation. =============================================================================*/ #include "MobileBasePassRendering.h" #include "DynamicPrimitiveDrawing.h" #include "ScenePrivate.h" #include "SceneTextureParameters.h" #include "ShaderPlatformQualitySettings.h" #include "MaterialShaderQualitySettings.h" #include "PrimitiveSceneInfo.h" #include "MeshPassProcessor.h" #include "MeshPassProcessor.inl" #include "EditorPrimitivesRendering.h" #include "FramePro/FrameProProfiler.h" #include "PostProcess/PostProcessPixelProjectedReflectionMobile.h" #include "Engine/SubsurfaceProfile.h" #include "LocalLightSceneProxy.h" #include "ReflectionEnvironment.h" // Changing this causes a full shader recompile static TAutoConsoleVariable CVarMobileDisableVertexFog( TEXT("r.Mobile.DisableVertexFog"), 0, TEXT("Set to 1 to disable vertex fogging in all mobile shaders."), ECVF_ReadOnly | ECVF_RenderThreadSafe); static TAutoConsoleVariable CVarMobileEnableMovableSpotLightShadows( TEXT("r.Mobile.EnableMovableSpotlightsShadow"), 0, TEXT("If 1 then enable movable spotlight shadow support"), ECVF_ReadOnly | ECVF_RenderThreadSafe); static TAutoConsoleVariable CVarMobileMaxVisibleMovableSpotLightShadows( TEXT("r.Mobile.MaxVisibleMovableSpotLightShadows"), 8, TEXT("The max number of visible spotlighs can cast shadow sorted by screen size, should be as less as possible for performance reason"), ECVF_RenderThreadSafe); static TAutoConsoleVariable CVarMobileSceneDepthAux( TEXT("r.Mobile.SceneDepthAux"), 1, TEXT("1: 16F SceneDepthAux Format") TEXT("2: 32F SceneDepthAux Format"), ECVF_Scalability | ECVF_RenderThreadSafe); static TAutoConsoleVariable CVarMobilePropagateAlpha( TEXT("r.Mobile.PropagateAlpha"), 0, TEXT("0: Disabled") TEXT("1: Propagate Full Alpha Propagate"), ECVF_ReadOnly | ECVF_RenderThreadSafe); IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT(FMobileBasePassUniformParameters, "MobileBasePass", SceneTextures); static TAutoConsoleVariable CVarMobileUseHWsRGBEncoding( TEXT("r.Mobile.UseHWsRGBEncoding"), 0, TEXT("0: Write sRGB encoding in the shader\n") TEXT("1: Use GPU HW to convert linear to sRGB automatically (device must support sRGB write control)\n"), ECVF_RenderThreadSafe); bool ShouldCacheShaderByPlatformAndOutputFormat(EShaderPlatform Platform, EOutputFormat OutputFormat) { bool bSupportsMobileHDR = IsMobileHDR(); bool bShaderUsesLDR = (OutputFormat == LDR_GAMMA_32); // only cache this shader if the LDR/HDR output matches what we currently support. IsMobileHDR can't change, so we don't need // the LDR shaders if we are doing HDR, and vice-versa. return (bShaderUsesLDR && !bSupportsMobileHDR) || (!bShaderUsesLDR && bSupportsMobileHDR); } #define IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_VERTEX_SHADER_TYPE(LightMapPolicyType,LightMapPolicyName) \ typedef TMobileBasePassVS< LightMapPolicyType, LDR_GAMMA_32 > TMobileBasePassVS##LightMapPolicyName##LDRGamma32; \ typedef TMobileBasePassVS< LightMapPolicyType, HDR_LINEAR_64 > TMobileBasePassVS##LightMapPolicyName##HDRLinear64; \ IMPLEMENT_MATERIAL_SHADER_TYPE(template<>, TMobileBasePassVS##LightMapPolicyName##LDRGamma32, TEXT("/Engine/Private/MobileBasePassVertexShader.usf"), TEXT("Main"), SF_Vertex); \ IMPLEMENT_MATERIAL_SHADER_TYPE(template<>, TMobileBasePassVS##LightMapPolicyName##HDRLinear64, TEXT("/Engine/Private/MobileBasePassVertexShader.usf"), TEXT("Main"), SF_Vertex); #define IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_PIXEL_SHADER_TYPE(LightMapPolicyType,LightMapPolicyName) \ typedef TMobileBasePassPS< LightMapPolicyType, LDR_GAMMA_32, false, false > TMobileBasePassPS##LightMapPolicyName##LDRGamma32; \ typedef TMobileBasePassPS< LightMapPolicyType, HDR_LINEAR_64, false, false > TMobileBasePassPS##LightMapPolicyName##HDRLinear64; \ typedef TMobileBasePassPS< LightMapPolicyType, LDR_GAMMA_32, true, false > TMobileBasePassPS##LightMapPolicyName##LDRGamma32##Skylight; \ typedef TMobileBasePassPS< LightMapPolicyType, HDR_LINEAR_64, true, false > TMobileBasePassPS##LightMapPolicyName##HDRLinear64##Skylight; \ typedef TMobileBasePassPS< LightMapPolicyType, LDR_GAMMA_32, false, true > TMobileBasePassPS##LightMapPolicyName##LDRGamma32##EnableLocalLights; \ typedef TMobileBasePassPS< LightMapPolicyType, HDR_LINEAR_64, false, true > TMobileBasePassPS##LightMapPolicyName##HDRLinear64##EnableLocalLights; \ typedef TMobileBasePassPS< LightMapPolicyType, LDR_GAMMA_32, true, true > TMobileBasePassPS##LightMapPolicyName##LDRGamma32##Skylight##EnableLocalLights; \ typedef TMobileBasePassPS< LightMapPolicyType, HDR_LINEAR_64, true, true > TMobileBasePassPS##LightMapPolicyName##HDRLinear64##Skylight##EnableLocalLights; \ IMPLEMENT_MATERIAL_SHADER_TYPE(template<>, TMobileBasePassPS##LightMapPolicyName##LDRGamma32, TEXT("/Engine/Private/MobileBasePassPixelShader.usf"), TEXT("Main"), SF_Pixel); \ IMPLEMENT_MATERIAL_SHADER_TYPE(template<>, TMobileBasePassPS##LightMapPolicyName##HDRLinear64, TEXT("/Engine/Private/MobileBasePassPixelShader.usf"), TEXT("Main"), SF_Pixel); \ IMPLEMENT_MATERIAL_SHADER_TYPE(template<>, TMobileBasePassPS##LightMapPolicyName##LDRGamma32##Skylight, TEXT("/Engine/Private/MobileBasePassPixelShader.usf"), TEXT("Main"), SF_Pixel); \ IMPLEMENT_MATERIAL_SHADER_TYPE(template<>, TMobileBasePassPS##LightMapPolicyName##HDRLinear64##Skylight, TEXT("/Engine/Private/MobileBasePassPixelShader.usf"), TEXT("Main"), SF_Pixel) \ IMPLEMENT_MATERIAL_SHADER_TYPE(template<>, TMobileBasePassPS##LightMapPolicyName##LDRGamma32##EnableLocalLights, TEXT("/Engine/Private/MobileBasePassPixelShader.usf"), TEXT("Main"), SF_Pixel); \ IMPLEMENT_MATERIAL_SHADER_TYPE(template<>, TMobileBasePassPS##LightMapPolicyName##HDRLinear64##EnableLocalLights, TEXT("/Engine/Private/MobileBasePassPixelShader.usf"), TEXT("Main"), SF_Pixel); \ IMPLEMENT_MATERIAL_SHADER_TYPE(template<>, TMobileBasePassPS##LightMapPolicyName##LDRGamma32##Skylight##EnableLocalLights, TEXT("/Engine/Private/MobileBasePassPixelShader.usf"), TEXT("Main"), SF_Pixel); \ IMPLEMENT_MATERIAL_SHADER_TYPE(template<>, TMobileBasePassPS##LightMapPolicyName##HDRLinear64##Skylight##EnableLocalLights, TEXT("/Engine/Private/MobileBasePassPixelShader.usf"), TEXT("Main"), SF_Pixel); #define IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_SHADER_TYPE(LightMapPolicyType,LightMapPolicyName) \ IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_VERTEX_SHADER_TYPE(LightMapPolicyType, LightMapPolicyName) \ IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_PIXEL_SHADER_TYPE(LightMapPolicyType, LightMapPolicyName) // Implement shader types per lightmap policy IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_SHADER_TYPE(TUniformLightMapPolicy, FNoLightMapPolicy); IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_SHADER_TYPE(TUniformLightMapPolicy, TLightMapPolicyLQ); IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_SHADER_TYPE(TUniformLightMapPolicy, FMobileDistanceFieldShadowsAndLQLightMapPolicy); IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_SHADER_TYPE(TUniformLightMapPolicy, FMobileDistanceFieldShadowsLightMapAndCSMLightingPolicy); IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_SHADER_TYPE(TUniformLightMapPolicy, FMobileDirectionalLightCSMAndLightMapPolicy); IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_SHADER_TYPE(TUniformLightMapPolicy, FMobileDirectionalLightAndSHIndirectPolicy); IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_SHADER_TYPE(TUniformLightMapPolicy, FMobileDirectionalLightCSMAndSHIndirectPolicy); IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_SHADER_TYPE(TUniformLightMapPolicy, FMobileMovableDirectionalLightWithLightmapPolicy); IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_SHADER_TYPE(TUniformLightMapPolicy, FMobileMovableDirectionalLightCSMWithLightmapPolicy); IMPLEMENT_MOBILE_SHADING_BASEPASS_LIGHTMAPPED_SHADER_TYPE(TUniformLightMapPolicy, FMobileDirectionalLightAndCSMPolicy); template bool TMobileBasePassPSPolicyParamType::ModifyCompilationEnvironmentForQualityLevel(EShaderPlatform Platform, EMaterialQualityLevel::Type QualityLevel, FShaderCompilerEnvironment& OutEnvironment) { // Get quality settings for shader platform const UShaderPlatformQualitySettings* MaterialShadingQuality = UMaterialShaderQualitySettings::Get()->GetShaderPlatformQualitySettings(Platform); const FMaterialQualityOverrides& QualityOverrides = MaterialShadingQuality->GetQualityOverrides(QualityLevel); // the point of this check is to keep the logic between enabling overrides here and in UMaterial::GetQualityLevelUsage() in sync checkf(QualityOverrides.CanOverride(Platform), TEXT("ShaderPlatform %d was not marked as being able to use quality overrides! Include it in CanOverride() and recook."), static_cast(Platform)); OutEnvironment.SetDefine(TEXT("MOBILE_QL_FORCE_FULLY_ROUGH"), QualityOverrides.bEnableOverride && QualityOverrides.bForceFullyRough != 0 ? 1u : 0u); OutEnvironment.SetDefine(TEXT("MOBILE_QL_FORCE_NONMETAL"), QualityOverrides.bEnableOverride && QualityOverrides.bForceNonMetal != 0 ? 1u : 0u); OutEnvironment.SetDefine(TEXT("QL_FORCEDISABLE_LM_DIRECTIONALITY"), QualityOverrides.bEnableOverride && QualityOverrides.bForceDisableLMDirectionality != 0 ? 1u : 0u); OutEnvironment.SetDefine(TEXT("MOBILE_QL_FORCE_DISABLE_PREINTEGRATEDGF"), QualityOverrides.bEnableOverride && QualityOverrides.bForceDisablePreintegratedGF != 0 ? 1u : 0u); OutEnvironment.SetDefine(TEXT("MOBILE_SHADOW_QUALITY"), (uint32)QualityOverrides.MobileShadowQuality); OutEnvironment.SetDefine(TEXT("MOBILE_QL_DISABLE_MATERIAL_NORMAL"), QualityOverrides.bEnableOverride && QualityOverrides.bDisableMaterialNormalCalculation); return true; } extern void SetupDummyForwardLightUniformParameters(FRDGBuilder& GraphBuilder, FForwardLightData& ForwardLightData); void SetupMobileBasePassUniformParameters( FRDGBuilder& GraphBuilder, const FViewInfo& View, EMobileBasePass BasePass, EMobileSceneTextureSetupMode SetupMode, const FMobileBasePassTextures& MobileBasePassTextures, FMobileBasePassUniformParameters& BasePassParameters) { SetupFogUniformParameters(GraphBuilder, View, BasePassParameters.Fog); if (View.ForwardLightingResources.ForwardLightData) { BasePassParameters.Forward = *View.ForwardLightingResources.ForwardLightData; } else { SetupDummyForwardLightUniformParameters(GraphBuilder, BasePassParameters.Forward); } const FScene* Scene = View.Family->Scene ? View.Family->Scene->GetRenderScene() : nullptr; const FPlanarReflectionSceneProxy* ReflectionSceneProxy = Scene ? Scene->GetForwardPassGlobalPlanarReflection() : nullptr; SetupPlanarReflectionUniformParameters(View, ReflectionSceneProxy, BasePassParameters.PlanarReflection); if (View.PrevViewInfo.MobilePixelProjectedReflection.IsValid()) { BasePassParameters.PlanarReflection.PlanarReflectionTexture = View.PrevViewInfo.MobilePixelProjectedReflection->GetRHI(); BasePassParameters.PlanarReflection.PlanarReflectionSampler = TStaticSamplerState::GetRHI(); } else if (BasePassParameters.PlanarReflection.PlanarReflectionTexture == nullptr) { BasePassParameters.PlanarReflection.PlanarReflectionTexture = GBlackTexture->TextureRHI; BasePassParameters.PlanarReflection.PlanarReflectionSampler = GBlackTexture->SamplerStateRHI; } const FRDGSystemTextures& SystemTextures = FRDGSystemTextures::Get(GraphBuilder); SetupMobileSceneTextureUniformParameters(GraphBuilder, View.GetSceneTexturesChecked(), SetupMode, BasePassParameters.SceneTextures); BasePassParameters.PreIntegratedGFTexture = GSystemTextures.PreintegratedGF->GetRHI(); BasePassParameters.PreIntegratedGFSampler = TStaticSamplerState::GetRHI(); BasePassParameters.EyeAdaptationBuffer = GraphBuilder.CreateSRV(GetEyeAdaptationBuffer(GraphBuilder, View), PF_A32B32G32R32F); FRDGTextureRef AmbientOcclusionTexture = SystemTextures.White; if (BasePass == EMobileBasePass::Opaque && MobileBasePassTextures.ScreenSpaceAO != nullptr) { AmbientOcclusionTexture = MobileBasePassTextures.ScreenSpaceAO; } BasePassParameters.AmbientOcclusionTexture = AmbientOcclusionTexture; BasePassParameters.AmbientOcclusionSampler = TStaticSamplerState::GetRHI(); BasePassParameters.AmbientOcclusionStaticFraction = FMath::Clamp(View.FinalPostProcessSettings.AmbientOcclusionStaticFraction, 0.0f, 1.0f); const bool bMobileUsesShadowMaskTexture = MobileUsesShadowMaskTexture(View.GetShaderPlatform()); if (bMobileUsesShadowMaskTexture && GScreenSpaceShadowMaskTextureMobileOutputs.ScreenSpaceShadowMaskTextureMobile.IsValid()) { FRDGTextureRef ScreenShadowMaskTexture = GraphBuilder.RegisterExternalTexture(GScreenSpaceShadowMaskTextureMobileOutputs.ScreenSpaceShadowMaskTextureMobile, TEXT("ScreenSpaceShadowMaskTextureMobile")); BasePassParameters.ScreenSpaceShadowMaskTexture = ScreenShadowMaskTexture; BasePassParameters.ScreenSpaceShadowMaskSampler = TStaticSamplerState::GetRHI(); } else { BasePassParameters.ScreenSpaceShadowMaskTexture = GSystemTextures.GetWhiteDummy(GraphBuilder); BasePassParameters.ScreenSpaceShadowMaskSampler = TStaticSamplerState::GetRHI(); } SetupReflectionUniformParameters(View, BasePassParameters.ReflectionsParameters); } TRDGUniformBufferRef CreateMobileBasePassUniformBuffer( FRDGBuilder& GraphBuilder, const FViewInfo& View, EMobileBasePass BasePass, EMobileSceneTextureSetupMode SetupMode, const FMobileBasePassTextures& MobileBasePassTextures) { FMobileBasePassUniformParameters* BasePassParameters = GraphBuilder.AllocParameters(); SetupMobileBasePassUniformParameters(GraphBuilder, View, BasePass, SetupMode, MobileBasePassTextures, *BasePassParameters); #if WITH_DEBUG_VIEW_MODES if (View.Family->UseDebugViewPS()) { SetupDebugViewModePassUniformBufferConstants(View, BasePassParameters->DebugViewMode); } #endif return GraphBuilder.CreateUniformBuffer(BasePassParameters); } void SetupMobileDirectionalLightUniformParameters( const FScene& Scene, int32 ViewIndex, const FViewInfo& SceneView, const TArray& VisibleLightInfos, int32 ChannelIdx, bool bDynamicShadows, FMobileDirectionalLightShaderParameters& Params) { ERHIFeatureLevel::Type FeatureLevel = Scene.GetFeatureLevel(); FLightSceneInfo* Light = Scene.MobileDirectionalLights[ChannelIdx]; if (Light) { Params.DirectionalLightColor = Light->Proxy->GetSunIlluminanceAccountingForSkyAtmospherePerPixelTransmittance() / PI; Params.DirectionalLightDirectionAndShadowTransition = FVector4f((FVector3f)-Light->Proxy->GetDirection(), 0.f); const FVector2D FadeParams = Light->Proxy->GetDirectionalLightDistanceFadeParameters(FeatureLevel, Light->IsPrecomputedLightingValid(), SceneView.MaxShadowCascades); Params.DirectionalLightDistanceFadeMADAndSpecularScale.X = FadeParams.Y; Params.DirectionalLightDistanceFadeMADAndSpecularScale.Y = -FadeParams.X * FadeParams.Y; Params.DirectionalLightDistanceFadeMADAndSpecularScale.Z = Light->Proxy->GetSpecularScale(); if (bDynamicShadows && VisibleLightInfos.IsValidIndex(Light->Id) && VisibleLightInfos[Light->Id].AllProjectedShadows.Num() > 0) { const TArray& DirectionalLightShadowInfos = VisibleLightInfos[Light->Id].AllProjectedShadows; static_assert(MAX_MOBILE_SHADOWCASCADES <= 4, "more than 4 cascades not supported by the shader and uniform buffer"); const int32 NumShadowsToCopy = FMath::Min(DirectionalLightShadowInfos.Num(), SceneView.MaxShadowCascades); int32_t OutShadowIndex = 0; for (int32 i = 0; i < NumShadowsToCopy; ++i) { const FProjectedShadowInfo* ShadowInfo = DirectionalLightShadowInfos[i + ViewIndex * NumShadowsToCopy]; if (ShadowInfo->ShadowDepthView && !ShadowInfo->bRayTracedDistanceField && ShadowInfo->CacheMode != SDCM_StaticPrimitivesOnly) { if (OutShadowIndex == 0) { const FIntPoint ShadowBufferResolution = ShadowInfo->GetShadowBufferResolution(); const FVector4f ShadowBufferSizeValue((float)ShadowBufferResolution.X, (float)ShadowBufferResolution.Y, 1.0f / (float)ShadowBufferResolution.X, 1.0f / (float)ShadowBufferResolution.Y); Params.DirectionalLightShadowTexture = ShadowInfo->RenderTargets.DepthTarget->GetRHI(); Params.DirectionalLightDirectionAndShadowTransition.W = 1.0f / ShadowInfo->ComputeTransitionSize(); Params.DirectionalLightShadowSize = ShadowBufferSizeValue; Params.DirectionalLightDistanceFadeMADAndSpecularScale.W = ShadowInfo->GetShaderReceiverDepthBias(); } Params.DirectionalLightScreenToShadow[OutShadowIndex] = FMatrix44f(ShadowInfo->GetScreenToShadowMatrix(SceneView)); // LWC_TODO: Precision loss? Params.DirectionalLightShadowDistances[OutShadowIndex] = ShadowInfo->CascadeSettings.SplitFar; OutShadowIndex++; } } } } } void SetupMobileSkyReflectionUniformParameters(FSkyLightSceneProxy* SkyLight, FMobileReflectionCaptureShaderParameters& Parameters) { float Brightness = 0.f; float SkyMaxMipIndex = 0.f; FTexture* CaptureTexture = GBlackTextureCube; if (SkyLight && SkyLight->ProcessedTexture) { check(SkyLight->ProcessedTexture->IsInitialized()); CaptureTexture = SkyLight->ProcessedTexture; SkyMaxMipIndex = FMath::Log2(static_cast(CaptureTexture->GetSizeX())); Brightness = SkyLight->AverageBrightness; } //To keep ImageBasedReflectionLighting coherence with PC, use AverageBrightness instead of InvAverageBrightness to calculate the IBL contribution Parameters.Params = FVector4f(Brightness, SkyMaxMipIndex, 0.f, 0.f); Parameters.Texture = CaptureTexture->TextureRHI; Parameters.TextureSampler = CaptureTexture->SamplerStateRHI; } void FMobileSceneRenderer::RenderMobileBasePass(FRHICommandListImmediate& RHICmdList, const FViewInfo& View) { CSV_SCOPED_TIMING_STAT_EXCLUSIVE(RenderBasePass); SCOPED_DRAW_EVENT(RHICmdList, MobileBasePass); SCOPE_CYCLE_COUNTER(STAT_BasePassDrawTime); SCOPED_GPU_STAT(RHICmdList, Basepass); RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1); View.ParallelMeshDrawCommandPasses[EMeshPass::BasePass].DispatchDraw(nullptr, RHICmdList, &MeshPassInstanceCullingDrawParams[EMeshPass::BasePass]); if (View.Family->EngineShowFlags.Atmosphere) { View.ParallelMeshDrawCommandPasses[EMeshPass::SkyPass].DispatchDraw(nullptr, RHICmdList, &MeshPassInstanceCullingDrawParams[EMeshPass::SkyPass]); } // editor primitives FMeshPassProcessorRenderState DrawRenderState; DrawRenderState.SetBlendState(TStaticBlendStateWriteMask::GetRHI()); DrawRenderState.SetDepthStencilAccess(Scene->DefaultBasePassDepthStencilAccess); DrawRenderState.SetDepthStencilState(TStaticDepthStencilState::GetRHI()); RenderMobileEditorPrimitives(RHICmdList, View, DrawRenderState); } void FMobileSceneRenderer::RenderMobileEditorPrimitives(FRHICommandList& RHICmdList, const FViewInfo& View, const FMeshPassProcessorRenderState& DrawRenderState) { QUICK_SCOPE_CYCLE_COUNTER(STAT_EditorDynamicPrimitiveDrawTime); SCOPED_DRAW_EVENT(RHICmdList, DynamicEd); View.SimpleElementCollector.DrawBatchedElements(RHICmdList, DrawRenderState, View, EBlendModeFilter::OpaqueAndMasked, SDPG_World); View.SimpleElementCollector.DrawBatchedElements(RHICmdList, DrawRenderState, View, EBlendModeFilter::OpaqueAndMasked, SDPG_Foreground); if (!View.Family->EngineShowFlags.CompositeEditorPrimitives) { const bool bNeedToSwitchVerticalAxis = RHINeedsToSwitchVerticalAxis(GShaderPlatformForFeatureLevel[FeatureLevel]) && !IsMobileHDR(); 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); } }); // Draw the view's batched simple elements(lines, sprites, etc). View.BatchedViewElements.Draw(RHICmdList, DrawRenderState, FeatureLevel, bNeedToSwitchVerticalAxis, View, false); 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, FeatureLevel, bNeedToSwitchVerticalAxis, View, false); } }