154 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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
```