---
title: Untitled
date: 2024-09-25 14:59:32
excerpt: 
tags: 
rating: ⭐
---
# 前言
可以使用DrawDynamicMeshPass(),实现在插件中使用MeshDraw绘制Pass。

参考文章:
- ***UE5,为HairStrands添加自定义深度与模板***:https://zhuanlan.zhihu.com/p/689578355

# MeshDraw
推荐学习:
- CustomDepth
- RenderBasePassInternal()
- RenderAnisotropyPass()

Shader推荐:
- DepthOnlyVertexShader.usf
- DepthOnlyPixelShader.usf

# NaniteMeshDraw
`Engine\Source\Runtime\Renderer\Private\Nanite\`NaniteMaterials.h & NaniteMaterials.cpp

PS.使用的Shader必须是`FNaniteGlobalShader`的子类。

## BasePass
### DrawBasePass()
该函数在FDeferredShadingSceneRenderer::RenderBasePassInternal()中调用。

DrawNaniteMaterialPass() => SubmitNaniteIndirectMaterial()
## PSO
-  RDG 04 Graphics Pipeline State Initializer https://zhuanlan.zhihu.com/p/582020846 

- FGraphicsPipelineStateInitializer
	- FRHIDepthStencilState*           DepthStencilState
	- FRHIBlendState*                       BlendState
	- FRHIRasterizerState*                RasterizerState
	- EPrimitiveType                           PrimitiveType
	- FBoundShaderStateInput         BoundShaderState.VertexDeclarationRHI
	- FBoundShaderStateInput         BoundShaderState.VertexShaderRHI
	- FBoundShaderStateInput         BoundShaderState.PixelShaderRHI
	- ……

// 应用
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit,0);

## FMeshPassProcessorRenderState
- FMeshPassProcessorRenderState
	- FRHIBlendState*                         BlendState
	- FRHIDepthStencilState*             DepthStencilState
	- FExclusiveDepthStencil::Type    DepthStencilAccess
	- FRHIUniformBuffer*                    ViewUniformBuffer
	- FRHIUniformBuffer*                    InstancedViewUniformBuffer
	- FRHIUniformBuffer*                    PassUniformBuffer
	- FRHIUniformBuffer*                    NaniteUniformBuffer
	- uint32                                          StencilRef = 0;

### FRHIBlendState
使用***FBlendStateInitializerRHI()*** 进行初始化。
它定义了8个渲染对象,一般我们只用第一组,它的七个参数分别是:
- Color
	- Color Write Mask
	- Color Blend 混合类型
	- Color Src 混合因子
	- Color Dest 混合因子
- Alpha
	- Alpha Blend 混合类型
	- Alpha Src 混合因子
	- Alpha Dest 混合因子

```c++
FRHIBlendState* CopyBlendState = TStaticBlendState<CW_RGB, BO_Add, BF_SourceAlpha, BF_InverseSourceAlpha, BO_Add, BF_Zero, BF_One>::GetRHI();
```

颜色写入蒙版:
```c++
enum EColorWriteMask
{
	CW_RED   = 0x01,
	CW_GREEN = 0x02,
	CW_BLUE  = 0x04,
	CW_ALPHA = 0x08,

	CW_NONE  = 0,
	CW_RGB   = CW_RED | CW_GREEN | CW_BLUE,
	CW_RGBA  = CW_RED | CW_GREEN | CW_BLUE | CW_ALPHA,
	CW_RG    = CW_RED | CW_GREEN,
	CW_BA    = CW_BLUE | CW_ALPHA,

	EColorWriteMask_NumBits = 4,
};
```

#### 混合运算
混合运算符对于颜色混合方程和Alpha混合方程效果是一样的,这里就只用颜色混合方程来做讲解。

| BlendOperation       | 颜色混合方程                                                                             |
| -------------------- | ---------------------------------------------------------------------------------- |
| BO_Add               | $$C=C_{src} \otimes F_{src} + C_{dst} \otimes F_{dst}Csrc​⊗Fsrc​+Cdst​⊗Fdst$$​     |
| BO_Subtract          | $$C = C_{src} \otimes F_{src} - C_{dst} \otimes F_{dst}C=Csrc​⊗Fsrc​−Cdst​⊗Fdst$$​ |
| BO_ReverseSubtract   | $$C = C_{dst} \otimes F_{dst} - C_{src} \otimes F_{src}C=Cdst​⊗Fdst​−Csrc​⊗Fsrc$$​ |
| BO_Min               | $$C = Min(C_{src} , C_{dst} )C=Min(Csrc​,Cdst​)$$                                  |
| BO_Max               | $$C = Max(C_{src} , C_{dst} )C=Max(Csrc​,Cdst​)$$                                  |
| BO_Min和BO_Max忽略了混合因子 |                                                                                    |

#### 混合因子

| BlendFactor                   | 颜色混合因子                                                           | Alpha混合因子                |
| ----------------------------- | ---------------------------------------------------------------- | ------------------------ |
| BF_Zero                       | $$F = (0,0,0)F=(0,0,0)$$                                         | $$F=0F=0$$               |
| BF_One                        | $$F=(1,1,1)F=(1,1,1)$$                                           | $$F=1F=1$$               |
| BF_SourceColor                | $$F=(r_{src},g_{src},b_{src})F=(rsrc​,gsrc​,bsrc​)$$             | –                        |
| BF_InverseSourceColor         | $$F=(1-r_{src},1-g_{src},1-b_{src})F=(1−rsrc​,1−gsrc​,1−bsrc​)$$ | –                        |
| BF_SourceAlpha                | $$F=(a_{src},a_{src},a_{src})F=(asrc​,asrc​,asrc​)$$             | $$F=a_{src}F=asrc$$​     |
| BF_InverseSourceAlpha         | $$F=(1-a_{src},1-a_{src},1-a_{src})F=(1−asrc​,1−asrc​,1−asrc​)$$ | $$F=1-a_{src}F=1−asrc$$​ |
| BF_DestAlpha                  | $$F=(a_{dst},a_{dst},a_{dst})F=(adst​,adst​,adst​)$$             | $$F=a_{dst}F=adst$$​     |
| BF_InverseDestAlpha           | $$F=(1-a_{dst},1-a_{dst},1-a_{dst})F=(1−adst​,1−adst​,1−adst​)$$ | $$F=1-a_{dst}F=1−adst$$​ |
| BF_DestColor                  | $$F=(r_{dst},g_{dst},b_{dst})F=(rdst​,gdst​,bdst​)$$             | –                        |
| BF_InverseDestColor           | $$F=(1-r_{dst},1-g_{dst},1-b_{dst})F=(1−rdst​,1−gdst​,1−bdst​)$$ | –                        |
| BF_ConstantBlendFactor        | F=(r,g,b)F=(r,g,b)                                               | F=aF=a                   |
| BF_InverseConstantBlendFactor | F=(1-r,1-g,1-b)F=(1−r,1−g,1−b)                                   | F=1-aF=1−a               |
| BF_Source1Color               | 未知                                                               | 未知                       |
| BF_InverseSource1Color        | 未知                                                               | 未知                       |
| BF_Source1Alpha               | 未知                                                               | 未知                       |
| BF_InverseSource1Alpha        | 未知                                                               | 未知                       |

最后四个选项没有在DirectX中找到对应的选项,没有继续探究,前面的应该足够一般使用了。
### FRHIDepthStencilState
```c++
TStaticDepthStencilState<
		bEnableDepthWrite,          // 是否启用深度写入
		DepthTest,                  // 深度测试比较函数
		bEnableFrontFaceStencil,    // (正面)启用模板
		FrontFaceStencilTest,       // (正面)模板测试操作
		FrontFaceStencilFailStencilOp, //(正面)模板测试失败时如何更新模板缓冲区
		FrontFaceDepthFailStencilOp,  //(正面)深度测试失败时如何更新模板缓冲区
		FrontFacePassStencilOp,     //(正面)通过模板测试时如何更新模板缓冲区
		bEnableBackFaceStencil,     // (背面)启用模板
		BackFaceStencilTest,        // (背面)模板失败操作
		BackFaceStencilFailStencilOp, //(背面)模板测试失败时如何更新模板缓冲区
		BackFaceDepthFailStencilOp, //(背面)深度测试失败时如何更新模板缓冲区
		BackFacePassStencilOp,      //(背面)通过模板测试时如何更新模板红冲去
		StencilReadMask,            // 模板读取Mask
		StencilWriteMask            // 模板写入Mask
		>
```

```c++
//一般使用这个
TStaticDepthStencilState<true, CF_DepthNearOrEqual>::GetRHI();
//CustomStencil中使用的
TStaticDepthStencilState<true, CF_DepthNearOrEqual, true, CF_Always, SO_Keep, SO_Keep, SO_Replace, false, CF_Always, SO_Keep, SO_Keep, SO_Keep, 255, 255>::GetRHI()
```

#### DepthTest
深度测试比较函数。
```c++
enum ECompareFunction
{
	CF_Less,
	CF_LessEqual,
	CF_Greater,
	CF_GreaterEqual,
	CF_Equal,
	CF_NotEqual,
	CF_Never, // 总是返回false
	CF_Always, // 总是返回true

	ECompareFunction_Num,
	ECompareFunction_NumBits = 3,

	// Utility enumerations
	CF_DepthNearOrEqual		= (((int32)ERHIZBuffer::IsInverted != 0) ? CF_GreaterEqual : CF_LessEqual),
	CF_DepthNear			= (((int32)ERHIZBuffer::IsInverted != 0) ? CF_Greater : CF_Less),
	CF_DepthFartherOrEqual	= (((int32)ERHIZBuffer::IsInverted != 0) ? CF_LessEqual : CF_GreaterEqual),
	CF_DepthFarther			= (((int32)ERHIZBuffer::IsInverted != 0) ? CF_Less : CF_Greater),
};
```

```c++
enum EStencilOp  
{  
    SO_Keep,  
    SO_Zero,  
    SO_Replace,  
    SO_SaturatedIncrement,  
    SO_SaturatedDecrement,  
    SO_Invert,  
    SO_Increment,  
    SO_Decrement,  
  
    EStencilOp_Num,  
    EStencilOp_NumBits = 3,  
};
```

### CustomStencil
#### InitCustomDepthStencilContext()
根据当前平台是否支持使用ComputeShader直接输出结果(bComputeExport)、以及是否写入Stencil缓存,以此来创建不同的资源。最终输出FCustomDepthContext。
```c++
struct FCustomDepthContext  
{  
    FRDGTextureRef InputDepth = nullptr;  
    FRDGTextureSRVRef InputStencilSRV = nullptr;  
    FRDGTextureRef DepthTarget = nullptr;  
    FRDGTextureRef StencilTarget = nullptr;  
    bool bComputeExport = true;  
};
```

#### EmitCustomDepthStencilTargets()
根据bComputeExport,分别使用RDG的ComputeShader与PixelShader输出DepthStencil。 
- CS使用FComputeShaderUtils::AddPass()
- PS使用NaniteExportGBuffer.usf的**EmitCustomDepthStencilPS()**,FPixelShaderUtils::AddFullscreenPass()

以**FEmitCustomDepthStencilPS**(NaniteExportGBuffer.usf)为例,额外输入的Nanite相关变量:
- FSceneUniformParameters Scene
- StructuredBuffer`<`FPackedView`>` InViews
- ByteAddressBuffer VisibleClustersSWHW?
- FIntVector4, PageConstants
- Texture2D`<`UlongType`>`, VisBuffer64
- ByteAddressBuffer MaterialSlotTable

#### FinalizeCustomDepthStencil()
替换输出的Depth&Stencil。

# FViewInfo
FViewInfo& ViewInfo
- WriteView.bSceneHasSkyMaterial |= bSceneHasSkyMaterial;
- WriteView.bHasSingleLayerWaterMaterial |= bHasSingleLayerWaterMaterial;
- WriteView.bHasCustomDepthPrimitives |= bHasCustomDepthPrimitives;
- WriteView.bHasDistortionPrimitives |= bHasDistortionPrimitives;
- WriteView.bUsesCustomDepth |= bUsesCustomDepth;  
- WriteView.bUsesCustomStencil |= bUsesCustomStencil;

- FRelevancePacket::Finalize()

相关性:
- 相关性定义
	- FStaticMeshBatchRelevance
	- FMaterialRelevance
- View相关计算
	- FViewInfo::Init()
	- FRelevancePacket
	- FRelevancePacket::Finalize()

# 相关宏定义
- SCOPE_CYCLE_COUNTER(STAT_BasePassDrawTime);:
	- DECLARE_CYCLE_STAT_EXTERN(TEXT("Base pass drawing"),STAT_BasePassDrawTime,STATGROUP_SceneRendering, RENDERCORE_API);
	- DEFINE_STAT(STAT_BasePassDrawTime);
- DEFINE_GPU_STAT(NaniteBasePass);
	- DECLARE_GPU_STAT_NAMED_EXTERN(NaniteBasePass, TEXT("Nanite BasePass"));
- GET_STATID(STAT_CLP_BasePass)
	- FRDGParallelCommandListSet ParallelCommandListSet(InPass, RHICmdList, GET_STATID(STAT_CLP_BasePass), View, FParallelCommandListBindings(PassParameters));
	- DECLARE_CYCLE_STAT(TEXT("BasePass"), STAT_CLP_BasePass, STATGROUP_ParallelCommandListMarkers);