延迟渲染到最终结果------3,prepass预处理阶段(大象无形11.3.1)

回顾目前流程

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
    )

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值