331 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			331 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								---
							 | 
						|||
| 
								 | 
							
								title: UE5RayTracing渲染管线笔记——(1)
							 | 
						|||
| 
								 | 
							
								date: 2022-08-09 13:55:15
							 | 
						|||
| 
								 | 
							
								tags: RayTracing
							 | 
						|||
| 
								 | 
							
								rating: ⭐️⭐️ 
							 | 
						|||
| 
								 | 
							
								---
							 | 
						|||
| 
								 | 
							
								## 任务
							 | 
						|||
| 
								 | 
							
								- [ ] 查看这个如何针对各个View构建场景
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 渲染事件
							 | 
						|||
| 
								 | 
							
								RayTracingScene位于LumenSceneUpdate之后。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 收集场景信息
							 | 
						|||
| 
								 | 
							
								### 场景信息
							 | 
						|||
| 
								 | 
							
								在FScene中定了这2个变量来存储RayTracing专用的场景信息:
							 | 
						|||
| 
								 | 
							
								```c#
							 | 
						|||
| 
								 | 
							
								FRayTracingScene RayTracingScene;
							 | 
						|||
| 
								 | 
							
								TArray<FLightSceneInfo*, TInlineAllocator<4>> RayTracedLights;
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								FRayTracingScene还存储着FRayTracingGeometryInstance数组、TArray<const FRayTracingGeometry*> GeometriesToBuild、RayTracingSceneBuffer、RayTracingSceneSRV。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### 收集过程
							 | 
						|||
| 
								 | 
							
								主要的逻辑位于GatherRayTracingWorldInstancesForView()中,通过RayTracingCollector来收集场景中的图元。在FSceneRenderer定义了MeshCollector与RayTracingCollector,其中MeshCollector的GatherDynamicMeshElements()在计算可见性阶段被调用()。
							 | 
						|||
| 
								 | 
							
								```c#
							 | 
						|||
| 
								 | 
							
								// Gather mesh instances, shaders, resources, parameters, etc. and build ray tracing acceleration structure
							 | 
						|||
| 
								 | 
							
								FRayTracingScene& RayTracingScene = Scene->RayTracingScene;
							 | 
						|||
| 
								 | 
							
								RayTracingScene.Reset(); // Resets the internal arrays, but does not release any resources.
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								const int32 ReferenceViewIndex = 0;
							 | 
						|||
| 
								 | 
							
								FViewInfo& ReferenceView = Views[ReferenceViewIndex];
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								// Prepare the scene for rendering this frame.
							 | 
						|||
| 
								 | 
							
								GatherRayTracingWorldInstancesForView(GraphBuilder, ReferenceView, RayTracingScene);
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								- GatherRayTracingWorldInstancesForView()
							 | 
						|||
| 
								 | 
							
								  - FGPUScenePrimitiveCollector DummyDynamicPrimitiveCollector;
							 | 
						|||
| 
								 | 
							
								  - 给RayTracingCollector的内部变量赋值:RayTracingCollector.AddViewMeshArrays(&View,&View.RayTracedDynamicMeshElements,&View.SimpleElementCollector,&DummyDynamicPrimitiveCollector,ViewFamily.GetFeatureLevel(),&DynamicIndexBufferForInitViews,&DynamicVertexBufferForInitViews,&DynamicReadBufferForInitViews);
							 | 
						|||
| 
								 | 
							
								  - 创建Mesh资源收集器:`View.RayTracingMeshResourceCollector = MakeUnique<FRayTracingMeshResourceCollector>(...);`
							 | 
						|||
| 
								 | 
							
								  - 初始化Rtx裁剪变量:View.RayTracingCullingParameters.Init(View);
							 | 
						|||
| 
								 | 
							
								  - 创建FRayTracingMaterialGatheringContext MaterialGatheringContext{Scene,&View,ViewFamily,GraphBuilder,*View.RayTracingMeshResourceCollector};
							 | 
						|||
| 
								 | 
							
								  - 声明FRelevantPrimitive结构体,实现InstancingKey()用于返回图元类型掩码。并定义FRelevantPrimitive数组,长度为场景图元总数。
							 | 
						|||
| 
								 | 
							
								  - 遍历所有图元,
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### 加速结构构建
							 | 
						|||
| 
								 | 
							
								>RayTracingGem中有提到了加速结构的Rebuild与Refit概念。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								该步骤会在BasePass()之前调用。DispatchRayTracingWorldUpdates()的注释说:
							 | 
						|||
| 
								 | 
							
								>异步构建可能会与BasePass重合。 Async AS builds can potentially overlap with BasePass
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								GeometriesToBuild在GatherRayTracingWorldInstancesForView()被填充,之后在DispatchRayTracingWorldUpdates()中通过**GRayTracingGeometryManager.ForceBuildIfPending(GraphBuilder.RHICmdList, RayTracingScene.GeometriesToBuild);**更新。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								- FRayTracingGeometryManager GRayTracingGeometryManager:全局的场景管理类。
							 | 
						|||
| 
								 | 
							
								  - ForceBuildIfPending():添加需要强制构建的多边形。
							 | 
						|||
| 
								 | 
							
								  - ProcessBuildRequests():在排序请求后,调用**InCmdList.BuildAccelerationStructures(BuildParams);**构建加速结构。Render() 2634 =>DispatchRayTracingWorldUpdates()=>ProcessBuildRequests()=>InCmdList.BuildAccelerationStructures(BuildParams);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								加速结构存在一个UAV上,以FRayTracingGeometryBuildParams为单位。里面存储了`FRayTracingGeometryRHIRef Geometry、BuildMode、以及TArrayView<const FRayTracingGeometrySegment> Segments;`
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### FRayTracingScene
							 | 
						|||
| 
								 | 
							
								使用这个类来管理Rtx场景。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## RayTracingCommon.h
							 | 
						|||
| 
								 | 
							
								UE使用宏来简化RayTracingShader的编写。 比如RayTracingShader入口函数:
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								#ifndef RAY_TRACING_ENTRY_RAYGEN
							 | 
						|||
| 
								 | 
							
								#define RAY_TRACING_ENTRY_RAYGEN(name)\
							 | 
						|||
| 
								 | 
							
								[shader("raygeneration")] void name()
							 | 
						|||
| 
								 | 
							
								#endif // RAY_TRACING_ENTRY_RAYGEN
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#ifndef RAY_TRACING_ENTRY_INTERSECTION
							 | 
						|||
| 
								 | 
							
								#define RAY_TRACING_ENTRY_INTERSECTION(name)\
							 | 
						|||
| 
								 | 
							
								[shader("intersection")] void name()
							 | 
						|||
| 
								 | 
							
								#endif //RAY_TRACING_ENTRY_INTERSECTION
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#ifndef RAY_TRACING_ENTRY_CLOSEST_HIT
							 | 
						|||
| 
								 | 
							
								#define RAY_TRACING_ENTRY_CLOSEST_HIT(name, payload_type, payload_name, attributes_type, attributes_name)\
							 | 
						|||
| 
								 | 
							
								[shader("closesthit")] void name(inout payload_type payload_name, in attributes_type attributes_name)
							 | 
						|||
| 
								 | 
							
								#endif //RAY_TRACING_ENTRY_CLOSEST_HIT
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#ifndef RAY_TRACING_ENTRY_ANY_HIT
							 | 
						|||
| 
								 | 
							
								#define RAY_TRACING_ENTRY_ANY_HIT(name, payload_type, payload_name, attributes_type, attributes_name)\
							 | 
						|||
| 
								 | 
							
								[shader("anyhit")] void name(inout payload_type payload_name, in attributes_type attributes_name)
							 | 
						|||
| 
								 | 
							
								#endif // RAY_TRACING_ENTRY_ANY_HIT
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#ifndef RAY_TRACING_ENTRY_MISS
							 | 
						|||
| 
								 | 
							
								#define RAY_TRACING_ENTRY_MISS(name, payload_type, payload_name)\
							 | 
						|||
| 
								 | 
							
								[shader("miss")] void name(inout payload_type payload_name)
							 | 
						|||
| 
								 | 
							
								#endif //RAY_TRACING_ENTRY_MISS
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								所以Name需要与**IMPLEMENT_GLOBAL_SHADER**中定义的Shader入口函数名相同。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								RayTracing函数:
							 | 
						|||
| 
								 | 
							
								- FMinimalPayload Payload=TraceVisibilityRay()
							 | 
						|||
| 
								 | 
							
								- FMaterialClosestHitPayload Payload = TraceMaterialRay()
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								以及其他工具函数:
							 | 
						|||
| 
								 | 
							
								- DispatchRaysIndex()
							 | 
						|||
| 
								 | 
							
								- GetPixelCoord()
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## RenderRayTracingReflections
							 | 
						|||
| 
								 | 
							
								- SortedDeferred
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								FRayTracingDeferredReflectionsRGS
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## RenderDiffuseIndirectAndAmbientOcclusion
							 | 
						|||
| 
								 | 
							
								RenderRayTracingAmbientOcclusion()
							 | 
						|||
| 
								 | 
							
								- 遍历每个View
							 | 
						|||
| 
								 | 
							
								  - 计算使用对应方式计算GI。将结果传递给FDiffuseIndirectInputs对象。
							 | 
						|||
| 
								 | 
							
								  - 通过AmbientOcclusionRGS()RayTracing降噪得到AmbientOcclusionMask并传递给FDiffuseIndirectInputs.AmbientOcclusionMask。
							 | 
						|||
| 
								 | 
							
								  - 如果有头发会多渲染头发的AO。
							 | 
						|||
| 
								 | 
							
								  - 调用FDiffuseIndirectCompositePS将之前的渲染结果与GI、AO效果合成在一起。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								FDiffuseIndirectCompositePS()
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								###  AmbientOcclusionRGS
							 | 
						|||
| 
								 | 
							
								RayTracingAmbientOcclusionRGS.usf
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								- 计算UV、当前像素的FGBufferData以及WorldPosition与CameraDirection
							 | 
						|||
| 
								 | 
							
								- 对于非SHADINGMODELID_TWOSIDED_FOLIAGE并且开启CONFIG_SHOOT_WITH_GEOMETRIC_NORMAL,则重新计算法线:
							 | 
						|||
| 
								 | 
							
								  - 通过HalfFOV * WorldDepth * ViewInvSize.z,计算像素半径
							 | 
						|||
| 
								 | 
							
								  - 计算通过DDX与DDY计算几何法线。
							 | 
						|||
| 
								 | 
							
								  - 计算3个球形高斯分布(没看懂)。
							 | 
						|||
| 
								 | 
							
								  - 初始化RayTracing相关变量开始RayTracing。如果不开启追踪,将**Visibility = 1.0;RayCount = SamplesPerPixel;SamplesPerPixelLocal = 0.0;**
							 | 
						|||
| 
								 | 
							
								    - 使用RandomSequence生成随机样本。之后调用GenerateCosineNormalRay(),生成Ray。
							 | 
						|||
| 
								 | 
							
								      1. 调用RandomSequence_GenerateSample2D()取得2维随机样本。默认使用Sobol低差异序列,其他还有Halton与Hash随机(https://github.com/skeeto/hash-prospector)
							 | 
						|||
| 
								 | 
							
								      2. 进行余弦-半球采样并转换局部坐标为世界空间。
							 | 
						|||
| 
								 | 
							
								      3. 完成Ray的初始化。
							 | 
						|||
| 
								 | 
							
									- 调用ApplyCameraRelativeDepthBias(),对Ray的起点进行摄像机->像素坐标方向的偏移一个ε,以解决浮点数不精确的问题。
							 | 
						|||
| 
								 | 
							
									- 计算光线采样权重, **max(dot(WorldNormal, Ray.Direction), 0.05) / max(RayPDF, 0.05);**
							 | 
						|||
| 
								 | 
							
									- 调用TraceVisibilityRay()进行RayTracing。
							 | 
						|||
| 
								 | 
							
									- 累加采样结果。Tracing范围内没有遮挡物Visibility就是1,否则就是1-IntensityLocal。该值为后处理空间里设定的AO亮度值RayTracingAOIntensity。如果Ray Hit还会设置新的ClosestRayHitDistance值。
							 | 
						|||
| 
								 | 
							
									- 输出结果。 OcclusionMask=ShadingDotGeometric * (Visibility / RayCount);HitDistance=ClosestRayHitDistance;(这两个UAV都是屏幕空间降噪器的贴图变量,Shader处理完之后会进行降噪处理)
							 | 
						|||
| 
								 | 
							
								- 否则直接使用世界法线,ShadingDotGeometric=1.0
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## RenderRayTracingSkyLight
							 | 
						|||
| 
								 | 
							
								- 初始化FPathTracingSkylight SkylightParameters与FSkyLightData SkyLightData,如果天光功能未开启则返回黑色OutSkyLightTexture与OutHitDistanceTexture。
							 | 
						|||
| 
								 | 
							
								- 使用CVarRayTracingSkyLightScreenPercentage计算ResolutionFraction。
							 | 
						|||
| 
								 | 
							
								- 创建RDG Texture资源RayTracingSkylight与RayTracingSkyLightHitDistance。
							 | 
						|||
| 
								 | 
							
								- 调用GenerateSkyLightVisibilityRays()生成Ray样本集(256*256),格式为`RWStructuredBuffer<SkyLightVisibilityRays>`,`SkyLightVisibilityRays为方向与PDF值,float4 DirectionAndPdf;`。
							 | 
						|||
| 
								 | 
							
								  - FGenerateSkyLightVisibilityRaysCS的流程
							 | 
						|||
| 
								 | 
							
								    1. 计算坐标UAV坐标与SkyLightSamplingStrategyPdf(会使用SkylightPdf)。
							 | 
						|||
| 
								 | 
							
								       - 大概率是在PrepareSkyTexture()中进行了资源绑定SkylightParameters->SkylightPdf = GraphBuilder.RegisterExternalTexture(Scene->PathTracingSkylightPdf, TEXT("PathTracer.SkylightPdf")); 
							 | 
						|||
| 
								 | 
							
								    2. 计算每个像素数据。
							 | 
						|||
| 
								 | 
							
								      1. 生成随机序列,使用Hilbert curve算法: https://github.com/hcs0/Hackers-Delight/blob/master/hilbert/hil_s_from_xy.c.txt
							 | 
						|||
| 
								 | 
							
								      2. 使用Sobol算子采样来得到样本。
							 | 
						|||
| 
								 | 
							
								      3. 使用样本来计算天光采样结果,这一步会根据上下半球进行区分。
							 | 
						|||
| 
								 | 
							
								         - ```FSkyLightSample {float3 Direction;float3 Radiance;float Pdf;};```
							 | 
						|||
| 
								 | 
							
								      4. 计算最终的半球混合PDF:float MisWeightOverPdf = 1.0 / lerp(UniformPdf, SkyLightPdf, SkyLightSamplingStrategyPdf);
							 | 
						|||
| 
								 | 
							
								      5. 计算Ray的Index,并将结果写入。
							 | 
						|||
| 
								 | 
							
								  - 创建用于输出结果的UAV对象OutSkyLightTexture、OutHitDistanceTexture,并且取得SceneTextures。
							 | 
						|||
| 
								 | 
							
								  - 遍历所有View计算天光结果。
							 | 
						|||
| 
								 | 
							
								    - 填充FRayTracingSkyLightRGS::FParameters。如果视口内有头发,将会额外绑定HairStrandsVoxelUniformParameters。
							 | 
						|||
| 
								 | 
							
								    - 设置FRayTracingSkyLightRGS变体。
							 | 
						|||
| 
								 | 
							
								    - 计算FIntPoint RayTracingResolution = View.ViewRect.Size() / UpscaleFactor;
							 | 
						|||
| 
								 | 
							
								    - RayTraceDispatch()。
							 | 
						|||
| 
								 | 
							
								    - Denoising
							 | 
						|||
| 
								 | 
							
								    - 如果SceneViewState有效,返回SkyLightVisibilityRaysDimensions。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								- 合成SkyLight
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### FRayTracingSkyLightRGS
							 | 
						|||
| 
								 | 
							
								FRayTracingSkyLightRGS是一个GlobalShader,但因为是一个RayTracing Shader,所以宏的类型为:
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								IMPLEMENT_GLOBAL_SHADER(FRayTracingSkyLightRGS, "/Engine/Private/Raytracing/RaytracingSkylightRGS.usf", "SkyLightRGS", SF_RayGen);
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								TLAS数据位于通过Scene->RayTracingScene->RayTracingSceneSRV。
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								PassParameters->TLAS = View.GetRayTracingSceneViewChecked();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								FRHIShaderResourceView* FViewInfo::GetRayTracingSceneViewChecked() const
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									FRHIShaderResourceView* Result = nullptr;
							 | 
						|||
| 
								 | 
							
									check(Family);
							 | 
						|||
| 
								 | 
							
									if (Family->Scene)
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										if (FScene* Scene = Family->Scene->GetRenderScene())
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											Result = Scene->RayTracingScene.GetShaderResourceViewChecked();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									checkf(Result, TEXT("Ray tracing scene SRV is expected to be created at this point."));
							 | 
						|||
| 
								 | 
							
									return Result;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								FRHIShaderResourceView* FRayTracingScene::GetShaderResourceViewChecked() const
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									checkf(RayTracingSceneSRV.IsValid(), TEXT("Ray tracing scene SRV was not created. Perhaps BeginCreate() was not called."));
							 | 
						|||
| 
								 | 
							
									return RayTracingSceneSRV.GetReference();
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#### AddPass
							 | 
						|||
| 
								 | 
							
								RayGem的AddPass()标记为ERDGPassFlags::Compute。RHICmdList.RayTraceDispatch()需要RayGem管线状态、Shader、RayTracingSceneRHI、RayTracing资源与分辨率。
							 | 
						|||
| 
								 | 
							
								FRayTracingPipelineStateInitializer管线状态需要:
							 | 
						|||
| 
								 | 
							
								- MaxPayloadSizeInBytes
							 | 
						|||
| 
								 | 
							
								- RayGenShaderTable
							 | 
						|||
| 
								 | 
							
								- HitGroupTable
							 | 
						|||
| 
								 | 
							
								- bAllowHitGroupIndexing
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								FIntPoint RayTracingResolution = View.ViewRect.Size() / UpscaleFactor;
							 | 
						|||
| 
								 | 
							
								GraphBuilder.AddPass(
							 | 
						|||
| 
								 | 
							
									RDG_EVENT_NAME("SkyLightRayTracing %dx%d", RayTracingResolution.X, RayTracingResolution.Y),
							 | 
						|||
| 
								 | 
							
									PassParameters,
							 | 
						|||
| 
								 | 
							
									ERDGPassFlags::Compute,
							 | 
						|||
| 
								 | 
							
									[PassParameters, this, &View, RayGenerationShader, RayTracingResolution](FRHIRayTracingCommandList& RHICmdList)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									//资源绑定,将Texture、UniformStruct绑定的工具函数
							 | 
						|||
| 
								 | 
							
									FRayTracingShaderBindingsWriter GlobalResources;
							 | 
						|||
| 
								 | 
							
									SetShaderParameters(GlobalResources, RayGenerationShader, *PassParameters);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									//取得RayTracing管线状态
							 | 
						|||
| 
								 | 
							
									FRayTracingPipelineState* Pipeline = View.RayTracingMaterialPipeline;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									//如果没开启RayTracing天光材质,则重新创建一个RayTracing管线状态。看得出主要需求RayGemShader与HitGroupTable
							 | 
						|||
| 
								 | 
							
									if (CVarRayTracingSkyLightEnableMaterials.GetValueOnRenderThread() == 0)
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										// Declare default pipeline
							 | 
						|||
| 
								 | 
							
										FRayTracingPipelineStateInitializer Initializer;
							 | 
						|||
| 
								 | 
							
										Initializer.MaxPayloadSizeInBytes = RAY_TRACING_MAX_ALLOWED_PAYLOAD_SIZE; // sizeof(FPackedMaterialClosestHitPayload)
							 | 
						|||
| 
								 | 
							
										FRHIRayTracingShader* RayGenShaderTable[] = { RayGenerationShader.GetRayTracingShader() };
							 | 
						|||
| 
								 | 
							
										Initializer.SetRayGenShaderTable(RayGenShaderTable);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										FRHIRayTracingShader* HitGroupTable[] = { View.ShaderMap->GetShader<FOpaqueShadowHitGroup>().GetRayTracingShader() };
							 | 
						|||
| 
								 | 
							
										Initializer.SetHitGroupTable(HitGroupTable);
							 | 
						|||
| 
								 | 
							
										Initializer.bAllowHitGroupIndexing = false; // Use the same hit shader for all geometry in the scene by disabling SBT indexing.
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										Pipeline = PipelineStateCache::GetAndOrCreateRayTracingPipelineState(RHICmdList, Initializer);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									FRHIRayTracingScene* RayTracingSceneRHI = View.GetRayTracingSceneChecked();
							 | 
						|||
| 
								 | 
							
									RHICmdList.RayTraceDispatch(Pipeline, RayGenerationShader.GetRayTracingShader(), RayTracingSceneRHI, GlobalResources, RayTracingResolution.X, RayTracingResolution.Y);
							 | 
						|||
| 
								 | 
							
								});
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#### Shader
							 | 
						|||
| 
								 | 
							
								- 计算DispatchThreadId以及对应的屏幕UV。并且取得对应的FGBufferData。
							 | 
						|||
| 
								 | 
							
								- 计算出WorldPosition以及CameraDirection。
							 | 
						|||
| 
								 | 
							
								- 判断是否需要追踪光线: 是否是有限深度 && 当前像素的ShaderModel不是Unlit。如果需要追踪采样数为传入Shader的 SkyLight.SamplesPerPixel,否则为0。
							 | 
						|||
| 
								 | 
							
								- 调用SkyLightEvaluate(),进行光追计算。
							 | 
						|||
| 
								 | 
							
								  - 初始化相关函数。
							 | 
						|||
| 
								 | 
							
								  - 计算天光采样PDF。
							 | 
						|||
| 
								 | 
							
								  - 采样循环
							 | 
						|||
| 
								 | 
							
								    - 根据bDecoupleSampleGeneration(),选择执行使用SkyLightVisibilityRays的样本 或者使用随机序列生成样本。
							 | 
						|||
| 
								 | 
							
								    - 如果当前像素的ShadingModel是Hair,需要重新计算CurrentWorldNormal。
							 | 
						|||
| 
								 | 
							
								    - 偏移当前光线的深度,并计算NoL。
							 | 
						|||
| 
								 | 
							
								    - 设置RayFlags,并且调用TraceVisibilityRay()进行光线追踪。返回FMinimalPayload(存光线命中距离信息)
							 | 
						|||
| 
								 | 
							
								    - 如果命中,累加RayDistance与HitCount。如没命中,累加BentNormal,并且计算FDirectLighting(光照计算,Hair会用另一套计算方式),最后累加ExitantRadiance、DiffuseThroughput、DiffuseExitantRadiance。
							 | 
						|||
| 
								 | 
							
								    - ExitantRadiance、DiffuseThroughput、DiffuseExitantRadiance除以样本数目(HitDistance = RayDistance / HitCount)。
							 | 
						|||
| 
								 | 
							
								    - 如果当前像素的ShadingModel是Hair,增加头发多重散射贡献值。
							 | 
						|||
| 
								 | 
							
								- 合成估算结果。DiffuseExitantRadiance.r = Albedo.r > 0.0 ? DiffuseExitantRadiance.r / Albedo.r : DiffuseExitantRadiance.r;
							 | 
						|||
| 
								 | 
							
								- 乘以曝光值。
							 | 
						|||
| 
								 | 
							
								- 返回RWSkyOcclusionMaskUAV[DispatchThreadId]=float4(ClampToHalfFloatRange(DiffuseExitantRadiance.rgb), AmbientOcclusion);RWSkyOcclusionRayDistanceUAV[DispatchThreadId] = float2(HitDistance, SamplesPerPixel);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#### 降噪(Denoising)
							 | 
						|||
| 
								 | 
							
								- 调用IScreenSpaceDenoiser接口取得默认降噪器
							 | 
						|||
| 
								 | 
							
								- 设置IScreenSpaceDenoiser::FDiffuseIndirectInputs的Color与RayHitDistance(OutSkyLightTexture、OutHitDistanceTexture)
							 | 
						|||
| 
								 | 
							
								- 设置IScreenSpaceDenoiser::FAmbientOcclusionRayTracingConfig的ResolutionFraction与RayCountPerPixel(ResolutionFraction、GetSkyLightSamplesPerPixel(SkyLight))
							 | 
						|||
| 
								 | 
							
								- 调用DenoiseSkyLight()输出降噪后的结果覆盖OutSkyLightTexture。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								if (GRayTracingSkyLightDenoiser != 0)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									//取得默认降噪器
							 | 
						|||
| 
								 | 
							
									const IScreenSpaceDenoiser* DefaultDenoiser = IScreenSpaceDenoiser::GetDefaultDenoiser();
							 | 
						|||
| 
								 | 
							
									const IScreenSpaceDenoiser* DenoiserToUse = DefaultDenoiser;// GRayTracingGlobalIlluminationDenoiser == 1 ? DefaultDenoiser : GScreenSpaceDenoiser;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									//降噪器变量结构体需要使用之前的渲染结果以及Hit距离结果
							 | 
						|||
| 
								 | 
							
									IScreenSpaceDenoiser::FDiffuseIndirectInputs DenoiserInputs;
							 | 
						|||
| 
								 | 
							
									DenoiserInputs.Color = OutSkyLightTexture;
							 | 
						|||
| 
								 | 
							
									DenoiserInputs.RayHitDistance = OutHitDistanceTexture;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										//初始化RayTracingConfig
							 | 
						|||
| 
								 | 
							
										IScreenSpaceDenoiser::FAmbientOcclusionRayTracingConfig RayTracingConfig;
							 | 
						|||
| 
								 | 
							
										RayTracingConfig.ResolutionFraction = ResolutionFraction;
							 | 
						|||
| 
								 | 
							
										RayTracingConfig.RayCountPerPixel = GetSkyLightSamplesPerPixel(SkyLight);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										RDG_EVENT_SCOPE(GraphBuilder, "%s%s(SkyLight) %dx%d",
							 | 
						|||
| 
								 | 
							
											DenoiserToUse != DefaultDenoiser ? TEXT("ThirdParty ") : TEXT(""),
							 | 
						|||
| 
								 | 
							
											DenoiserToUse->GetDebugName(),
							 | 
						|||
| 
								 | 
							
											View.ViewRect.Width(), View.ViewRect.Height());
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										//降噪
							 | 
						|||
| 
								 | 
							
										IScreenSpaceDenoiser::FDiffuseIndirectOutputs DenoiserOutputs = DenoiserToUse->DenoiseSkyLight(
							 | 
						|||
| 
								 | 
							
											GraphBuilder,
							 | 
						|||
| 
								 | 
							
											View,
							 | 
						|||
| 
								 | 
							
											&View.PrevViewInfo,
							 | 
						|||
| 
								 | 
							
											SceneTextures,
							 | 
						|||
| 
								 | 
							
											DenoiserInputs,
							 | 
						|||
| 
								 | 
							
											RayTracingConfig);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										//输出结果
							 | 
						|||
| 
								 | 
							
										OutSkyLightTexture = DenoiserOutputs.Color;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## RenderRayTracingDebug
							 | 
						|||
| 
								 | 
							
								位于渲染Fog与Translucency、VirtualTextureFeedbackEnd()之后
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								#if RHI_RAYTRACING
							 | 
						|||
| 
								 | 
							
									if (IsRayTracingEnabled())
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										// Path tracer requires the full ray tracing pipeline support, as well as specialized extra shaders.
							 | 
						|||
| 
								 | 
							
										// Most of the ray tracing debug visualizations also require the full pipeline, but some support inline mode.
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										if (ViewFamily.EngineShowFlags.PathTracing 
							 | 
						|||
| 
								 | 
							
											&& FDataDrivenShaderPlatformInfo::GetSupportsPathTracing(Scene->GetShaderPlatform()))
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											for (const FViewInfo& View : Views)
							 | 
						|||
| 
								 | 
							
											{
							 | 
						|||
| 
								 | 
							
												RenderPathTracing(GraphBuilder, View, SceneTextures.UniformBuffer, SceneTextures.Color.Target);
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else if (ViewFamily.EngineShowFlags.RayTracingDebug)
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											for (const FViewInfo& View : Views)
							 | 
						|||
| 
								 | 
							
											{
							 | 
						|||
| 
								 | 
							
												RenderRayTracingDebug(GraphBuilder, View, SceneTextures.Color.Target);
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								DebugVisualizationMode具有3中模式:
							 | 
						|||
| 
								 | 
							
								- TRAVERSAL:使用ComputeShader
							 | 
						|||
| 
								 | 
							
								- RAY_TRACING_DEBUG_VIZ_PRIMARY_RAYS:使用SF_RayGen,FRayTracingPrimaryRaysRGS
							 | 
						|||
| 
								 | 
							
								- DebugVisualizationMode == RAY_TRACING_DEBUG_VIZ_INSTANCES || DebugVisualizationMode == RAY_TRACING_DEBUG_VIZ_TRIANGLES;使用SF_RayGen,FRayTracingDebugRGS 
							 |