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

延迟渲染到最终结果——3,prepass预处理阶段(大象无形11.3.1)回顾目前流程一,按需要重新分配渲染目标1,voidFSceneRenderTargets::AllocDummyGBufferTargets(FRHICommandList&RHICmdList)1.1,templa

回顾目前流程

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

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注