154 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
---
 | 
						||
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
 | 
						||
``` |