141 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			141 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								## 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<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有这么一些:
							 | 
						|||
| 
								 | 
							
								```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
							 |