UE 透明物体绘制准备

PassProcessor注册:

  • Engine/Source/Runtime/Renderer/Private/BasePassRendering.cpp
  • 透明的5个PassProcessor都继承BassPassProcessor。
  • 透明物质绘制,也是走的basepasspixelshader。
REGISTER_MESHPASSPROCESSOR_AND_PSOCOLLECTOR(BasePass, CreateBasePassProcessor, EShadingPath::Deferred, EMeshPass::BasePass, EMeshPassFlags::CachedMeshCommands | EMeshPassFlags::MainView);
REGISTER_MESHPASSPROCESSOR_AND_PSOCOLLECTOR(TranslucencyStandardPass, CreateTranslucencyStandardPassProcessor, EShadingPath::Deferred, EMeshPass::TranslucencyStandard, EMeshPassFlags::MainView);
REGISTER_MESHPASSPROCESSOR_AND_PSOCOLLECTOR(TranslucencyAfterDOFPass, CreateTranslucencyAfterDOFProcessor, EShadingPath::Deferred, EMeshPass::TranslucencyAfterDOF, EMeshPassFlags::MainView);
REGISTER_MESHPASSPROCESSOR_AND_PSOCOLLECTOR(TranslucencyAfterDOFModulatePass, CreateTranslucencyAfterDOFModulateProcessor, EShadingPath::Deferred, EMeshPass::TranslucencyAfterDOFModulate, EMeshPassFlags::MainView);
REGISTER_MESHPASSPROCESSOR_AND_PSOCOLLECTOR(TranslucencyAfterMotionBlurPass, CreateTranslucencyAfterMotionBlurProcessor, EShadingPath::Deferred, EMeshPass::TranslucencyAfterMotionBlur, EMeshPassFlags::MainView);
REGISTER_MESHPASSPROCESSOR_AND_PSOCOLLECTOR(TranslucencyAllPass, CreateTranslucencyAllPassProcessor, EShadingPath::Deferred, EMeshPass::TranslucencyAll, EMeshPassFlags::MainView);
FMeshPassProcessor* CreateTranslucencyAfterDOFProcessor(ERHIFeatureLevel::Type FeatureLevel, 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 FBasePassMeshProcessor(EMeshPass::TranslucencyAfterDOF, Scene, FeatureLevel, InViewIfDynamicMeshCommand, PassDrawRenderState, InDrawListContext, Flags, ETranslucencyPass::TPT_TranslucencyAfterDOF);
}

绘制准备

FSceneRenderer::ComputeViewVisibility -> FSceneRenderer::SetupMeshPass
void FSceneRenderer::SetupMeshPass(FViewInfo& View, FExclusiveDepthStencil::Type BasePassDepthStencilAccess, FViewCommands& ViewCommands, FInstanceCullingManager& InstanceCullingManager)
{SCOPE_CYCLE_COUNTER(STAT_SetupMeshPass);const EShadingPath ShadingPath = Scene->GetShadingPath();for (int32 PassIndex = 0; PassIndex < EMeshPass::Num; PassIndex++){const EMeshPass::Type PassType = (EMeshPass::Type)PassIndex;if ((FPassProcessorManager::GetPassFlags(ShadingPath, PassType) & EMeshPassFlags::MainView) != EMeshPassFlags::None){// Mobile: BasePass and MobileBasePassCSM lists need to be merged and sorted after shadow pass.if (ShadingPath == EShadingPath::Mobile && (PassType == EMeshPass::BasePass || PassType == EMeshPass::MobileBasePassCSM)){continue;}if (ViewFamily.UseDebugViewPS() && ShadingPath == EShadingPath::Deferred){switch (PassType){case EMeshPass::DepthPass:case EMeshPass::CustomDepth:case EMeshPass::DebugViewMode:
#if WITH_EDITORcase EMeshPass::HitProxy:case EMeshPass::HitProxyOpaqueOnly:case EMeshPass::EditorSelection:case EMeshPass::EditorLevelInstance:
#endifbreak;default:continue;}}FMeshPassProcessor* MeshPassProcessor = FPassProcessorManager::CreateMeshPassProcessor(ShadingPath, PassType, Scene->GetFeatureLevel(), Scene, &View, nullptr);FParallelMeshDrawCommandPass& Pass = View.ParallelMeshDrawCommandPasses[PassIndex];if (ShouldDumpMeshDrawCommandInstancingStats()){Pass.SetDumpInstancingStats(GetMeshPassName(PassType));}TArray<int32, TInlineAllocator<2> > ViewIds;ViewIds.Add(View.GPUSceneViewId);// Only apply instancing for ISR to main view passesconst bool bIsMainViewPass = PassType != EMeshPass::Num && (FPassProcessorManager::GetPassFlags(Scene->GetShadingPath(), PassType) & EMeshPassFlags::MainView) != EMeshPassFlags::None;EInstanceCullingMode InstanceCullingMode = bIsMainViewPass && View.IsInstancedStereoPass() ? EInstanceCullingMode::Stereo : EInstanceCullingMode::Normal;if (InstanceCullingMode == EInstanceCullingMode::Stereo){check(View.GetInstancedView() != nullptr);ViewIds.Add(View.GetInstancedView()->GPUSceneViewId);}EInstanceCullingFlags CullingFlags = EInstanceCullingFlags::None;if (ViewFamily.EngineShowFlags.DrawOnlyVSMInvalidatingGeo != 0){EnumAddFlags(CullingFlags, EInstanceCullingFlags::DrawOnlyVSMInvalidatingGeometry);}Pass.DispatchPassSetup(Scene,View,FInstanceCullingContext(FeatureLevel, &InstanceCullingManager, ViewIds, View.PrevViewInfo.HZB, InstanceCullingMode, CullingFlags),PassType,BasePassDepthStencilAccess,MeshPassProcessor,View.DynamicMeshElements,&View.DynamicMeshElementsPassRelevance,View.NumVisibleDynamicMeshElements[PassType],ViewCommands.DynamicMeshCommandBuildRequests[PassType],ViewCommands.NumDynamicMeshCommandBuildRequestElements[PassType],ViewCommands.MeshCommands[PassIndex]);}}
}

DispatchPassSetup函数参数准备流程(View. 和 ViewCommands.)

DispatchPassSetup函数实现流程 

void FParallelMeshDrawCommandPass::DispatchPassSetup(FScene* Scene,const FViewInfo& View,FInstanceCullingContext&& InstanceCullingContext,EMeshPass::Type PassType,FExclusiveDepthStencil::Type BasePassDepthStencilAccess,FMeshPassProcessor* MeshPassProcessor,const TArray<FMeshBatchAndRelevance, SceneRenderingAllocator>& DynamicMeshElements,const TArray<FMeshPassMask, SceneRenderingAllocator>* DynamicMeshElementsPassRelevance,int32 NumDynamicMeshElements,TArray<const FStaticMeshBatch*, SceneRenderingAllocator>& InOutDynamicMeshCommandBuildRequests,int32 NumDynamicMeshCommandBuildRequestElements,FMeshCommandOneFrameArray& InOutMeshDrawCommands,FMeshPassProcessor* MobileBasePassCSMMeshPassProcessor,FMeshCommandOneFrameArray* InOutMobileBasePassCSMMeshDrawCommands
)
{TRACE_CPUPROFILER_EVENT_SCOPE(ParallelMdcDispatchPassSetup);check(!TaskEventRef.IsValid() && MeshPassProcessor != nullptr && TaskContext.PrimitiveIdBufferData == nullptr);check((PassType == EMeshPass::Num) == (DynamicMeshElementsPassRelevance == nullptr));MaxNumDraws = InOutMeshDrawCommands.Num() + NumDynamicMeshElements + NumDynamicMeshCommandBuildRequestElements;TaskContext.MeshPassProcessor = MeshPassProcessor;TaskContext.MobileBasePassCSMMeshPassProcessor = MobileBasePassCSMMeshPassProcessor;TaskContext.DynamicMeshElements = &DynamicMeshElements;TaskContext.DynamicMeshElementsPassRelevance = DynamicMeshElementsPassRelevance;TaskContext.View = &View;TaskContext.Scene = Scene;TaskContext.ShadingPath = Scene->GetShadingPath();TaskContext.ShaderPlatform = Scene->GetShaderPlatform();TaskContext.PassType = PassType;TaskContext.bUseGPUScene = UseGPUScene(GMaxRHIShaderPlatform, View.GetFeatureLevel());TaskContext.bDynamicInstancing = IsDynamicInstancingEnabled(View.GetFeatureLevel());TaskContext.bReverseCulling = View.bReverseCulling;TaskContext.bRenderSceneTwoSided = View.bRenderSceneTwoSided;TaskContext.BasePassDepthStencilAccess = BasePassDepthStencilAccess;TaskContext.DefaultBasePassDepthStencilAccess = Scene->DefaultBasePassDepthStencilAccess;TaskContext.NumDynamicMeshElements = NumDynamicMeshElements;TaskContext.NumDynamicMeshCommandBuildRequestElements = NumDynamicMeshCommandBuildRequestElements;// Only apply instancing for ISR to main view passesconst bool bIsMainViewPass = PassType != EMeshPass::Num && (FPassProcessorManager::GetPassFlags(TaskContext.ShadingPath, TaskContext.PassType) & EMeshPassFlags::MainView) != EMeshPassFlags::None;// GPUCULL_TODO: Note the InstanceFactor is ignored by the GPU-Scene supported instances, but is used for legacy primitives.TaskContext.InstanceFactor = (bIsMainViewPass && View.IsInstancedStereoPass()) ? 2 : 1;TaskContext.InstanceCullingContext = MoveTemp(InstanceCullingContext); // Setup translucency sort key update pass based on view.TaskContext.TranslucencyPass = ETranslucencyPass::TPT_MAX;TaskContext.TranslucentSortPolicy = View.TranslucentSortPolicy;TaskContext.TranslucentSortAxis = View.TranslucentSortAxis;TaskContext.ViewOrigin = View.ViewMatrices.GetViewOrigin();TaskContext.ViewMatrix = View.ViewMatrices.GetViewMatrix();TaskContext.PrimitiveBounds = &Scene->PrimitiveBounds;switch (PassType){case EMeshPass::TranslucencyStandard: TaskContext.TranslucencyPass = ETranslucencyPass::TPT_StandardTranslucency; break;case EMeshPass::TranslucencyAfterDOF: TaskContext.TranslucencyPass = ETranslucencyPass::TPT_TranslucencyAfterDOF; break;case EMeshPass::TranslucencyAfterDOFModulate: TaskContext.TranslucencyPass = ETranslucencyPass::TPT_TranslucencyAfterDOFModulate; break;case EMeshPass::TranslucencyAfterMotionBlur: TaskContext.TranslucencyPass = ETranslucencyPass::TPT_TranslucencyAfterMotionBlur; break;case EMeshPass::TranslucencyAll: TaskContext.TranslucencyPass = ETranslucencyPass::TPT_AllTranslucency; break;}FMemory::Memswap(&TaskContext.MeshDrawCommands, &InOutMeshDrawCommands, sizeof(InOutMeshDrawCommands));FMemory::Memswap(&TaskContext.DynamicMeshCommandBuildRequests, &InOutDynamicMeshCommandBuildRequests, sizeof(InOutDynamicMeshCommandBuildRequests));if (TaskContext.ShadingPath == EShadingPath::Mobile && TaskContext.PassType == EMeshPass::BasePass){FMemory::Memswap(&TaskContext.MobileBasePassCSMMeshDrawCommands, InOutMobileBasePassCSMMeshDrawCommands, sizeof(*InOutMobileBasePassCSMMeshDrawCommands));}else{check(MobileBasePassCSMMeshPassProcessor == nullptr && InOutMobileBasePassCSMMeshDrawCommands == nullptr);}if (MaxNumDraws > 0){// Preallocate resources on rendering thread based on MaxNumDraws.TaskContext.PrimitiveIdBufferDataSize = TaskContext.InstanceFactor * MaxNumDraws * sizeof(int32);TaskContext.PrimitiveIdBufferData = FMemory::Malloc(TaskContext.PrimitiveIdBufferDataSize);
#if DO_GUARD_SLOWFMemory::Memzero(TaskContext.PrimitiveIdBufferData, TaskContext.PrimitiveIdBufferDataSize);
#endif // DO_GUARD_SLOWTaskContext.MeshDrawCommands.Reserve(MaxNumDraws);TaskContext.TempVisibleMeshDrawCommands.Reserve(MaxNumDraws);const bool bExecuteInParallel = FApp::ShouldUseThreadingForPerformance()&& CVarMeshDrawCommandsParallelPassSetup.GetValueOnRenderThread() > 0&& GIsThreadedRendering; // Rendering thread is required to safely use rendering resources in parallel.if (bExecuteInParallel){if (IsOnDemandShaderCreationEnabled()){TaskEventRef = TGraphTask<FMeshDrawCommandPassSetupTask>::CreateTask(nullptr, ENamedThreads::GetRenderThread()).ConstructAndDispatchWhenReady(TaskContext);}else{FGraphEventArray DependentGraphEvents;DependentGraphEvents.Add(TGraphTask<FMeshDrawCommandPassSetupTask>::CreateTask(nullptr, ENamedThreads::GetRenderThread()).ConstructAndDispatchWhenReady(TaskContext));TaskEventRef = TGraphTask<FMeshDrawCommandInitResourcesTask>::CreateTask(&DependentGraphEvents, ENamedThreads::GetRenderThread()).ConstructAndDispatchWhenReady(TaskContext);}}else{QUICK_SCOPE_CYCLE_COUNTER(STAT_MeshPassSetupImmediate);FMeshDrawCommandPassSetupTask Task(TaskContext);Task.AnyThreadTask();if (!IsOnDemandShaderCreationEnabled()){FMeshDrawCommandInitResourcesTask DependentTask(TaskContext);DependentTask.AnyThreadTask();}}}
}
void AnyThreadTask(){FOptionalTaskTagScope Scope(ETaskTag::EParallelRenderingThread);SCOPED_NAMED_EVENT(MeshDrawCommandPassSetupTask, FColor::Magenta);// Mobile base pass is a special case, as final lists is created from two mesh passes based on CSM visibility.const bool bMobileShadingBasePass = Context.ShadingPath == EShadingPath::Mobile && Context.PassType == EMeshPass::BasePass;// On SM5 Mobile platform, still want the same sortingconst bool bMobileVulkanSM5BasePass = IsVulkanMobileSM5Platform(Context.ShaderPlatform) && Context.PassType == EMeshPass::BasePass;if (bMobileShadingBasePass){MergeMobileBasePassMeshDrawCommands(Context.View->MobileCSMVisibilityInfo,Context.PrimitiveBounds->Num(),Context.MeshDrawCommands,Context.MobileBasePassCSMMeshDrawCommands);GenerateMobileBasePassDynamicMeshDrawCommands(*Context.View,Context.ShadingPath,Context.PassType,Context.MeshPassProcessor,Context.MobileBasePassCSMMeshPassProcessor,*Context.DynamicMeshElements,Context.DynamicMeshElementsPassRelevance,Context.NumDynamicMeshElements,Context.DynamicMeshCommandBuildRequests,Context.NumDynamicMeshCommandBuildRequestElements,Context.MeshDrawCommands,Context.MeshDrawCommandStorage,Context.MinimalPipelineStatePassSet,Context.NeedsShaderInitialisation);}else{GenerateDynamicMeshDrawCommands(*Context.View,Context.ShadingPath,Context.PassType,Context.MeshPassProcessor,*Context.DynamicMeshElements,Context.DynamicMeshElementsPassRelevance,Context.NumDynamicMeshElements,Context.DynamicMeshCommandBuildRequests,Context.NumDynamicMeshCommandBuildRequestElements,Context.MeshDrawCommands,Context.MeshDrawCommandStorage,Context.MinimalPipelineStatePassSet,Context.NeedsShaderInitialisation);}if (Context.MeshDrawCommands.Num() > 0){if (Context.PassType != EMeshPass::Num){ApplyViewOverridesToMeshDrawCommands(Context.ShadingPath,Context.PassType,Context.bReverseCulling,Context.bRenderSceneTwoSided,Context.BasePassDepthStencilAccess,Context.DefaultBasePassDepthStencilAccess,Context.MeshDrawCommands,Context.MeshDrawCommandStorage,Context.MinimalPipelineStatePassSet,Context.NeedsShaderInitialisation,Context.TempVisibleMeshDrawCommands);}// Update sort keys.if (bMobileShadingBasePass || bMobileVulkanSM5BasePass){UpdateMobileBasePassMeshSortKeys(Context.ViewOrigin,*Context.PrimitiveBounds,Context.MeshDrawCommands);}else if (Context.TranslucencyPass != ETranslucencyPass::TPT_MAX){// When per-pixel OIT is enabled, sort primitive from front to back ensure avoid // constantly resorting front-to-back samples list.const bool bInverseSorting = OIT::IsEnabled(EOITSortingType::SortedPixels, Context.ShaderPlatform) && Context.View->AntiAliasingMethod != EAntiAliasingMethod::AAM_MSAA;UpdateTranslucentMeshSortKeys(Context.TranslucentSortPolicy,Context.TranslucentSortAxis,Context.ViewOrigin,Context.ViewMatrix,*Context.PrimitiveBounds,Context.TranslucencyPass,bInverseSorting,Context.MeshDrawCommands);}{QUICK_SCOPE_CYCLE_COUNTER(STAT_SortVisibleMeshDrawCommands);Context.MeshDrawCommands.Sort(FCompareFMeshDrawCommands());}if (Context.bUseGPUScene){TArrayView<const FStateBucketAuxData> StateBucketsAuxData;if (Context.PassType != EMeshPass::Num){StateBucketsAuxData = Context.Scene->CachedStateBucketsAuxData[Context.PassType];}Context.InstanceCullingContext.SetupDrawCommands(StateBucketsAuxData,Context.MeshDrawCommands, true, Context.MaxInstances, Context.VisibleMeshDrawCommandsNum, Context.NewPassVisibleMeshDrawCommandsNum);}}}
void GenerateDynamicMeshDrawCommands(const FViewInfo& View,EShadingPath ShadingPath,EMeshPass::Type PassType,FMeshPassProcessor* PassMeshProcessor,const TArray<FMeshBatchAndRelevance, SceneRenderingAllocator>& DynamicMeshElements,const TArray<FMeshPassMask, SceneRenderingAllocator>* DynamicMeshElementsPassRelevance,int32 MaxNumDynamicMeshElements,const TArray<const FStaticMeshBatch*, SceneRenderingAllocator>& DynamicMeshCommandBuildRequests,int32 MaxNumBuildRequestElements,FMeshCommandOneFrameArray& VisibleCommands,FDynamicMeshDrawCommandStorage& MeshDrawCommandStorage,FGraphicsMinimalPipelineStateSet& MinimalPipelineStatePassSet,bool& NeedsShaderInitialisation
)
{QUICK_SCOPE_CYCLE_COUNTER(STAT_GenerateDynamicMeshDrawCommands);check(PassMeshProcessor);check((PassType == EMeshPass::Num) == (DynamicMeshElementsPassRelevance == nullptr));FDynamicPassMeshDrawListContext DynamicPassMeshDrawListContext(MeshDrawCommandStorage,VisibleCommands,MinimalPipelineStatePassSet,NeedsShaderInitialisation);PassMeshProcessor->SetDrawListContext(&DynamicPassMeshDrawListContext);{const int32 NumCommandsBefore = VisibleCommands.Num();const int32 NumDynamicMeshBatches = DynamicMeshElements.Num();for (int32 MeshIndex = 0; MeshIndex < NumDynamicMeshBatches; MeshIndex++){if (!DynamicMeshElementsPassRelevance || (*DynamicMeshElementsPassRelevance)[MeshIndex].Get(PassType)){const FMeshBatchAndRelevance& MeshAndRelevance = DynamicMeshElements[MeshIndex];const uint64 BatchElementMask = ~0ull;PassMeshProcessor->AddMeshBatch(*MeshAndRelevance.Mesh, BatchElementMask, MeshAndRelevance.PrimitiveSceneProxy);}}const int32 NumCommandsGenerated = VisibleCommands.Num() - NumCommandsBefore;checkf(NumCommandsGenerated <= MaxNumDynamicMeshElements,TEXT("Generated %d mesh draw commands for DynamicMeshElements, while preallocating resources only for %d of them."), NumCommandsGenerated, MaxNumDynamicMeshElements);}{const int32 NumCommandsBefore = VisibleCommands.Num();const int32 NumStaticMeshBatches = DynamicMeshCommandBuildRequests.Num();for (int32 MeshIndex = 0; MeshIndex < NumStaticMeshBatches; MeshIndex++){const FStaticMeshBatch* StaticMeshBatch = DynamicMeshCommandBuildRequests[MeshIndex];const uint64 DefaultBatchElementMask = ~0ul;PassMeshProcessor->AddMeshBatch(*StaticMeshBatch, DefaultBatchElementMask, StaticMeshBatch->PrimitiveSceneInfo->Proxy, StaticMeshBatch->Id);}const int32 NumCommandsGenerated = VisibleCommands.Num() - NumCommandsBefore;checkf(NumCommandsGenerated <= MaxNumBuildRequestElements,TEXT("Generated %d mesh draw commands for DynamicMeshCommandBuildRequests, while preallocating resources only for %d of them."), NumCommandsGenerated, MaxNumBuildRequestElements);}
}
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(Material, OverrideSettings);const ERasterizerCullMode MeshCullMode = ComputeMeshCullMode(Material, OverrideSettings);bool bShouldDraw = ShouldDraw(Material);// 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();const bool bAllowStaticLighting = AllowStaticLighting();const FLightMapInteraction LightMapInteraction = (bAllowStaticLighting && MeshBatch.LCI && bIsLitMaterial)? MeshBatch.LCI->GetLightMapInteraction(FeatureLevel): FLightMapInteraction();const bool bAllowIndirectLightingCache = Scene && Scene->PrecomputedLightVolumes.Num() > 0;const bool bUseVolumetricLightmap = Scene && Scene->VolumetricLightmapSceneData.HasData();FMeshMaterialShaderElementData MeshMaterialShaderElementData;MeshMaterialShaderElementData.InitializeMeshMaterialData(ViewIfDynamicMeshCommand, PrimitiveSceneProxy, MeshBatch, StaticMeshId, true);// Render volumetric translucent self-shadowing only for >= SM4 and fallback to non-shadowed for lesser shader modelsif (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 neededbResult = 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{ELightMapPolicyType UniformLightMapPolicyType = GetUniformLightMapPolicyType(FeatureLevel, Scene, MeshBatch, PrimitiveSceneProxy, Material);bResult = Process< FUniformLightMapPolicy >(MeshBatch,BatchElementMask,StaticMeshId,PrimitiveSceneProxy,MaterialRenderProxy,Material,BlendMode,ShadingModels,FUniformLightMapPolicy(UniformLightMapPolicyType),MeshBatch.LCI,MeshFillMode,MeshCullMode);}}return bResult;
}
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(),GBL_Default, // Currently only Nanite uses non-default layout&BasePassShaders.VertexShader,&BasePassShaders.PixelShader)){return false;}FMeshPassProcessorRenderState DrawRenderState(PassDrawRenderState);bool bForceEnableStencilDitherState = false;if (ViewIfDynamicMeshCommand && StaticMeshId >= 0 && MeshBatch.bDitheredLODTransition){checkSlow(ViewIfDynamicMeshCommand->bIsViewInfo);const FViewInfo* ViewInfo = static_cast<const FViewInfo*>(ViewIfDynamicMeshCommand);if (ViewInfo->bAllowStencilDither){if (ViewInfo->StaticMeshFadeOutDitheredLODMap[StaticMeshId] || ViewInfo->StaticMeshFadeInDitheredLODMap[StaticMeshId]){bForceEnableStencilDitherState = true;}}}SetDepthStencilStateForBasePass(DrawRenderState,FeatureLevel,MeshBatch.bDitheredLODTransition,MaterialResource,bEnableReceiveDecalOutput,bForceEnableStencilDitherState);if (bEnableReceiveDecalOutput){// Set stencil value for this draw call// This is effectively extending the GBuffer using the stencil bitsconst 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);DrawRenderState.SetStencilRef(StencilValue);}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;
}
template<typename PassShadersType, typename ShaderElementDataType>
void FMeshPassProcessor::BuildMeshDrawCommands(const FMeshBatch& RESTRICT MeshBatch,uint64 BatchElementMask,const FPrimitiveSceneProxy* RESTRICT PrimitiveSceneProxy,const FMaterialRenderProxy& RESTRICT MaterialRenderProxy,const FMaterial& RESTRICT MaterialResource,const FMeshPassProcessorRenderState& RESTRICT DrawRenderState,PassShadersType PassShaders,ERasterizerFillMode MeshFillMode,ERasterizerCullMode MeshCullMode,FMeshDrawCommandSortKey SortKey,EMeshPassFeatures MeshPassFeatures,const ShaderElementDataType& ShaderElementData)
{const FVertexFactory* RESTRICT VertexFactory = MeshBatch.VertexFactory;const FPrimitiveSceneInfo* RESTRICT PrimitiveSceneInfo = PrimitiveSceneProxy ? PrimitiveSceneProxy->GetPrimitiveSceneInfo() : nullptr;FMeshDrawCommand SharedMeshDrawCommand;EFVisibleMeshDrawCommandFlags SharedFlags = EFVisibleMeshDrawCommandFlags::Default;if (MaterialResource.MaterialUsesWorldPositionOffset_RenderThread()){SharedFlags |= EFVisibleMeshDrawCommandFlags::MaterialUsesWorldPositionOffset;}SharedMeshDrawCommand.SetStencilRef(DrawRenderState.GetStencilRef());SharedMeshDrawCommand.PrimitiveType = (EPrimitiveType)MeshBatch.Type;FGraphicsMinimalPipelineStateInitializer PipelineState;PipelineState.PrimitiveType = (EPrimitiveType)MeshBatch.Type;PipelineState.ImmutableSamplerState = MaterialRenderProxy.ImmutableSamplerState;EVertexInputStreamType InputStreamType = EVertexInputStreamType::Default;if ((MeshPassFeatures & EMeshPassFeatures::PositionOnly) != EMeshPassFeatures::Default)				InputStreamType = EVertexInputStreamType::PositionOnly;if ((MeshPassFeatures & EMeshPassFeatures::PositionAndNormalOnly) != EMeshPassFeatures::Default)	InputStreamType = EVertexInputStreamType::PositionAndNormalOnly;check(VertexFactory && VertexFactory->IsInitialized());FRHIVertexDeclaration* VertexDeclaration = VertexFactory->GetDeclaration(InputStreamType);check(!VertexFactory->NeedsDeclaration() || VertexDeclaration);FMeshProcessorShaders MeshProcessorShaders = PassShaders.GetUntypedShaders();PipelineState.SetupBoundShaderState(VertexDeclaration, MeshProcessorShaders);SharedMeshDrawCommand.InitializeShaderBindings(MeshProcessorShaders);PipelineState.RasterizerState = GetStaticRasterizerState<true>(MeshFillMode, MeshCullMode);check(DrawRenderState.GetDepthStencilState());check(DrawRenderState.GetBlendState());PipelineState.BlendState = DrawRenderState.GetBlendState();PipelineState.DepthStencilState = DrawRenderState.GetDepthStencilState();PipelineState.DrawShadingRate = GetShadingRateFromMaterial(MaterialResource.GetShadingRate());// PSO Precache hash only needed when PSO precaching is enabledif (PipelineStateCache::IsPSOPrecachingEnabled()){PipelineState.ComputePrecachePSOHash();}check(VertexFactory && VertexFactory->IsInitialized());VertexFactory->GetStreams(FeatureLevel, InputStreamType, SharedMeshDrawCommand.VertexStreams);#if PSO_PRECACHING_VALIDATEPSOCollectorStats::CheckMinimalPipelineStateInCache(PipelineState, (uint32)MeshPassType, VertexFactory->GetType());
#endif // PSO_PRECACHING_VALIDATESharedMeshDrawCommand.PrimitiveIdStreamIndex = VertexFactory->GetPrimitiveIdStreamIndex(FeatureLevel, InputStreamType);if (SharedMeshDrawCommand.PrimitiveIdStreamIndex != INDEX_NONE){SharedFlags |= EFVisibleMeshDrawCommandFlags::HasPrimitiveIdStreamIndex;}int32 DataOffset = 0;if (PassShaders.VertexShader.IsValid()){FMeshDrawSingleShaderBindings ShaderBindings = SharedMeshDrawCommand.ShaderBindings.GetSingleShaderBindings(SF_Vertex, DataOffset);PassShaders.VertexShader->GetShaderBindings(Scene, FeatureLevel, PrimitiveSceneProxy, MaterialRenderProxy, MaterialResource, DrawRenderState, ShaderElementData, ShaderBindings);}if (PassShaders.PixelShader.IsValid()){FMeshDrawSingleShaderBindings ShaderBindings = SharedMeshDrawCommand.ShaderBindings.GetSingleShaderBindings(SF_Pixel, DataOffset);PassShaders.PixelShader->GetShaderBindings(Scene, FeatureLevel, PrimitiveSceneProxy, MaterialRenderProxy, MaterialResource, DrawRenderState, ShaderElementData, ShaderBindings);}if (PassShaders.GeometryShader.IsValid()){FMeshDrawSingleShaderBindings ShaderBindings = SharedMeshDrawCommand.ShaderBindings.GetSingleShaderBindings(SF_Geometry, DataOffset);PassShaders.GeometryShader->GetShaderBindings(Scene, FeatureLevel, PrimitiveSceneProxy, MaterialRenderProxy, MaterialResource, DrawRenderState, ShaderElementData, ShaderBindings);}SharedMeshDrawCommand.SetDebugData(PrimitiveSceneProxy, &MaterialResource, &MaterialRenderProxy, PassShaders.GetUntypedShaders(), VertexFactory, (uint32)MeshPassType);const int32 NumElements = ShouldSkipMeshDrawCommand(MeshBatch, PrimitiveSceneProxy) ? 0 : MeshBatch.Elements.Num();for (int32 BatchElementIndex = 0; BatchElementIndex < NumElements; BatchElementIndex++){if ((1ull << BatchElementIndex) & BatchElementMask){const FMeshBatchElement& BatchElement = MeshBatch.Elements[BatchElementIndex];FMeshDrawCommand& MeshDrawCommand = DrawListContext->AddCommand(SharedMeshDrawCommand, NumElements);EFVisibleMeshDrawCommandFlags Flags = SharedFlags;if (BatchElement.bForceInstanceCulling){Flags |= EFVisibleMeshDrawCommandFlags::ForceInstanceCulling;}if (BatchElement.bPreserveInstanceOrder){// TODO: add support for bPreserveInstanceOrder on mobileif (ensureMsgf(FeatureLevel > ERHIFeatureLevel::ES3_1, TEXT("FMeshBatchElement::bPreserveInstanceOrder is currently only supported on non-mobile platforms."))){					Flags |= EFVisibleMeshDrawCommandFlags::PreserveInstanceOrder;}}DataOffset = 0;if (PassShaders.VertexShader.IsValid()){FMeshDrawSingleShaderBindings VertexShaderBindings = MeshDrawCommand.ShaderBindings.GetSingleShaderBindings(SF_Vertex, DataOffset);FMeshMaterialShader::GetElementShaderBindings(PassShaders.VertexShader, Scene, ViewIfDynamicMeshCommand, VertexFactory, InputStreamType, FeatureLevel, PrimitiveSceneProxy, MeshBatch, BatchElement, ShaderElementData, VertexShaderBindings, MeshDrawCommand.VertexStreams);}if (PassShaders.PixelShader.IsValid()){FMeshDrawSingleShaderBindings PixelShaderBindings = MeshDrawCommand.ShaderBindings.GetSingleShaderBindings(SF_Pixel, DataOffset);FMeshMaterialShader::GetElementShaderBindings(PassShaders.PixelShader, Scene, ViewIfDynamicMeshCommand, VertexFactory, EVertexInputStreamType::Default, FeatureLevel, PrimitiveSceneProxy, MeshBatch, BatchElement, ShaderElementData, PixelShaderBindings, MeshDrawCommand.VertexStreams);}if (PassShaders.GeometryShader.IsValid()){FMeshDrawSingleShaderBindings GeometryShaderBindings = MeshDrawCommand.ShaderBindings.GetSingleShaderBindings(SF_Geometry, DataOffset);FMeshMaterialShader::GetElementShaderBindings(PassShaders.GeometryShader, Scene, ViewIfDynamicMeshCommand, VertexFactory, EVertexInputStreamType::Default, FeatureLevel, PrimitiveSceneProxy, MeshBatch, BatchElement, ShaderElementData, GeometryShaderBindings, MeshDrawCommand.VertexStreams);}FMeshDrawCommandPrimitiveIdInfo IdInfo = GetDrawCommandPrimitiveId(PrimitiveSceneInfo, BatchElement);FMeshProcessorShaders ShadersForDebugging = PassShaders.GetUntypedShaders();DrawListContext->FinalizeCommand(MeshBatch, BatchElementIndex, IdInfo, MeshFillMode, MeshCullMode, SortKey, Flags, PipelineState, &ShadersForDebugging, MeshDrawCommand);}}
}
void FCachedPassMeshDrawListContextImmediate::FinalizeCommand(const FMeshBatch& MeshBatch, int32 BatchElementIndex,const FMeshDrawCommandPrimitiveIdInfo& IdInfo,ERasterizerFillMode MeshFillMode,ERasterizerCullMode MeshCullMode,FMeshDrawCommandSortKey SortKey,EFVisibleMeshDrawCommandFlags Flags,const FGraphicsMinimalPipelineStateInitializer& PipelineState,const FMeshProcessorShaders* ShadersForDebugging,FMeshDrawCommand& MeshDrawCommand)
{// disabling this by default as it incurs a high cost in perf captures due to sheer volume.  Recommendation is to re-enable locally if you need to profile this particular code.// QUICK_SCOPE_CYCLE_COUNTER(STAT_FinalizeCachedMeshDrawCommand);FinalizeCommandCommon(MeshBatch, BatchElementIndex,MeshFillMode,MeshCullMode,SortKey,Flags,PipelineState,ShadersForDebugging,MeshDrawCommand);if (bUseGPUScene){Experimental::FHashElementId SetId;FStateBucketMap& BucketMap = Scene.CachedMeshDrawCommandStateBuckets[CurrMeshPass];auto hash = BucketMap.ComputeHash(MeshDrawCommand);{SetId = BucketMap.FindOrAddIdByHash(hash, MeshDrawCommand, FMeshDrawCommandCount());FMeshDrawCommandCount& DrawCount = BucketMap.GetByElementId(SetId).Value;DrawCount.Num++;}CommandInfo.StateBucketId = SetId.GetIndex();if (bUseStateBucketsAuxData){// grow MDC AuxData array in sync with MDC StateBucketsScene.CachedStateBucketsAuxData[CurrMeshPass].SetNum(BucketMap.GetMaxIndex() + 1, false);Scene.CachedStateBucketsAuxData[CurrMeshPass][CommandInfo.StateBucketId] = FStateBucketAuxData(MeshBatch);}}else{// Only one FMeshDrawCommand supported per FStaticMesh in a pass// Allocate at lowest free index so that 'r.DoLazyStaticMeshUpdate' can shrink the TSparseArray more effectivelyFCachedPassMeshDrawList& CachedDrawLists = Scene.CachedDrawLists[CurrMeshPass];CommandInfo.CommandIndex = CachedDrawLists.MeshDrawCommands.EmplaceAtLowestFreeIndex(CachedDrawLists.LowestFreeIndexSearchStart, MeshDrawCommand);}	
}
void FCachedPassMeshDrawListContext::FinalizeCommandCommon(const FMeshBatch& MeshBatch, int32 BatchElementIndex,ERasterizerFillMode MeshFillMode,ERasterizerCullMode MeshCullMode,FMeshDrawCommandSortKey SortKey,EFVisibleMeshDrawCommandFlags Flags,const FGraphicsMinimalPipelineStateInitializer& PipelineState,const FMeshProcessorShaders* ShadersForDebugging,FMeshDrawCommand& MeshDrawCommand)
{FGraphicsMinimalPipelineStateId PipelineId = FGraphicsMinimalPipelineStateId::GetPersistentId(PipelineState);MeshDrawCommand.SetDrawParametersAndFinalize(MeshBatch, BatchElementIndex, PipelineId, ShadersForDebugging);CommandInfo = FCachedMeshDrawCommandInfo(CurrMeshPass);CommandInfo.SortKey = SortKey;CommandInfo.MeshFillMode = MeshFillMode;CommandInfo.MeshCullMode = MeshCullMode;CommandInfo.Flags = Flags;#if MESH_DRAW_COMMAND_DEBUG_DATAif (bUseGPUScene){MeshDrawCommand.ClearDebugPrimitiveSceneProxy(); //When using State Buckets multiple PrimitiveSceneProxies use the same MeshDrawCommand, so The PrimitiveSceneProxy pointer can't be stored.}
#endif
#if DO_GUARD_SLOWif (bUseGPUScene){FMeshDrawCommand MeshDrawCommandDebug = FMeshDrawCommand(MeshDrawCommand);check(MeshDrawCommandDebug.ShaderBindings.GetDynamicInstancingHash() == MeshDrawCommand.ShaderBindings.GetDynamicInstancingHash());check(MeshDrawCommandDebug.GetDynamicInstancingHash() == MeshDrawCommand.GetDynamicInstancingHash());}if (Scene.GetShadingPath() == EShadingPath::Deferred){ensureMsgf(MeshDrawCommand.VertexStreams.GetAllocatedSize() == 0, TEXT("Cached Mesh Draw command overflows VertexStreams. VertexStream inline size should be tweaked."));if (CurrMeshPass == EMeshPass::BasePass || CurrMeshPass == EMeshPass::DepthPass || CurrMeshPass == EMeshPass::CSMShadowDepth || CurrMeshPass == EMeshPass::VSMShadowDepth){TArray<EShaderFrequency, TInlineAllocator<SF_NumFrequencies>> ShaderFrequencies;MeshDrawCommand.ShaderBindings.GetShaderFrequencies(ShaderFrequencies);int32 DataOffset = 0;for (int32 i = 0; i < ShaderFrequencies.Num(); i++){FMeshDrawSingleShaderBindings SingleShaderBindings = MeshDrawCommand.ShaderBindings.GetSingleShaderBindings(ShaderFrequencies[i], DataOffset);if (SingleShaderBindings.GetParameterMapInfo().LooseParameterBuffers.Num() != 0){bAnyLooseParameterBuffers = true;}ensureMsgf(SingleShaderBindings.GetParameterMapInfo().SRVs.Num() == 0, TEXT("Cached Mesh Draw command uses individual SRVs.  This will break dynamic instancing in performance critical pass.  Use Uniform Buffers instead."));ensureMsgf(SingleShaderBindings.GetParameterMapInfo().TextureSamplers.Num() == 0, TEXT("Cached Mesh Draw command uses individual Texture Samplers.  This will break dynamic instancing in performance critical pass.  Use Uniform Buffers instead."));}}}
#endif
}

CPP与usf

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,GBufferLayout,LayoutName) \typedef TBasePassPS<LightMapPolicyType, bEnableSkyLight, GBufferLayout> TBasePassPS##LightMapPolicyName##SkyLightName##LayoutName; \IMPLEMENT_MATERIAL_SHADER_TYPE(template<>,TBasePassPS##LightMapPolicyName##SkyLightName##LayoutName,TEXT("/Engine/Private/BasePassPixelShader.usf"),TEXT("MainPS"),SF_Pixel);#define IMPLEMENT_BASEPASS_COMPUTESHADER_TYPE(LightMapPolicyType,LightMapPolicyName,bEnableSkyLight,SkyLightName,GBufferLayout,LayoutName) \typedef TBasePassCS<LightMapPolicyType, bEnableSkyLight, GBufferLayout> TBasePassCS##LightMapPolicyName##SkyLightName##LayoutName; \IMPLEMENT_MATERIAL_SHADER_TYPE(template<>,TBasePassCS##LightMapPolicyName##SkyLightName##LayoutName,TEXT("/Engine/Private/BasePassPixelShader.usf"),TEXT("MainCS"),SF_Compute);// Implement a pixel and compute 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,GBL_Default,) \IMPLEMENT_BASEPASS_PIXELSHADER_TYPE(LightMapPolicyType,LightMapPolicyName,false,,GBL_Default,) \IMPLEMENT_BASEPASS_PIXELSHADER_TYPE(LightMapPolicyType,LightMapPolicyName,true,Skylight,GBL_ForceVelocity,ForceVelocity) \IMPLEMENT_BASEPASS_PIXELSHADER_TYPE(LightMapPolicyType,LightMapPolicyName,false,,GBL_ForceVelocity,ForceVelocity) \IMPLEMENT_BASEPASS_COMPUTESHADER_TYPE(LightMapPolicyType,LightMapPolicyName,true,Skylight,GBL_Default,) \IMPLEMENT_BASEPASS_COMPUTESHADER_TYPE(LightMapPolicyType,LightMapPolicyName,false,,GBL_Default,) \IMPLEMENT_BASEPASS_COMPUTESHADER_TYPE(LightMapPolicyType,LightMapPolicyName,true,Skylight,GBL_ForceVelocity,ForceVelocity) \IMPLEMENT_BASEPASS_COMPUTESHADER_TYPE(LightMapPolicyType,LightMapPolicyName,false,,GBL_ForceVelocity,ForceVelocity)// 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_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);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/57647.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为OD机试 - MELON的难题 - 动态规划(Java 2023 B卷 100分)

目录 一、题目描述二、输入描述三、输出描述四、动态规划五、解题思路六、Java算法源码七、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 一、题目描述 MELON有一堆精美的雨花石(数量为n&#xff0c;重量各异)&#xff0c;准备送给…

类和对象(上)

&#x1f493;博主个人主页:不是笨小孩&#x1f440; ⏩专栏分类:数据结构与算法&#x1f440; C&#x1f440; 刷题专栏&#x1f440; C语言&#x1f440; &#x1f69a;代码仓库:笨小孩的代码库&#x1f440; ⏩社区&#xff1a;不是笨小孩&#x1f440; &#x1f339;欢迎大…

socket

Socket是一种用于网络通信的编程接口&#xff0c;它提供了在计算机网络中进行数据传输的方法。通过Socket&#xff0c;可以在不同主机之间建立网络连接&#xff0c;并通过发送和接收数据来进行通信。在C语言中&#xff0c;可以使用Socket函数库&#xff08;如BSD Socket或Winso…

深入探讨Eureka的三级缓存架构与缓存运行原理

推荐阅读 AI文本 OCR识别最佳实践 AI Gamma一键生成PPT工具直达链接 玩转cloud Studio 在线编码神器 玩转 GPU AI绘画、AI讲话、翻译,GPU点亮AI想象空间 史上最全文档AI绘画stablediffusion资料分享 AI绘画关于SD,GPT,SDXL等个人总结文档 资源分享 「java、python面试题…

Zblog博客网站搭建与上线发布:在Windows环境下利用cpolar内网穿透实现公网访问的指引

文章目录 1. 前言2. Z-blog网站搭建2.1 XAMPP环境设置2.2 Z-blog安装2.3 Z-blog网页测试2.4 Cpolar安装和注册 3. 本地网页发布3.1. Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 想要成为一个合格的技术宅或程序员&#xff0c;自己搭建网站制作网页是绕…

RHCE——十一、NFS服务器

NFS服务器 一、简介1、NFS背景介绍2、生产应用场景 二、NFS工作原理1、示例图2、流程 三、NFS的使用1、安装2、配置文件3、主配置文件分析3.1 实验1 4、NFS账户映射4.1 实验24.2 实验3 四、autofs自动挂载服务1、产生原因2、安装3、配置文件分析4、实验45、实验5 一、简介 1、…

算法通关村十三关 | 进制转换问题处理模板

1. 七进制数 题目&#xff1a;LeetCode504&#xff1a;504. 七进制数 - 力扣&#xff08;LeetCode&#xff09; 思路 进制转换&#xff0c;对几转换就是对几求余&#xff0c;最后将所有的余数反过来即可、如果num< 0&#xff0c;先取绝对值&#xff0c;再进行操作。 100转7…

【笔记】泛型以及如何绕过泛型定义

泛型定义以及其带来的好处 泛型使类型&#xff08;类和接口&#xff09;能够在定义类、接口和方法时成为参数。与方法声明中使用的更熟悉的形式参数非常相似&#xff0c;类型参数为您提供了一种通过不同输入重复使用相同代码的方法。区别在于形式参数的输入是值&#xff0c;而…

leetcode分类刷题:链表(一、创建虚拟头节点)

1、现在再看链表问题&#xff0c;发现之前对傻傻分不清的cur.next有了更清晰的理解了&#xff1a;以cur变量表示当前节点&#xff0c;cur.next为当前节点的指针或下个节点&#xff0c;以上两个含义是一个意思&#xff0c;但在实际代码里选择其中一个进行理解会在逻辑上更清晰 2…

【WINAPI】文件读写操作问题

问题描述 在利用WINAPI中的WriteFile和ReadFile函数进行文件读写操作时&#xff0c;出现无法正常读写文件报错。 分析问题 查阅WINAPI源码&#xff0c;查看参数列表各个参数的数据类型。 发现其中第二个参数&#xff0c;也就是需要写进文件的真实数据&#xff0c;其数据类型…

go http-proxy

我们这里主要讲使用HTTP&#xff0f;1.1协议中的CONNECT方法建立起来的隧道连接&#xff0c;实现的HTTP Proxy。这种代理的好处就是不用知道客户端请求的数据&#xff0c;只需要原封不动的转发就可以了&#xff0c;对于处理HTTPS的请求就非常方便了&#xff0c;不用解析他的内容…

【linux命令讲解大全】021.强大的压缩包查看工具:bzless和less的使用详解

文章目录 bzless补充说明语法参数 less补充说明语法选项参数实例 从零学 python bzless 增强.bz2压缩包查看器 补充说明 bzless命令是一个增强的.bz2压缩包查看器&#xff0c;功能比bzmore命令更加强大。 语法 bzless [文件]参数 文件&#xff1a;指定要分屏显示的.bz2压…

Bresenham 贝汉明算法

理解&#xff1a;给定两个点&#xff0c;画出两个点的连线经过的栅格。 求解思路&#xff1a; 1. bresenham贝汉明算法_Bimme军的博客-CSDN博客 2. 若干计算机图形学算法实现_JulyThirteenth的博客-CSDN博客 // grid traversal void gridTraversal(const dPoint &star…

Visual Studio软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 Visual Studio是微软公司开发的一款集成开发环境&#xff08;IDE&#xff09;&#xff0c;广泛应用于Windows平台上的应用程序和Web应用程序的开发。以下是Visual Studio软件的主要特点和功能&#xff1a; 集成开发环境&#x…

文件夹无法删除?简单3招,轻松解决问题!

“我电脑里有一个文件夹占用了很大的内存&#xff0c;我想将它删除来释放一些内存&#xff0c;但是根本没法删除&#xff0c;为什么会这样呢&#xff1f;文件夹无法删除应该怎么办呢&#xff1f;” 在日常电脑使用中&#xff0c;有时候会遇到文件夹无法删除的情况&#xff0c;这…

IDEA如何打jar包

IntelliJ IDEA如何打jar包 1、无maven打jar包 1、编写好Java项目后&#xff0c;点击File --> Project Structure&#xff0c;然后按照以下图示步骤进行打包操作 若项目还存在一些额外的文件&#xff0c;可通过以下方式&#xff0c;将文件添加到jar包中。 //如果我们将项目…

如何在VR头显端实现低延迟的RTSP或RTMP播放

技术背景 VR&#xff08;虚拟现实技术&#xff09;给我们带来身临其境的视觉体验&#xff0c;广泛的应用于城市规划、教育培训、工业仿真、房地产、水利电力、室内设计、文旅、军事等众多领域&#xff0c;常用的行业比如&#xff1a; 教育行业&#xff1a;VR头显可以用于教育…

淘宝API技术解析,实现按图搜索淘宝商品

淘宝提供了开放平台接口&#xff08;API&#xff09;来实现按图搜索淘宝商品的功能。您可以通过以下步骤来实现&#xff1a; 1. 获取开放平台的访问权限&#xff1a;首先&#xff0c;您需要在淘宝开放平台创建一个应用&#xff0c;获取访问淘宝API的权限。具体的申请步骤和要求…

java中stream流中findFirst和findAny的区别?

在Java中&#xff0c;findFirst()和findAny()是Stream流的两个方法&#xff0c;用于获取流中的元素。它们的区别如下&#xff1a; findFirst(): findFirst()方法返回流中的第一个元素&#xff08;根据流的顺序&#xff09;。它在并行流操作中的行为更可预测&#xff0c;通常会返…

前端开发之Element Plus的分页组件el-pagination显示英文转变为中文

前言 在使用element的时候分页提示语句是中文的到了element-plus中式英文的&#xff0c;本文讲解的就是怎样将英文转变为中文 效果图 解决方案 如果你的element-plus版本为2.2.29以下的 import { createApp } from vue import App from ./App.vue import ElementPlus from …