137 lines
6.8 KiB
Markdown
137 lines
6.8 KiB
Markdown
|
---
|
|||
|
title: 剖析虚幻渲染体系(05)- 光源和阴影
|
|||
|
date: 2024-02-08 17:48:39
|
|||
|
excerpt:
|
|||
|
tags:
|
|||
|
rating: ⭐
|
|||
|
---
|
|||
|
# 前言
|
|||
|
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:主要定义了跟图形API(DirectX、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.ush**的`SetGBufferForShadingModel`。
|
|||
|
- **DeferredLightingCommon.ush**:此模块定义了延迟光照相关的通用的接口、宏、变量、类型等。
|
|||
|
|
|||
|
# BasePass
|
|||
|
下面是`RenderBasePass`和`RenderBasePassViewParallel`并行渲染的逻辑:
|
|||
|
```c++
|
|||
|
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分别是`TBasePassVS`和`TBasePassPS`。
|
|||
|
可知`TBasePassVS`提供了获取Shader绑定、更改编译环境和只编译指定的排列组合shader等接口,此外还拥有反射球、光照图类型等属性。下面是它的获取shader绑定的代码分析:
|
|||
|
```c++
|
|||
|
```
|