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