BlueRose
文章97
标签28
分类7
Ue4后处理逻辑简析

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与变量之后

    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();

读取参数并设置

TOverridePassSequence<EPass> 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有这么一些:

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对传入的图形进行后处理。

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