## Ue4后处理逻辑简析 ### APostProcessVolume 通常我们在后处理体积,也就是APostProcessVolume设置后处理效果。它存储了struct FPostProcessSettings Settings; 加入关卡后,会存储在UWorld的PostProcessVolumes中,之后依次调用DoPostProcessVolume=》OverridePostProcessSettings,之后修改FSceneView中的FFinalPostProcessSettings FinalPostProcessSettings。(对所有属性进行插值计算) 最后就可以通过View.FinalPostProcessSettings来读取后处理参数了。 ### AddPostProcessingPasses 控制渲染的变量主要用下方式获取 - 从FViewInfo里直接获取 - 从FFinalPostProcessSettings获取(View.FinalPostProcessSettings) - 从FEngineShowFlags获取(View.Family->EngineShowFlags) - 从ConsoleVariable中获取 获取各种Buffer与变量之后 ```c# const FIntRect PrimaryViewRect = View.ViewRect; const FSceneTextureParameters SceneTextureParameters = GetSceneTextureParameters(GraphBuilder, Inputs.SceneTextures); const FScreenPassRenderTarget ViewFamilyOutput = FScreenPassRenderTarget::CreateViewFamilyOutput(Inputs.ViewFamilyTexture, View); const FScreenPassTexture SceneDepth(SceneTextureParameters.SceneDepthTexture, PrimaryViewRect); const FScreenPassTexture SeparateTranslucency(Inputs.SeparateTranslucencyTextures->GetColorForRead(GraphBuilder), PrimaryViewRect); const FScreenPassTexture CustomDepth((*Inputs.SceneTextures)->CustomDepthTexture, PrimaryViewRect); const FScreenPassTexture Velocity(SceneTextureParameters.GBufferVelocityTexture, PrimaryViewRect); const FScreenPassTexture BlackDummy(GSystemTextures.GetBlackDummy(GraphBuilder)); // Scene color is updated incrementally through the post process pipeline. FScreenPassTexture SceneColor((*Inputs.SceneTextures)->SceneColorTexture, PrimaryViewRect); // Assigned before and after the tonemapper. FScreenPassTexture SceneColorBeforeTonemap; FScreenPassTexture SceneColorAfterTonemap; // Unprocessed scene color stores the original input. const FScreenPassTexture OriginalSceneColor = SceneColor; // Default the new eye adaptation to the last one in case it's not generated this frame. const FEyeAdaptationParameters EyeAdaptationParameters = GetEyeAdaptationParameters(View, ERHIFeatureLevel::SM5); FRDGTextureRef LastEyeAdaptationTexture = GetEyeAdaptationTexture(GraphBuilder, View); FRDGTextureRef EyeAdaptationTexture = LastEyeAdaptationTexture; // Histogram defaults to black because the histogram eye adaptation pass is used for the manual metering mode. FRDGTextureRef HistogramTexture = BlackDummy.Texture; const FEngineShowFlags& EngineShowFlags = View.Family->EngineShowFlags; const bool bVisualizeHDR = EngineShowFlags.VisualizeHDR; const bool bViewFamilyOutputInHDR = GRHISupportsHDROutput && IsHDREnabled(); const bool bVisualizeGBufferOverview = IsVisualizeGBufferOverviewEnabled(View); const bool bVisualizeGBufferDumpToFile = IsVisualizeGBufferDumpToFileEnabled(View); const bool bVisualizeGBufferDumpToPIpe = IsVisualizeGBufferDumpToPipeEnabled(View); const bool bOutputInHDR = IsPostProcessingOutputInHDR(); ``` 读取参数并设置 ```c# TOverridePassSequence PassSequence(ViewFamilyOutput); PassSequence.SetNames(PassNames, UE_ARRAY_COUNT(PassNames)); PassSequence.SetEnabled(EPass::VisualizeStationaryLightOverlap, EngineShowFlags.StationaryLightOverlap); PassSequence.SetEnabled(EPass::VisualizeLightCulling, EngineShowFlags.VisualizeLightCulling); #if WITH_EDITOR PassSequence.SetEnabled(EPass::SelectionOutline, GIsEditor && EngineShowFlags.Selection && EngineShowFlags.SelectionOutline && !EngineShowFlags.Wireframe && !bVisualizeHDR && !IStereoRendering::IsStereoEyeView(View)); PassSequence.SetEnabled(EPass::EditorPrimitive, FSceneRenderer::ShouldCompositeEditorPrimitives(View)); #else PassSequence.SetEnabled(EPass::SelectionOutline, false); PassSequence.SetEnabled(EPass::EditorPrimitive, false); #endif PassSequence.SetEnabled(EPass::VisualizeShadingModels, EngineShowFlags.VisualizeShadingModels); PassSequence.SetEnabled(EPass::VisualizeGBufferHints, EngineShowFlags.GBufferHints); PassSequence.SetEnabled(EPass::VisualizeSubsurface, EngineShowFlags.VisualizeSSS); PassSequence.SetEnabled(EPass::VisualizeGBufferOverview, bVisualizeGBufferOverview || bVisualizeGBufferDumpToFile || bVisualizeGBufferDumpToPIpe); PassSequence.SetEnabled(EPass::VisualizeHDR, EngineShowFlags.VisualizeHDR); #if WITH_EDITOR PassSequence.SetEnabled(EPass::PixelInspector, View.bUsePixelInspector); #else PassSequence.SetEnabled(EPass::PixelInspector, false); #endif PassSequence.SetEnabled(EPass::HMDDistortion, EngineShowFlags.StereoRendering && EngineShowFlags.HMDDistortion); PassSequence.SetEnabled(EPass::HighResolutionScreenshotMask, IsHighResolutionScreenshotMaskEnabled(View)); PassSequence.SetEnabled(EPass::PrimaryUpscale, PaniniConfig.IsEnabled() || (View.PrimaryScreenPercentageMethod == EPrimaryScreenPercentageMethod::SpatialUpscale && PrimaryViewRect.Size() != View.GetSecondaryViewRectSize())); PassSequence.SetEnabled(EPass::SecondaryUpscale, View.RequiresSecondaryUpscale() || View.Family->GetSecondarySpatialUpscalerInterface() != nullptr); ``` 这些操作一直到`PassSequence.Finalize();`。 ### 后处理Pass处理 主要的Pass有这么一些: ```c# TEXT("MotionBlur"), TEXT("Tonemap"), TEXT("FXAA"), TEXT("PostProcessMaterial (AfterTonemapping)"), TEXT("VisualizeDepthOfField"), TEXT("VisualizeStationaryLightOverlap"), TEXT("VisualizeLightCulling"), TEXT("SelectionOutline"), TEXT("EditorPrimitive"), TEXT("VisualizeShadingModels"), TEXT("VisualizeGBufferHints"), TEXT("VisualizeSubsurface"), TEXT("VisualizeGBufferOverview"), TEXT("VisualizeHDR"), TEXT("PixelInspector"), TEXT("HMDDistortion"), TEXT("HighResolutionScreenshotMask"), TEXT("PrimaryUpscale"), TEXT("SecondaryUpscale") ``` 之前读取了参数,对这些Pass是否开启进行了设置。之后以这种格式使用Shader对传入的图形进行后处理。 ```c# if (PassSequence.IsEnabled(EPass::MotionBlur)) { FMotionBlurInputs PassInputs; PassSequence.AcceptOverrideIfLastPass(EPass::MotionBlur, PassInputs.OverrideOutput); PassInputs.SceneColor = SceneColor; PassInputs.SceneDepth = SceneDepth; PassInputs.SceneVelocity = Velocity; PassInputs.Quality = GetMotionBlurQuality(); PassInputs.Filter = GetMotionBlurFilter(); // Motion blur visualization replaces motion blur when enabled. if (bVisualizeMotionBlur) { SceneColor = AddVisualizeMotionBlurPass(GraphBuilder, View, PassInputs); } else { SceneColor = AddMotionBlurPass(GraphBuilder, View, PassInputs); } } SceneColor = AddAfterPass(EPass::MotionBlur, SceneColor); ``` 这些效果的代码都在UnrealEngine\Engine\Source\Runtime\Renderer\Private\PostProcess中。 ### 后处理材质调用 AddPostProcessMaterialChain =》 AddPostProcessMaterialPass()为实际的绘制函数。最后在AddDrawScreenPass()中进行绘制。(DrawScreenPass()=>DrawPostProcessPass=>DrawPostProcessPass()) ### 推荐参考的后处理代码 PostProcessBloomSetup.h VisualizeShadingModels.cpp