Contents

UE4 主渲染函数

Contents

从今天起,我将从主渲染函数入手,来整理整个UE4的渲染内容和框架,这将是一个非常漫长和艰巨的任务,因为其内容实在是太多,虚幻的更新速度也是超乎寻常的快,但是以后的版本应该不会有大的调整,毕竟新的框架直接用在UE5就可以了。

这里我们只是笼统的将Render函数那一个层级所出现的内容进行概况和整理,每一个概念的内部原理将会在之后的该系列文章中进行讲解。

虚化中目前的渲染基类为FSceneRenderer,其一共有两个派生类,一个是FDeferredShadingSceneRenderer,另一个是FMobileSceneRenderer。当然我们就算是在编辑器里选择为前向渲染,其本身还是会走FDeferredShadingSceneRendererFMobileSceneRenderer确实是移动平台才会创建的类型。我们讲讨论feature更完备的FDeferredShadingSceneRenderer

关于延迟渲染和前向渲染这种问题到底还需不需要讨论,如果有讨论的必要请在评论区留言,否则就默认大家都会的。因为实在是没办法照顾到所有人的学习阶段,是统一天坑还是我讲我的,前期很多概念没有达成共识的话,基本上很难理解剩下的内容。

在这里我将去掉与头发、光线追踪,虚拟纹理相关内容,因为他们比较凌乱,后面如果有可能会出专题。

看代码之前我们可以使用RenderDoc来抓帧unreal,只要安装了RenderDoc并且你启用了对应的插件。之后你就会看到对应的渲染列表。

https://papalqiblog.oss-cn-beijing.aliyuncs.com/blog/picture20210207195603.png

这可以帮助你快速的对应代码,图形化的帮助你理解每一步的用处。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//更新需要添加到scene和需要删除的物体。
Scene->UpdateAllPrimitiveSceneInfos(RHICmdList, true);

//抗锯齿策略,分辨率大小比例,窗口大小,屏幕百分比策略
PrepareViewRectsForRendering();

//场景中是否存在天空大气的渲染需求,进行准备工作
PrepareSunLightProxy(*Scene->GetSkyAtmosphereSceneInfo(),LightIndex, *Scene->AtmosphereLights[LightIndex]);
//如果存在多GPU,计算GPUMask
ComputeViewGPUMasks(RenderTargetGPUMask);
//将RT池中的rt设置为可写入
GRenderTargetPool.TransitionTargetsWritable(RHICmdList);
//清理所有的sceneColor
SceneContext.ReleaseSceneColor();
//等待上一帧的遮挡剔除完成
WaitOcclusionTests(RHICmdList);
//初始化纯色的那些贴图
GSystemTextures.InitializeTextures(RHICmdList, FeatureLevel);
//重新分配所有的RT
SceneContext.Allocate(RHICmdList, this);
//进行物体的装配和渲染pass的组装,做剔除
bDoInitViewAftersPrepass = InitViews(RHICmdList, BasePassDepthStencilAccess, ILCTaskData, UpdateViewCustomDataEvents);

//更新GPUscene,所有的物体都在GPU里有一套,可以用来还原场景和进行数据访问
UpdateGPUScene(RHICmdList, *Scene);

//加载GPUScene 的dunamic data
UploadDynamicPrimitiveShaderDataForView(RHICmdList, *Scene, View);
//准备距离场信息
PrepareDistanceFieldScene(RHICmdList, bSplitDispatch);
//遮挡查询,当然是是跟你的硬件平台支持相关,遮挡查询是使用硬件的api特性来做的。
DoOcclusionQueries(FeatureLevel)
//提交DynamicBuffer
//预计算Dither stencil
PreRenderDitherFill(RHICmdList, SceneContext, StencilTextureUAV);
//渲染天空大气的LookUpTable
RenderSkyAtmosphereLookUpTables(RHICmdList);
//通知将要渲染特效,进行排序
GPUSortManager->OnPreRender(RHICmdList);
//等待DitherFill完成
RHICmdList.WaitComputeFence(AsyncDitherLODEndFence);

//将GPUSkin的Cache设置为Render
RunGPUSkinCacheTransition(RHICmdList, Scene, EGPUSkinCacheTransition::Renderer);

//开始渲染第一个pass Pre pass
RenderPrePass(RHICmdList, AfterTasksAreStarted);
  
//搜集场景中所有的光源,进行光源网格的计算
GatherAndSortLights(SortedLightSet);
ComputeLightGrid(RHICmdList, bComputeLightGrid, SortedLightSet);

//遮挡查询,为下一帧所使用,本帧的遮挡使用的是上一帧的数据
RenderOcclusion(RHICmdList);
bool bUseHzbOcclusion = RenderHzb(RHICmdList);
FinishOcclusion(RHICmdList);
if (bOcclusionBeforeBasePass)
{
    //如果开启选项 提早渲染阴影
    RenderShadowDepthMaps(RHICmdList);

    //计算体积雾
    ComputeVolumetricFog(RHICmdList);
}
//清理LPV
ClearLPVs(RHICmdList);


//计算Dbuffer                       
GCompositionLighting.ProcessBeforeBasePass(RHICmdList, View, bDBuffer, SSAOLevels);

//渲染CapsuleShadow
RenderIndirectCapsuleShadows(……)
if(GetCustomDepthPassLocation() == 0)
{
    //根据选项判断是否需要渲染CustomDepth
    RenderCustomDepthPassAtLocation(RHICmdList, 0);
};


//建立我们 的Gbuffer
SceneContext.BeginRenderingGBuffer(RHICmdList, ColorLoadAction, DepthLoadAction, BasePassDepthStencilAccess, 
ViewFamily.EngineShowFlags.ShaderComplexity, true, ClearColor);
//写Gbuffer
RenderBasePass()

if (!bOcclusionBeforeBasePass)
{
	RenderShadowDepthMaps(RHICmdList);
    ComputeVolumetricFog(RHICmdList);
}
if(GetCustomDepthPassLocation() == 1)
{
	RenderCustomDepthPassAtLocation(RHICmdList, 1);
}




//进行Lighting
RenderDiffuseIndirectAndAmbientOcclusion(RHICmdList);
RenderIndirectCapsuleShadows();
RenderDFAOAsIndirectShadowing(RHICmdList, SceneContext.SceneVelocity, DynamicBentNormalAO);
RenderLights(RHICmdList, SortedLightSet, HairDatas);
InjectAmbientCubemapTranslucentVolumeLighting();
FilterTranslucentVolumeLighting(RHICmdList, View, ViewIndex);
RenderDeferredReflectionsAndSkyLighting(RHICmdList, DynamicBentNormalAO, 


//渲染水体
RenderUnderWaterFog(RHICmdList, SingleLayerWaterPassData);
RenderSingleLayerWaterPass(RHICmdList, SingleLayerWaterPassData, WaterPassDepthStencilAccess, bDoParallelSingleLayerWater);
RenderSingleLayerWaterReflections(RHICmdList, SingleLayerWaterPassData);
//渲染光束
RenderLightShaftOcclusion(RHICmdList, LightShaftOutput);

//渲染大气
RenderAtmosphere(RHICmdList, LightShaftOutput);
RenderSkyAtmosphere(RHICmdList);

//渲染雾
RenderFog(RHICmdList, LightShaftOutput);
RendererModule.RenderPostOpaqueExtensions();

//通知特效系统已经渲染完了
Scene->FXSystem->PostRenderOpaque();
//GPU粒子渲染完的回调。
GPUSortManager->OnPostRenderOpaque(RHICmdList);

//渲染那些材质标识为透明的物体
RenderTranslucency(RHICmdList);

//渲染畸变
RenderDistortion(RHICmdList);
//渲染LightShaft
RenderLightShaftBloom(RHICmdList);

//渲染距离场AO
RenderDistanceFieldLighting(RHICmdList, FDistanceFieldAOParameters(OcclusionMaxDistance), SceneContext.SceneVelocity, DummyOutput, false, ViewFamily.EngineShowFlags.VisualizeDistanceFieldAO);

//执行默认的后处理,和自定义的后处理
FRDGBuilder GraphBuilder(RHICmdList);
AddDebugPostProcessingPasses(GraphBuilder, View, PostProcessingInputs);
AddPostProcessingPasses(GraphBuilder, View, PostProcessingInputs);
SceneContext.FreeSeparateTranslucency();
SceneContext.FreeSeparateTranslucencyModulate();
SceneContext.SetSceneColor(nullptr);
SceneContext.AdjustGBufferRefCount(GraphBuilder.RHICmdList, -1);
GraphBuilder.Execute();
//执行那些在默认后处理后面的自定义后处理材质
GRenderTargetPool.AddPhaseEvent(TEXT("AfterPostprocessing"));