6.8 KiB
Raw Blame History

title, date, excerpt, tags, rating
title date excerpt tags rating
剖析虚幻渲染体系05- 光源和阴影 2024-02-08 17:48:39

前言

https://www.cnblogs.com/timlly/p/14817455.html

Shader体系

Shader模块层级

第一梯队的shader模块是最底层最基础的模块,这些模块不会引用其它模块,但会被其它很多模块引用。这些模块主要有:

  • BasePassCommon.ush
  • BRDF.ush
  • CapsuleLight.ush
  • Common.ush
  • CommonViewUniformBuffer.ush
  • Definitions.usf
  • FP16Math.ush
  • Platform.ush
  • ShaderVersion.ush
  • LightGridCommon.ush
  • LocalVertexFactoryCommon.ush
  • ShadingCommon.ush
  • ShadowDepthCommon.ush
  • ShadowProjectionCommon.ush
  • SHCommon.ush
  • (......)

第二梯队重要或基础模块会引用第一梯队的基础模块,但也会被其它梯队或模块引用:

  • BasePassVertexCommon.ush
  • CapsuleLightIntegrate.ush
  • DeferredLightingCommon.ush
  • DeferredShadingCommon.ush
  • LocalVertexFactory.ush
  • MaterialTemplate.ush
  • RectLight.ush
  • RectLightIntegrate.ush
  • ShadingModels.ush
  • ShadingModelsMaterial.ush
  • VertexFactoryCommon.ush
  • (......)

最后是第三梯队的模块,重要模块的实现,会引用第一、第二梯队的模块:

  • BasePassPixelShader.usf
  • BasePassVertexShader.usf
  • CapsuleShadowShaders.usf
  • DeferredLightPixelShaders.usf
  • DeferredLightVertexShaders.usf
  • ShadowProjectionPixelShader.usf
  • ShadowProjectionVertexShader.usf
  • (......)

Shader基础模块

  • Platform.ush主要定义了跟图形APIDirectX、OpenGL、Vulkan、Metal和FEATURE_LEVEL相关的宏、变量及工具类接口。
  • Common.ush此模块主要包含了图形API或Feature Level相关的宏、类型、局部变量、静态变量、基础工具接口、常用Shader函数等。
  • Definitions.ush:此模块主要是预先定义了一些常见的宏,防止其它模块引用时出现语法错误。
  • ShadingCommon.ush此模块主要是定义了材质所有ShaderModel并提供了少量相关的工具类接口。
  • ShadingModels.ush:此模块主要是着色模型以及光照计算相关的类型和辅助接口。
  • BasePassCommon.ush此模块定义了BasePass的一些变量、宏定义、插值结构体和工具类接口。
  • ShadingModelsMaterial.ush提供了根据材质和指定参数设置GBuffe的接口。
  • BRDF.ush双向反射分布函数模块提供了很多基础光照算法及相关辅助接口。
  • VertexFactoryCommon.ush此模块主要定义了顶点变换相关的辅助接口。
  • LocalVertexFactoryCommon.ush局部顶点工厂通用模块定义了顶点工厂的数据插值结构体及部分辅助接口。
  • LocalVertexFactory.ush局部顶点工厂模块定义了骨骼蒙皮、顶点着色器等相关的数据类型和接口。
  • BasePassVertexCommon.ush此模块定义了一些BasePass通用的结构体、宏。
    • 需要注意的是核心结构体FGBufferData它是通用的结构体可用于BasePass和LightingPass的VS和PS之间也可用于前向和延迟渲染中。是最大数据集合体,在某些情况下,部分属性才有效,具体见ShadingModelsMaterial.ushSetGBufferForShadingModel
  • DeferredLightingCommon.ush:此模块定义了延迟光照相关的通用的接口、宏、变量、类型等。

BasePass

下面是RenderBasePassRenderBasePassViewParallel并行渲染的逻辑:

bool FDeferredShadingSceneRenderer::RenderBasePass(FRHICommandListImmediate& RHICmdList, FExclusiveDepthStencil::Type BasePassDepthStencilAccess, IPooledRenderTarget* ForwardScreenSpaceShadowMask, bool bParallelBasePass, bool bRenderLightmapDensity)
{
    (......)
    
    FExclusiveDepthStencil::Type BasePassDepthStencilAccess_NoDepthWrite = FExclusiveDepthStencil::Type(BasePassDepthStencilAccess & ~FExclusiveDepthStencil::DepthWrite);
    // 并行模式
    if (bParallelBasePass)
    {
        // 绘制任务等待.
        FScopedCommandListWaitForTasks Flusher(CVarRHICmdFlushRenderThreadTasksBasePass.GetValueOnRenderThread() > 0 || CVarRHICmdFlushRenderThreadTasks.GetValueOnRenderThread() > 0, RHICmdList);
        
        // 遍历所有view, 每个view渲染一次Base Pass.
        for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
        {
            FViewInfo& View = Views[ViewIndex];

            // Uniform Buffer
            TUniformBufferRef<FOpaqueBasePassUniformParameters> BasePassUniformBuffer;
            CreateOpaqueBasePassUniformBuffer(RHICmdList, View, ForwardScreenSpaceShadowMask, nullptr, nullptr, nullptr, BasePassUniformBuffer);

            // Render State
            FMeshPassProcessorRenderState DrawRenderState(View, BasePassUniformBuffer);
            SetupBasePassState(BasePassDepthStencilAccess, ViewFamily.EngineShowFlags.ShaderComplexity, DrawRenderState);

            const bool bShouldRenderView = View.ShouldRenderView();
            if (bShouldRenderView)
            {
                Scene->UniformBuffers.UpdateViewUniformBuffer(View);

                // 执行并行渲染.
                RenderBasePassViewParallel(View, RHICmdList, BasePassDepthStencilAccess, DrawRenderState);
            }

            FSceneRenderTargets::Get(RHICmdList).BeginRenderingGBuffer(RHICmdList, ERenderTargetLoadAction::ELoad, ERenderTargetLoadAction::ELoad, BasePassDepthStencilAccess, this->ViewFamily.EngineShowFlags.ShaderComplexity);
            RHICmdList.EndRenderPass();

            (......)
        }
    }

    (......)
}

void FDeferredShadingSceneRenderer::RenderBasePassViewParallel(FViewInfo& View, FRHICommandListImmediate& ParentCmdList, FExclusiveDepthStencil::Type BasePassDepthStencilAccess, const FMeshPassProcessorRenderState& InDrawRenderState)
{
    // 并行绘制的数据: 命令队列, 上下文, 渲染状态等.
    FBasePassParallelCommandListSet ParallelSet(View, ParentCmdList, 
        CVarRHICmdBasePassDeferredContexts.GetValueOnRenderThread() > 0, 
        CVarRHICmdFlushRenderThreadTasksBasePass.GetValueOnRenderThread() == 0 && CVarRHICmdFlushRenderThreadTasks.GetValueOnRenderThread() == 0,
        this,
        BasePassDepthStencilAccess,
        InDrawRenderState);

    // 触发并行绘制指令.
    View.ParallelMeshDrawCommandPasses[EMeshPass::BasePass].DispatchDraw(&ParallelSet, ParentCmdList);
}

RenderBasePass是依靠FScopedCommandListWaitForTasks等待绘制指令完成。

BasePass渲染状态

我们知道BasePass是通过FBasePassMeshProcessor来收集很多shader绑定和绘制参数的从Processor的过程中可以很容易知道BasePass绘制时使用的VS和PS分别是TBasePassVSTBasePassPS。 可知TBasePassVS提供了获取Shader绑定、更改编译环境和只编译指定的排列组合shader等接口此外还拥有反射球、光照图类型等属性。下面是它的获取shader绑定的代码分析