回顾目前流程
void FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList);
一,按需要重新分配渲染目标
1,void FSceneRenderTargets::AllocDummyGBufferTargets(FRHICommandList& RHICmdList)
1.1, template<typename InitializerType,typename RHIRefType,typename RHIParamRefType> static RHIParamRefType TStaticStateRHI<typename InitializerType,typename RHIRefType,typename RHIParamRefType>::GetRHI();
1.2,FGBufferResourceStruct::CreateUniformBuffer(GBufferResourceStruct, UniformBuffer_SingleFrame);
二,初始化视口(可以多个),包括确定可见性与设置阴影相关参数
1,bool FDeferredShadingSceneRenderer::InitViews(FRHICommandListImmediate& RHICmdList, struct FILCUpdatePrimTaskData& ILCTaskData, FGraphEventArray& SortEvents)
1.1,预设置可见性
void FSceneRenderer::PreVisibilityFrameSetup(FRHICommandListImmediate& RHICmdList)
1.1.1,根据当前画质设置,设置TemporalAA的采样方式,同时确定采样位置,
1.1.1.1, uint32 FSceneViewState::GetCurrentTemporalAASampleIndex() const
1.1.1.2,void FViewMatrices::HackAddTemporalAAProjectionJitter(const FVector2D& InTemporalAAProjectionJitter)
1.1.2,设置视口矩阵,包括视口投影矩阵和转换矩阵
void FViewMatrices::ApplyWorldOffset(const FVector& InOffset)
1.2,可见性计算
void FSceneRenderer::ComputeViewVisibility(FRHICommandListImmediate& RHICmdList)
1.2.1,初始化一系列用于可视化检测的缓冲区,(位数组,0和1代表是否可见)
1.2.2,用六棱锥进行筛选(a,b代表true或者false),不可见的对象的可视化检测缓冲区对应的比特位设置为0
template<bool UseCustomCulling, bool bAlsoUseSphereTest>
static int32 FrustumCull(const FScene* Scene, FViewInfo& View)
1.2.3,线框模式下,对直接剔除,剔除所有的非线框和过小的线框
1.2.4,在非线框模式下,对于处于视口范围内,但是被其他对象遮挡的对象进行一次剔除
static int32 OcclusionCull(FRHICommandListImmediate& RHICmdList, const FScene* Scene, FViewInfo& View)
1.2.5,根据所有的可见性位图,设置每个需要渲染的对象的可见性状况,即Hiddenflags
void FLODSceneTree::UpdateAndApplyVisibilityStates(FViewInfo& View)
1.2.6,给每个对象返回自己是否可见的机会
1.2.7,获取所有动态对象的渲染信息
void FSceneRenderer::GatherDynamicMeshElements(
TArray<FViewInfo>& InViews,
const FScene* InScene,
const FSceneViewFamily& InViewFamily,
const FPrimitiveViewMasks& HasDynamicMeshElementsMasks,
const FPrimitiveViewMasks& HasDynamicEditorMeshElementsMasks,
FMeshElementCollector& Collector)
1.3,完成可见性计算
void FSceneRenderer::PostVisibilityFrameSetup(FILCUpdatePrimTaskData& OutILCTaskData)
1.3.1,对半透明对象进行排序,半透明对象的渲染由于涉及到互相遮挡,则必须按照从后往前的顺序来渲染,才能保 证渲染结果的正确性,因此,必须在此时完成排序
1.3.1.1,void FTranslucentPrimSet::SortPrimitives()
1.3.1.2,void FSceneViewState::TrimHistoryRenderTargets(const FScene* Scene)
1.3.2,对每个光照确定当前光照可见的对象列表,这里也是使用平截头体剔除,只需要测点光源和聚光灯,而平行光始 终可见
bool FConvexVolume::IntersectSphere(const FVector& Origin,const float& Radius) const
1.3.3,初始化雾与大气的常量值
void FSceneRenderer::InitFogConstants()
现在该进行第三阶段———prepass预处理阶段
三、prepass预处理阶段
1,判断是否需要预处理
void FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList)
{
…………….
const bool bNeedsPrePass = NeedsPrePass(this);
bool bDepthWasCleared;
if (bNeedsPrePass)
{
bDepthWasCleared = RenderPrePass(RHICmdList, AfterTasksAreStarted);
}
}
对于是否需要预处理,则需要同时满足两个条件
static FORCEINLINE bool NeedsPrePass(const FDeferredShadingSceneRenderer* Renderer)
{
//(1)不是基于分块的GPU,即TiledGPU,例如ARM移动端平台很多就是
return (RHIHasTiledGPU(Renderer->ViewFamily.GetShaderPlatform()) == false) &&
//(2)渲染器的EarlyZPassMode参数不为DDM_None,或者GEarlyZPassMovable不为0
(Renderer->EarlyZPassMode != DDM_None || Renderer->bEarlyZPassMovable != 0);
}
2,预处理
2.1设置渲染状态
bool FDeferredShadingSceneRenderer::RenderPrePass(FRHICommandListImmediate& RHICmdList, TFunctionRef<void()> AfterTasksAreStarted)
{
……………..
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
{
………….
const FViewInfo& View = Views[ViewIndex];
if (View.ShouldRenderView())
{
bDirty |= RenderPrePassView(RHICmdList, View);
}
………………
}
bool FDeferredShadingSceneRenderer::RenderPrePassView(FRHICommandList& RHICmdList, const FViewInfo& View)
{
bool bDirty = false;
FDrawingPolicyRenderState DrawRenderState(View);
SetupPrePassView(RHICmdList, View, DrawRenderState);
…….
}
static void SetupPrePassView(FRHICommandList& RHICmdList, const FViewInfo& View, FDrawingPolicyRenderState& DrawRenderState, const bool bIsEditorPrimitivePass = false)
{
// 关闭颜色写入,
DrawRenderState.SetBlendState(TStaticBlendState<CW_NONE>::GetRHI());
//打开深度测试与深度写入,不需要计算颜色,只需要计算每个不透明物体的像素的深度
DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<true, CF_DepthNearOrEqual>::GetRHI());
………
}
2.2,渲染三个绘制列表,这三个列表是由静态模型组成的,通过可见性位图控制是否可见。
bool FDeferredShadingSceneRenderer::RenderPrePassView(FRHICommandList& RHICmdList, const FViewInfo& View)
{
…….
{
//只绘制深度的对象列表,这个列表里的对象只在深度渲染过程中起作用。
SCOPED_DRAW_EVENT(RHICmdList, PosOnlyOpaque);
bDirty |= Scene->PositionOnlyDepthDrawList.DrawVisible(RHICmdList, View, DrawRenderState, View.StaticMeshOccluderMap, View.StaticMeshBatchVisibility);
}
{
// 深度绘制列表,是最主要的不透明物体渲染列表
SCOPED_DRAW_EVENT(RHICmdList, Opaque);
bDirty |= Scene->DepthDrawList.DrawVisible(RHICmdList, View, DrawRenderState, View.StaticMeshOccluderMap, View.StaticMeshBatchVisibility);
}
if (EarlyZPassMode >= DDM_AllOccluders)
{
//带蒙版的深度绘制列表,蒙版即对应材质系统中的Mask材质
SCOPED_DRAW_EVENT(RHICmdList, Masked);
bDirty |= Scene->MaskedDepthDrawList.DrawVisible(RHICmdList, View, DrawRenderState, View.StaticMeshOccluderMap, View.StaticMeshBatchVisibility);
}
。。。。。。。
}
2.3,绘制动态的预处理阶段对象
bool FDeferredShadingSceneRenderer::RenderPrePassView(FRHICommandList& RHICmdList, const FViewInfo& View)
{
…….
//
SCOPED_DRAW_EVENT(RHICmdList, Dynamic);
bDirty |= RenderPrePassViewDynamic(RHICmdList, View, DrawRenderState);
}
bool FDeferredShadingSceneRenderer::RenderPrePassViewDynamic(FRHICommandList& RHICmdList, const FViewInfo& View, const FDrawingPolicyRenderState& DrawRenderState)
{
……….
FDepthDrawingPolicyFactory::ContextType Context(EarlyZPassMode, true);
for (int32 MeshBatchIndex = 0; MeshBatchIndex < View.DynamicMeshElements.Num(); MeshBatchIndex++)
{
const FMeshBatchAndRelevance& MeshBatchAndRelevance = View.DynamicMeshElements[MeshBatchIndex];
if (MeshBatchAndRelevance.GetHasOpaqueOrMaskedMaterial() && MeshBatchAndRelevance.GetRenderInMainPass())
{
//询问RenderProxy是否被当作一个遮挡物体,决定是否需要在这个阶段绘制
bShouldUseAsOccluder = PrimitiveSceneProxy->ShouldUseAsOccluder()
// Only render static objects unless movable are requested
&& (!PrimitiveSceneProxy->IsMovable() || bEarlyZPassMovable)
&& (FMath::Square(PrimitiveSceneProxy->GetBounds().SphereRadius) > GMinScreenRadiusForDepthPrepass * GMinScreenRadiusForDepthPrepass * LODFactorDistanceSquared);
}
if (bShouldUseAsOccluder)
{
FDepthDrawingPolicyFactory::DrawDynamicMesh(RHICmdList, View, Context, MeshBatch, true, DrawRenderState, PrimitiveSceneProxy, MeshBatch.BatchHitProxyId, View.IsInstancedStereoPass());
}
}
}
return true;
}
4,对于DrawVisible绘制可见对象,
template<typename DrawingPolicyType>
bool TStaticMeshDrawList<DrawingPolicyType>::DrawVisible(
FRHICommandList& RHICmdList,
const FViewInfo& View,
const typename DrawingPolicyType::ContextDataType PolicyContext,
const FDrawingPolicyRenderState& DrawRenderState,
const TBitArray<SceneRenderingBitArrayAllocator>& StaticMeshVisibilityMap,
const TArray<uint64,SceneRenderingAllocator>& BatchVisibilityArray
)
{
//moved out of the inner loop and only modified if bDrawnShared
FDrawingPolicyRenderState DrawRenderStateLocal(DrawRenderState);
return DrawVisibleInner<InstancedStereoPolicy::Disabled>(RHICmdList, View, PolicyContext, DrawRenderStateLocal, &StaticMeshVisibilityMap, &BatchVisibilityArray, nullptr, 0, OrderedDrawingPolicies.Num() – 1, false);
}
/** Called by the RHI. Records the current bound shader state when r.UseShaderDrawLog or r.UseShaderPredraw are enabled. */
static DEPRECATED(4.16, “Use SetGraphicsPipelineState”) FORCEINLINE void SetBoundShaderState(FShaderCacheState* CacheState, FBoundShaderStateRHIParamRef State)
{
if ( Cache && CacheState)
{
Cache->InternalSetBoundShaderState(*CacheState, State);
}
}
说明已经SetBoundShaderState作废了,改用SetGraphicsPipelineState,怪不得找了半天没找见。这下明了了。
template<typename DrawingPolicyType>
template<InstancedStereoPolicy InstancedStereo>
int32 TStaticMeshDrawList<DrawingPolicyType>::DrawElement(
FRHICommandList& RHICmdList,
const FViewInfo& View,
const typename DrawingPolicyType::ContextDataType PolicyContext,
FDrawingPolicyRenderState& DrawRenderState,
const FElement& Element,
uint64 BatchElementMask,
FDrawingPolicyLink* DrawingPolicyLink,
bool& bDrawnShared
)
{
。。。。。。
//4.1,逐列表载入公共着色器信息,
CommitGraphicsPipelineState(RHICmdList, DrawingPolicyLink->DrawingPolicy, DrawRenderState, BoundShaderStateInput);
DrawingPolicyLink->DrawingPolicy.SetSharedState(RHICmdList, DrawRenderState, &View, PolicyContext);
/ /4.2,逐元素渲染,(组合过的BatchElement)
// 4.2.1设置渲染状态,
….
DrawingPolicyLink->DrawingPolicy.SetMeshRenderState(
RHICmdList,
View,
Proxy,
*Element.Mesh,
BatchElementIndex,
DrawRenderState,
Element.PolicyData,
PolicyContext
);
…..
//4.2.2实际绘制
DrawingPolicyLink->DrawingPolicy.DrawMesh(RHICmdList, *Element.Mesh, BatchElementIndex, true);
…….
}
4.1,
template<class DrawingPolicyType>
void CommitGraphicsPipelineState(FRHICommandList& RHICmdList, const DrawingPolicyType& DrawingPolicy, const FDrawingPolicyRenderState& DrawRenderState, const FBoundShaderStateInput& BoundShaderStateInput)
{
。。。。。。。
//载入需要的着色器
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);
……
}
void SetGraphicsPipelineState(FRHICommandList& RHICmdList, const FGraphicsPipelineStateInitializer& Initializer, EApplyRendertargetOption ApplyFlags)
{
RHICmdList.SetGraphicsPipelineState(GetAndOrCreateGraphicsPipelineState(RHICmdList, Initializer, ApplyFlags));
}
void FRHICommandList::SetGraphicsPipelineState(class FGraphicsPipelineState* GraphicsPipelineState)
void FMeshDrawingPolicy::SetSharedState(FRHICommandList& RHICmdList, const FDrawingPolicyRenderState& DrawRenderState, const FSceneView* View, const FMeshDrawingPolicy::ContextDataType PolicyContext) const
4.2.1,设置渲染状态
void FMeshDrawingPolicy::SetMeshRenderState(
FRHICommandList& RHICmdList,
const FSceneView& View,
const FPrimitiveSceneProxy* PrimitiveSceneProxy,
const FMeshBatch& Mesh,
int32 BatchElementIndex,
const FDrawingPolicyRenderState& DrawRenderState,
const ElementDataType& ElementData,
const ContextDataType PolicyContext
) const
4.2.2,绘制
void FMeshDrawingPolicy::DrawMesh(FRHICommandList& RHICmdList, const FMeshBatch& Mesh, int32 BatchElementIndex, const bool bIsInstancedStereo = false) const;
总结下:
void FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList);
一,按需要重新分配渲染目标
1,void FSceneRenderTargets::AllocDummyGBufferTargets(FRHICommandList& RHICmdList)
1.1, template<typename InitializerType,typename RHIRefType,typename RHIParamRefType> static RHIParamRefType TStaticStateRHI<typename InitializerType,typename RHIRefType,typename RHIParamRefType>::GetRHI();
1.2,FGBufferResourceStruct::CreateUniformBuffer(GBufferResourceStruct, UniformBuffer_SingleFrame);
二,初始化视口(可以多个),包括确定可见性与设置阴影相关参数
1,bool FDeferredShadingSceneRenderer::InitViews(FRHICommandListImmediate& RHICmdList, struct FILCUpdatePrimTaskData& ILCTaskData, FGraphEventArray& SortEvents)
1.1,预设置可见性
void FSceneRenderer::PreVisibilityFrameSetup(FRHICommandListImmediate& RHICmdList)
1.1.1,根据当前画质设置,设置TemporalAA的采样方式,同时确定采样位置,
1.1.1.1, uint32 FSceneViewState::GetCurrentTemporalAASampleIndex() const
1.1.1.2,void FViewMatrices::HackAddTemporalAAProjectionJitter(const FVector2D& InTemporalAAProjectionJitter)
1.1.2,设置视口矩阵,包括视口投影矩阵和转换矩阵
void FViewMatrices::ApplyWorldOffset(const FVector& InOffset)
1.2,可见性计算
void FSceneRenderer::ComputeViewVisibility(FRHICommandListImmediate& RHICmdList)
1.2.1,初始化一系列用于可视化检测的缓冲区,(位数组,0和1代表是否可见)
1.2.2,用六棱锥进行筛选(a,b代表true或者false),不可见的对象的可视化检测缓冲区对应的比特位设置为0
template<bool UseCustomCulling, bool bAlsoUseSphereTest>
static int32 FrustumCull(const FScene* Scene, FViewInfo& View)
1.2.3,线框模式下,对直接剔除,剔除所有的非线框和过小的线框
1.2.4,在非线框模式下,对于处于视口范围内,但是被其他对象遮挡的对象进行一次剔除
static int32 OcclusionCull(FRHICommandListImmediate& RHICmdList, const FScene* Scene, FViewInfo& View)
1.2.5,根据所有的可见性位图,设置每个需要渲染的对象的可见性状况,即Hiddenflags
void FLODSceneTree::UpdateAndApplyVisibilityStates(FViewInfo& View)
1.2.6,给每个对象返回自己是否可见的机会
1.2.7,获取所有动态对象的渲染信息
void FSceneRenderer::GatherDynamicMeshElements(
TArray<FViewInfo>& InViews,
const FScene* InScene,
const FSceneViewFamily& InViewFamily,
const FPrimitiveViewMasks& HasDynamicMeshElementsMasks,
const FPrimitiveViewMasks& HasDynamicEditorMeshElementsMasks,
FMeshElementCollector& Collector)
1.3,完成可见性计算
void FSceneRenderer::PostVisibilityFrameSetup(FILCUpdatePrimTaskData& OutILCTaskData)
1.3.1,对半透明对象进行排序,半透明对象的渲染由于涉及到互相遮挡,则必须按照从后往前的顺序来渲染,才能保证渲染结果的正确性,因此,必须在此时完成排序
1.3.1.1,void FTranslucentPrimSet::SortPrimitives()
1.3.1.2,void FSceneViewState::TrimHistoryRenderTargets(const FScene* Scene)
1.3.2,对每个光照确定当前光照可见的对象列表,这里也是使用平截头体剔除,只需要测点光源和聚光灯,而平行光始 终可见
bool FConvexVolume::IntersectSphere(const FVector& Origin,const float& Radius) const
1.3.3,初始化雾与大气的常量值
void FSceneRenderer::InitFogConstants()
三、prepass预处理阶段
1,判断是否需要预处理
void FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList)
2,预处理
2.1设置渲染状态
bool FDeferredShadingSceneRenderer::RenderPrePass(FRHICommandListImmediate& RHICmdList, TFunctionRef<void()> AfterTasksAreStarted)
2.1.1
bool FDeferredShadingSceneRenderer::RenderPrePassView(FRHICommandList& RHICmdList, const FViewInfo& View)
2.1.1.1
static void SetupPrePassView(FRHICommandList& RHICmdList, const FViewInfo& View, FDrawingPolicyRenderState& DrawRenderState, const bool bIsEditorPrimitivePass = false)
2.2,渲染三个绘制列表,这三个列表是由静态模型组成的,通过可见性位图控制是否可见。
bool FDeferredShadingSceneRenderer::RenderPrePassView(FRHICommandList& RHICmdList, const FViewInfo& View)
2.2.1,以StaticMesh为例绘制,
bool TStaticMeshDrawList<DrawingPolicyType>::DrawVisible(
FRHICommandList& RHICmdList,
const FViewInfo& View,
const typename DrawingPolicyType::ContextDataType PolicyContext,
const FDrawingPolicyRenderState& DrawRenderState,
const TBitArray<SceneRenderingBitArrayAllocator>& StaticMeshVisibilityMap,
const TArray<uint64,SceneRenderingAllocator>& BatchVisibilityArray
)
2.2.1.1载入公共着色器信息
template<typename DrawingPolicyType>
template<InstancedStereoPolicy InstancedStereo>
bool TStaticMeshDrawList<DrawingPolicyType>::DrawVisibleInner(
FRHICommandList& RHICmdList,
const FViewInfo& View,
const typename DrawingPolicyType::ContextDataType PolicyContext,
FDrawingPolicyRenderState& DrawRenderState,
const TBitArray<SceneRenderingBitArrayAllocator>* const StaticMeshVisibilityMap,
const TArray<uint64, SceneRenderingAllocator>* const BatchVisibilityArray,
const StereoPair* const StereoView,
int32 FirstPolicy, int32 LastPolicy,
bool bUpdateCounts
)
2.2.1.1.1
template<typename DrawingPolicyType>
template<InstancedStereoPolicy InstancedStereo>
int32 TStaticMeshDrawList<DrawingPolicyType>::DrawElement(
FRHICommandList& RHICmdList,
const FViewInfo& View,
const typename DrawingPolicyType::ContextDataType PolicyContext,
FDrawingPolicyRenderState& DrawRenderState,
const FElement& Element,
uint64 BatchElementMask,
FDrawingPolicyLink* DrawingPolicyLink,
bool& bDrawnShared
)
2.2.1.1.1.1,逐列表载入公共着色器信息
template<class DrawingPolicyType>
void CommitGraphicsPipelineState(FRHICommandList& RHICmdList, const DrawingPolicyType& DrawingPolicy, const FDrawingPolicyRenderState& DrawRenderState, const FBoundShaderStateInput& BoundShaderStateInput)
2.2.1.1.1.1.1
void SetGraphicsPipelineState(FRHICommandList& RHICmdList, const FGraphicsPipelineStateInitializer& Initializer, EApplyRendertargetOption ApplyFlags)
2.2.1.2.逐元素渲染(并非一对一的元素,而是经过组合的BatchElement)
2.2.1.2.1,设置渲染状态
void FMeshDrawingPolicy::SetMeshRenderState(
FRHICommandList& RHICmdList,
const FSceneView& View,
const FPrimitiveSceneProxy* PrimitiveSceneProxy,
const FMeshBatch& Mesh,
int32 BatchElementIndex,
const FDrawingPolicyRenderState& DrawRenderState,
const ElementDataType& ElementData,
const ContextDataType PolicyContext
) const
2.2.1.2.2,完成实际绘制
void FMeshDrawingPolicy::DrawMesh(FRHICommandList& RHICmdList, const FMeshBatch& Mesh, int32 BatchElementIndex, const bool bIsInstancedStereo = false) const;
2.3,绘制动态的预处理阶段对象
bool FDeferredShadingSceneRenderer::RenderPrePassViewDynamic(FRHICommandList& RHICmdList, const FViewInfo& View, const FDrawingPolicyRenderState& DrawRenderState)
2.3.1,询问RenderProxy是否被当作一个遮挡物体,决定是否需要在这个阶段绘制
FPrimitiveSceneProxy::ShouldUseAsOccluder()
2.3.2,具体绘制动态物体
bool FDepthDrawingPolicyFactory::DrawDynamicMesh(
FRHICommandList& RHICmdList,
const FViewInfo& View,
ContextType DrawingContext,
const FMeshBatch& Mesh,
bool bPreFog,
const FDrawingPolicyRenderState& DrawRenderState,
const FPrimitiveSceneProxy* PrimitiveSceneProxy,
FHitProxyId HitProxyId,
const bool bIsInstancedStereo,
const bool bIsInstancedStereoEmulated
)
今天的文章延迟渲染到最终结果——3,prepass预处理阶段(大象无形11.3.1)分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/64509.html