vault backup: 2024-11-14 12:59:18
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: 未命名
|
||||
date: 2022-09-04 19:50:57
|
||||
excerpt:
|
||||
tags:
|
||||
rating: ⭐
|
||||
---
|
||||
可以使用DrawDynamicMeshPass(),实现在插件中使用MeshDraw绘制Pass。
|
@@ -0,0 +1,258 @@
|
||||
---
|
||||
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);
|
@@ -0,0 +1,91 @@
|
||||
---
|
||||
title: Untitled
|
||||
date: 2024-11-14 12:19:36
|
||||
excerpt:
|
||||
tags:
|
||||
rating: ⭐
|
||||
---
|
||||
# 前言
|
||||
探索思路:
|
||||
- [ ] SceneProxy收集机制的改变。
|
||||
- [ ] GetDynamicMeshElements的调用方式。
|
||||
- [ ] 在SendRenderDynamicData_Concurrent中添加(模仿USkeletalMeshComponent::SendRenderDynamicData_Concurrent()与FDebugSkelMeshSceneProxy)
|
||||
|
||||
# GetDynamicMeshElements
|
||||
看得出主要在FDynamicMeshElementContext::GatherDynamicMeshElementsForPrimitive()中调用Primitive->Proxy->GetDynamicMeshElements()。
|
||||
|
||||
```c++
|
||||
UE::Tasks::FTask FDynamicMeshElementContext::LaunchAsyncTask(FDynamicPrimitiveIndexQueue* PrimitiveIndexQueue, UE::Tasks::ETaskPriority TaskPriority)
|
||||
{
|
||||
return Pipe.Launch(UE_SOURCE_LOCATION, [this, PrimitiveIndexQueue]
|
||||
{
|
||||
FOptionalTaskTagScope Scope(ETaskTag::EParallelRenderingThread);
|
||||
FDynamicPrimitiveIndex PrimitiveIndex;
|
||||
|
||||
while (PrimitiveIndexQueue->Pop(PrimitiveIndex))
|
||||
{
|
||||
GatherDynamicMeshElementsForPrimitive(Primitives[PrimitiveIndex.Index], PrimitiveIndex.ViewMask);
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
while (PrimitiveIndexQueue->PopEditor(PrimitiveIndex))
|
||||
{
|
||||
GatherDynamicMeshElementsForEditorPrimitive(Primitives[PrimitiveIndex.Index], PrimitiveIndex.ViewMask);
|
||||
}
|
||||
#endif
|
||||
}, TaskPriority);
|
||||
}
|
||||
|
||||
void FDynamicMeshElementContext::GatherDynamicMeshElementsForPrimitive(FPrimitiveSceneInfo* Primitive, uint8 ViewMask)
|
||||
{
|
||||
SCOPED_NAMED_EVENT(DynamicPrimitive, FColor::Magenta);
|
||||
|
||||
TArray<int32, TInlineAllocator<4>> MeshBatchCountBefore;
|
||||
MeshBatchCountBefore.SetNumUninitialized(Views.Num());
|
||||
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
|
||||
{
|
||||
MeshBatchCountBefore[ViewIndex] = MeshCollector.GetMeshBatchCount(ViewIndex);
|
||||
}
|
||||
|
||||
MeshCollector.SetPrimitive(Primitive->Proxy, Primitive->DefaultDynamicHitProxyId);
|
||||
|
||||
// If Custom Render Passes aren't in use, there will be only one group, which is the common case.
|
||||
if (ViewFamilyGroups.Num() == 1 || Primitive->Proxy->SinglePassGDME())
|
||||
{
|
||||
Primitive->Proxy->GetDynamicMeshElements(FirstViewFamily.AllViews, FirstViewFamily, ViewMask, MeshCollector);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (FViewFamilyGroup& Group : ViewFamilyGroups)
|
||||
{
|
||||
if (uint8 MaskedViewMask = ViewMask & Group.ViewSubsetMask)
|
||||
{
|
||||
Primitive->Proxy->GetDynamicMeshElements(FirstViewFamily.AllViews, *Group.Family, MaskedViewMask, MeshCollector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
|
||||
{
|
||||
FViewInfo& View = *Views[ViewIndex];
|
||||
|
||||
if (ViewMask & (1 << ViewIndex))
|
||||
{
|
||||
FDynamicPrimitive& DynamicPrimitive = DynamicPrimitives.Emplace_GetRef();
|
||||
DynamicPrimitive.PrimitiveIndex = Primitive->GetIndex();
|
||||
DynamicPrimitive.ViewIndex = ViewIndex;
|
||||
DynamicPrimitive.StartElementIndex = MeshBatchCountBefore[ViewIndex];
|
||||
DynamicPrimitive.EndElementIndex = MeshCollector.GetMeshBatchCount(ViewIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# SendRenderDynamicData_Concurrent
|
||||
|
||||
## FDebugSkelMeshSceneProxy::GetDynamicMeshElements
|
||||
|
||||
|
||||
# 其他?
|
||||
|
||||
MeshBuilderSurface.GetMesh(GetLocalToWorld(), MatProxySurface, SDPG_Foreground, false, false, ViewIndex, Collector);
|
@@ -0,0 +1,154 @@
|
||||
---
|
||||
title: Untitled
|
||||
date: 2024-09-23 19:47:03
|
||||
excerpt:
|
||||
tags:
|
||||
rating: ⭐
|
||||
---
|
||||
# ShadowPassSwitch
|
||||
## Cpp
|
||||
MaterialExpressionShadowReplace.h
|
||||
|
||||
MaterialExpressions.cpp
|
||||
```c++
|
||||
int32 UMaterialExpressionShadowReplace::Compile(class FMaterialCompiler* Compiler, int32 OutputIndex)
|
||||
{
|
||||
if (!Default.GetTracedInput().Expression)
|
||||
{
|
||||
return Compiler->Errorf(TEXT("Missing input Default"));
|
||||
}
|
||||
else if (!Shadow.GetTracedInput().Expression)
|
||||
{
|
||||
return Compiler->Errorf(TEXT("Missing input Shadow"));
|
||||
}
|
||||
else
|
||||
{
|
||||
const int32 Arg1 = Default.Compile(Compiler);
|
||||
const int32 Arg2 = Shadow.Compile(Compiler);
|
||||
return Compiler->ShadowReplace(Arg1, Arg2);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
MaterialCompiler.h => **HLSLMaterialTranslator.cpp**
|
||||
```c++
|
||||
int32 FHLSLMaterialTranslator::ShadowReplace(int32 Default, int32 Shadow)
|
||||
{
|
||||
return GenericSwitch(TEXT("GetShadowReplaceState()"), Shadow, Default);
|
||||
}
|
||||
```
|
||||
|
||||
```c++
|
||||
int32 FHLSLMaterialTranslator::GenericSwitch(const TCHAR* SwitchExpressionText, int32 IfTrue, int32 IfFalse)
|
||||
{
|
||||
if (IfTrue == INDEX_NONE || IfFalse == INDEX_NONE)
|
||||
{
|
||||
return INDEX_NONE;
|
||||
}
|
||||
|
||||
// exactly the same inputs on both sides - no need to generate anything extra
|
||||
if (IfTrue == IfFalse)
|
||||
{
|
||||
return IfTrue;
|
||||
}
|
||||
|
||||
FMaterialUniformExpression* IfTrueExpression = GetParameterUniformExpression(IfTrue);
|
||||
FMaterialUniformExpression* IfFalseExpression = GetParameterUniformExpression(IfFalse);
|
||||
if (IfTrueExpression &&
|
||||
IfFalseExpression &&
|
||||
IfTrueExpression->IsConstant() &&
|
||||
IfFalseExpression->IsConstant())
|
||||
{
|
||||
FMaterialRenderContext DummyContext(nullptr, *Material, nullptr);
|
||||
FLinearColor IfTrueValue;
|
||||
FLinearColor IfFalseValue;
|
||||
IfTrueExpression->GetNumberValue(DummyContext, IfTrueValue);
|
||||
IfFalseExpression->GetNumberValue(DummyContext, IfFalseValue);
|
||||
if (IfTrueValue == IfFalseValue)
|
||||
{
|
||||
// If both inputs are wired to == constant values, avoid adding the runtime switch
|
||||
// This will avoid breaking various offline checks for constant values
|
||||
return IfTrue;
|
||||
}
|
||||
}
|
||||
|
||||
// Both branches of '?:' need to be the same type
|
||||
const EMaterialValueType ResultType = GetArithmeticResultType(IfTrue, IfFalse);
|
||||
const FString IfTrueCode = CoerceParameter(IfTrue, ResultType);
|
||||
const FString IfFalseCode = CoerceParameter(IfFalse, ResultType);
|
||||
|
||||
if (IsLWCType(ResultType))
|
||||
{
|
||||
AddLWCFuncUsage(ELWCFunctionKind::Other);
|
||||
return AddCodeChunk(ResultType, TEXT("LWCSelect(%s, %s, %s)"), SwitchExpressionText, *IfTrueCode, *IfFalseCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
return AddCodeChunk(ResultType, TEXT("(%s ? (%s) : (%s))"), SwitchExpressionText, *IfTrueCode, *IfFalseCode);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
>可以看得出最终会编译成(%s ? (%s) : (%s)),也就是 GetShadowReplaceState() ? True的Shader : False时的Shader。
|
||||
|
||||
## Shader
|
||||
### Common.ush
|
||||
```c++
|
||||
// NOTE: The raytraced implementation of the ShadowPassSwitch node is kept in RayTracingShaderUtils.ush as it needs to access per ray information.
|
||||
#if RAYHITGROUPSHADER == 0
|
||||
// Experimental way to allow adjusting the OpacityMask for shadow map rendering of masked materials.
|
||||
// This is exposed via the ShadowPassSwitch material node. This can also be accessed with a Custom
|
||||
// material node. If this turns out to be very useful we can expose as MaterialFunction
|
||||
// and potentially expose other queries as well (e.g. SkeletalMesh, HitProxy, ).
|
||||
// @return 0:no, 1:yes
|
||||
bool GetShadowReplaceState()
|
||||
{
|
||||
#if SHADOW_DEPTH_SHADER
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
float IsShadowDepthShader()
|
||||
{
|
||||
return GetShadowReplaceState() ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
#endif // RAYHITGROUPSHADER == 0
|
||||
```
|
||||
|
||||
可以看得出主要通过**SHADOW_DEPTH_SHADER**宏进行判断,而渲染阴影的Shader ShadowDepthVertexShader.usf&ShadowDepthPixelShader.usf都定义该宏为1。
|
||||
|
||||
### NaniteRasterizer.usf
|
||||
```c++
|
||||
// This must be defined before including Common.ush (see GetShadowReplaceState)
|
||||
#define SHADOW_DEPTH_SHADER DEPTH_ONLY
|
||||
```
|
||||
在NaniteCullRaster.cpp中DEPTH_ONLY设置为1。
|
||||
|
||||
### RayTracingShaderUtils.ush
|
||||
光追相关
|
||||
```c++
|
||||
#ifndef RAYHITGROUPSHADER
|
||||
#error "This header should only be included in raytracing contexts"
|
||||
#endif
|
||||
|
||||
#ifndef PATH_TRACING // Path Tracing has a similar implemental with a slightly different set of flags
|
||||
|
||||
#include "RayTracingCommon.ush"
|
||||
|
||||
static int CurrentPayloadInputFlags = 0;
|
||||
|
||||
bool GetShadowReplaceState()
|
||||
{
|
||||
return (CurrentPayloadInputFlags & RAY_TRACING_PAYLOAD_INPUT_FLAG_SHADOW_RAY) != 0;
|
||||
}
|
||||
|
||||
float IsShadowDepthShader()
|
||||
{
|
||||
return GetShadowReplaceState() ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
#endif
|
||||
```
|
Reference in New Issue
Block a user