738 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			738 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								# Common
							 | 
						|||
| 
								 | 
							
								## Common.ush
							 | 
						|||
| 
								 | 
							
								添加结构体,主要用在材质的CustomNode里。
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								// Used by toon shading.  
							 | 
						|||
| 
								 | 
							
								// Define a global custom data structure which can be filled by Custom node in material BP.  
							 | 
						|||
| 
								 | 
							
								struct FToonShadingPerMaterialCustomData  
							 | 
						|||
| 
								 | 
							
								{  
							 | 
						|||
| 
								 | 
							
								    // Toon specular  
							 | 
						|||
| 
								 | 
							
								    float3 ToonSpecularColor;  
							 | 
						|||
| 
								 | 
							
								    float ToonSpecularLocation;  
							 | 
						|||
| 
								 | 
							
								    float ToonSpecularSmoothness;  
							 | 
						|||
| 
								 | 
							
								    // Toon shadow  
							 | 
						|||
| 
								 | 
							
								    float3 ToonShadowColor;  
							 | 
						|||
| 
								 | 
							
								    float ToonShadowLocation;  
							 | 
						|||
| 
								 | 
							
								    float ToonShadowSmoothness;  
							 | 
						|||
| 
								 | 
							
								    float ToonForceShadow;  
							 | 
						|||
| 
								 | 
							
								    // Toon secondary shadow  
							 | 
						|||
| 
								 | 
							
								    float3 ToonSecondaryShadowColor;  
							 | 
						|||
| 
								 | 
							
								    float ToonSecondaryShadowLocation;  
							 | 
						|||
| 
								 | 
							
								    float ToonSecondaryShadowSmoothness;  
							 | 
						|||
| 
								 | 
							
								    // custom data, usually not used  
							 | 
						|||
| 
								 | 
							
								    float4 CustomData0;  
							 | 
						|||
| 
								 | 
							
								    float4 CustomData1;  
							 | 
						|||
| 
								 | 
							
								    float4 CustomData2;  
							 | 
						|||
| 
								 | 
							
								    float4 CustomData3;  
							 | 
						|||
| 
								 | 
							
								};  
							 | 
						|||
| 
								 | 
							
								  
							 | 
						|||
| 
								 | 
							
								static FToonShadingPerMaterialCustomData ToonShadingPerMaterialCustomData;
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## DeferredShadingCommon.ush
							 | 
						|||
| 
								 | 
							
								1. 实现[[#Encode/Decode函数]]
							 | 
						|||
| 
								 | 
							
								2. HasCustomGBufferData()函数添加对应的ToonShadingModel宏判断
							 | 
						|||
| 
								 | 
							
								3. [[#FGBufferData新增变量]]
							 | 
						|||
| 
								 | 
							
								4. [[#Encode/Decode GBufferData新增逻辑]]
							 | 
						|||
| 
								 | 
							
									1. Metallic/Specualr/Roughness => ToonShadowLocation/ToonForceShadow/ToonShadowSmoothness
							 | 
						|||
| 
								 | 
							
									2. AO => ToonSecondaryShadowLocation
							 | 
						|||
| 
								 | 
							
									3. CustomData => ToonShadowColor/ToonSecondaryShadowSmoothness
							 | 
						|||
| 
								 | 
							
									4. PrecomputedShadowFactors => ToonSecondaryShadowColor
							 | 
						|||
| 
								 | 
							
								5. `#define GBUFFER_REFACTOR 0` 以此关闭自动生成Encode/Decode GBufferData代码,并使用硬编码调用Encode/Decode GBufferData。
							 | 
						|||
| 
								 | 
							
								6. `#if WRITES_VELOCITY_TO_GBUFFER` => `#if GBUFFER_HAS_VELOCITY`,以此**关闭写入VELOCITY到GBuffer中**。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### Encode/Decode函数
							 | 
						|||
| 
								 | 
							
								RGB655 to 8-bit RGB。
							 | 
						|||
| 
								 | 
							
								将R 256 => 64 ,GB 256 => 32。之后使用2个8bit浮点来存储:通道1存储R与G的头两位;通道2存储G的后3位与B。
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								float2 EncodeColorToRGB655(float3 Color)  
							 | 
						|||
| 
								 | 
							
								{  
							 | 
						|||
| 
								 | 
							
								    const uint ChannelR = (1 << 6) - 1;  
							 | 
						|||
| 
								 | 
							
								    const uint ChannelG = (1 << 5) - 1;  
							 | 
						|||
| 
								 | 
							
								    const uint ChannelB = (1 << 5) - 1;  
							 | 
						|||
| 
								 | 
							
								  
							 | 
						|||
| 
								 | 
							
								    uint3 RoundedColor = uint3(float3(  
							 | 
						|||
| 
								 | 
							
								       round(Color.r * ChannelR),  
							 | 
						|||
| 
								 | 
							
								       round(Color.g * ChannelG),  
							 | 
						|||
| 
								 | 
							
								       round(Color.b * ChannelB)  
							 | 
						|||
| 
								 | 
							
								    ));  
							 | 
						|||
| 
								 | 
							
								    return float2(  
							 | 
						|||
| 
								 | 
							
								       (RoundedColor.r << 2 | RoundedColor.g >> 3) / 255.0,  
							 | 
						|||
| 
								 | 
							
								       (RoundedColor.g << 5 | RoundedColor.b     ) / 255.0  
							 | 
						|||
| 
								 | 
							
								    );  
							 | 
						|||
| 
								 | 
							
								}  
							 | 
						|||
| 
								 | 
							
								  
							 | 
						|||
| 
								 | 
							
								float3 DecodeRGB655ToColor(float2 RGB655)  
							 | 
						|||
| 
								 | 
							
								{  
							 | 
						|||
| 
								 | 
							
								    const uint ChannelR = (1 << 6) - 1;  
							 | 
						|||
| 
								 | 
							
								    const uint ChannelG = (1 << 5) - 1;  
							 | 
						|||
| 
								 | 
							
								    const uint ChannelB = (1 << 5) - 1;  
							 | 
						|||
| 
								 | 
							
								  
							 | 
						|||
| 
								 | 
							
								    uint2 Inputs = uint2(round(RGB655 * 255.0));  
							 | 
						|||
| 
								 | 
							
								    uint BitBuffer = (Inputs.x << 8) | Inputs.y;  
							 | 
						|||
| 
								 | 
							
								    uint R = (BitBuffer & 0xFC00) >> 10;  
							 | 
						|||
| 
								 | 
							
								    uint G = (BitBuffer & 0x03E0) >> 5;  
							 | 
						|||
| 
								 | 
							
								    uint B = (BitBuffer & 0x001F);  
							 | 
						|||
| 
								 | 
							
								  
							 | 
						|||
| 
								 | 
							
								    return float3(R, G, B) * float3(1.0 / ChannelR, 1.0 / ChannelG, 1.0 / ChannelB);  
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### FGBufferData新增变量
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								struct FGBufferData  
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								...
							 | 
						|||
| 
								 | 
							
									// Toon specular  
							 | 
						|||
| 
								 | 
							
									// 0..1, specular color  
							 | 
						|||
| 
								 | 
							
									half3 ToonSpecularColor;  
							 | 
						|||
| 
								 | 
							
									// 0..1, specular edge position  
							 | 
						|||
| 
								 | 
							
									half ToonSpecularLocation;  
							 | 
						|||
| 
								 | 
							
									// 0..1, specular edge smoothness  
							 | 
						|||
| 
								 | 
							
									half ToonSpecularSmoothness;  
							 | 
						|||
| 
								 | 
							
									  
							 | 
						|||
| 
								 | 
							
									// Toon shadow  
							 | 
						|||
| 
								 | 
							
									// 0..1, shadow color  
							 | 
						|||
| 
								 | 
							
									half3 ToonShadowColor;  
							 | 
						|||
| 
								 | 
							
									// 0..1, shadow egde location  
							 | 
						|||
| 
								 | 
							
									half ToonShadowLocation;  
							 | 
						|||
| 
								 | 
							
									// 0..1, shadow edge smoothness  
							 | 
						|||
| 
								 | 
							
									half ToonShadowSmoothness;  
							 | 
						|||
| 
								 | 
							
									// 0..1, force shadow  
							 | 
						|||
| 
								 | 
							
									half ToonForceShadow;  
							 | 
						|||
| 
								 | 
							
									  
							 | 
						|||
| 
								 | 
							
									// Toon secondary shadow  
							 | 
						|||
| 
								 | 
							
									// 0..1, secondary shadow color  
							 | 
						|||
| 
								 | 
							
									float3 ToonSecondaryShadowColor;  
							 | 
						|||
| 
								 | 
							
									// 0..1, secondary shadow edge location  
							 | 
						|||
| 
								 | 
							
									float ToonSecondaryShadowLocation;  
							 | 
						|||
| 
								 | 
							
									// 0..1, secondary shadow edge smoothness  
							 | 
						|||
| 
								 | 
							
									float ToonSecondaryShadowSmoothness;  
							 | 
						|||
| 
								 | 
							
									  
							 | 
						|||
| 
								 | 
							
									// Toon render  
							 | 
						|||
| 
								 | 
							
									half3 ToonCalcShadowColor;
							 | 
						|||
| 
								 | 
							
								};
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### Encode/Decode GBufferData新增逻辑
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								  
							 | 
						|||
| 
								 | 
							
								void EncodeGBuffer(  
							 | 
						|||
| 
								 | 
							
								    FGBufferData GBuffer,  
							 | 
						|||
| 
								 | 
							
								    out float4 OutGBufferA,  
							 | 
						|||
| 
								 | 
							
								    out float4 OutGBufferB,  
							 | 
						|||
| 
								 | 
							
								    out float4 OutGBufferC,  
							 | 
						|||
| 
								 | 
							
								    out float4 OutGBufferD,  
							 | 
						|||
| 
								 | 
							
								    out float4 OutGBufferE,  
							 | 
						|||
| 
								 | 
							
								    out float4 OutGBufferVelocity,  
							 | 
						|||
| 
								 | 
							
								    float QuantizationBias = 0    // -0.5 to 0.5 random float. Used to bias quantization.  
							 | 
						|||
| 
								 | 
							
								    )  
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									...
							 | 
						|||
| 
								 | 
							
										switch(GBuffer.ShadingModelID)
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											case SHADINGMODELID_TOON_BASE:
							 | 
						|||
| 
								 | 
							
												OutGBufferB.r = ToonShadingPerMaterialCustomData.ToonShadowLocation;
							 | 
						|||
| 
								 | 
							
												OutGBufferB.g = ToonShadingPerMaterialCustomData.ToonForceShadow;
							 | 
						|||
| 
								 | 
							
												OutGBufferB.b = ToonShadingPerMaterialCustomData.ToonShadowSmoothness;
							 | 
						|||
| 
								 | 
							
												OutGBufferC.a = ToonShadingPerMaterialCustomData.ToonSecondaryShadowLocation;
							 | 
						|||
| 
								 | 
							
												OutGBufferD.a = ToonShadingPerMaterialCustomData.ToonSecondaryShadowSmoothness;
							 | 
						|||
| 
								 | 
							
												OutGBufferD.rgb = ToonShadingPerMaterialCustomData.ToonShadowColor.rgb;
							 | 
						|||
| 
								 | 
							
												OutGBufferE.gba = ToonShadingPerMaterialCustomData.ToonSecondaryShadowColor.rgb;
							 | 
						|||
| 
								 | 
							
												break;
							 | 
						|||
| 
								 | 
							
											case SHADINGMODELID_TOON_PBR:
							 | 
						|||
| 
								 | 
							
												OutGBufferB.g = ToonShadingPerMaterialCustomData.ToonShadowLocation;
							 | 
						|||
| 
								 | 
							
												OutGBufferD.a = ToonShadingPerMaterialCustomData.ToonShadowSmoothness;
							 | 
						|||
| 
								 | 
							
												OutGBufferD.rgb = ToonShadingPerMaterialCustomData.ToonShadowColor.rgb;
							 | 
						|||
| 
								 | 
							
												OutGBufferE.gba = ToonShadingPerMaterialCustomData.ToonSpecularColor.rgb;
							 | 
						|||
| 
								 | 
							
												break;
							 | 
						|||
| 
								 | 
							
											case SHADINGMODELID_TOON_SKIN:
							 | 
						|||
| 
								 | 
							
												OutGBufferB.r = ToonShadingPerMaterialCustomData.ToonShadowLocation;
							 | 
						|||
| 
								 | 
							
												OutGBufferD.a = ToonShadingPerMaterialCustomData.ToonShadowSmoothness;
							 | 
						|||
| 
								 | 
							
												OutGBufferD.rgb = ToonShadingPerMaterialCustomData.ToonShadowColor.rgb;
							 | 
						|||
| 
								 | 
							
												break;
							 | 
						|||
| 
								 | 
							
											default:
							 | 
						|||
| 
								 | 
							
												break;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									...
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								FGBufferData DecodeGBufferData(  
							 | 
						|||
| 
								 | 
							
								    float4 InGBufferA,  
							 | 
						|||
| 
								 | 
							
								    float4 InGBufferB,  
							 | 
						|||
| 
								 | 
							
								    float4 InGBufferC,  
							 | 
						|||
| 
								 | 
							
								    float4 InGBufferD,  
							 | 
						|||
| 
								 | 
							
								    float4 InGBufferE,  
							 | 
						|||
| 
								 | 
							
								    float4 InGBufferF,  
							 | 
						|||
| 
								 | 
							
								    float4 InGBufferVelocity,  
							 | 
						|||
| 
								 | 
							
								    float CustomNativeDepth,  
							 | 
						|||
| 
								 | 
							
								    uint CustomStencil,  
							 | 
						|||
| 
								 | 
							
								    float SceneDepth,  
							 | 
						|||
| 
								 | 
							
								    bool bGetNormalizedNormal,  
							 | 
						|||
| 
								 | 
							
								    bool bChecker)  
							 | 
						|||
| 
								 | 
							
								{  
							 | 
						|||
| 
								 | 
							
								    FGBufferData GBuffer = (FGBufferData)0;
							 | 
						|||
| 
								 | 
							
									...
							 | 
						|||
| 
								 | 
							
									 switch(GBuffer.ShadingModelID)
							 | 
						|||
| 
								 | 
							
									    {
							 | 
						|||
| 
								 | 
							
									        case SHADINGMODELID_TOON_BASE:
							 | 
						|||
| 
								 | 
							
									            GBuffer.ToonShadowColor               = InGBufferD.rgb;
							 | 
						|||
| 
								 | 
							
									            GBuffer.ToonShadowLocation            = InGBufferB.r;
							 | 
						|||
| 
								 | 
							
									            GBuffer.ToonShadowSmoothness          = InGBufferB.b;
							 | 
						|||
| 
								 | 
							
									            GBuffer.ToonForceShadow               = InGBufferB.g;
							 | 
						|||
| 
								 | 
							
												GBuffer.ToonSecondaryShadowColor      = InGBufferE.gba;
							 | 
						|||
| 
								 | 
							
												GBuffer.ToonSecondaryShadowLocation   = InGBufferC.a;
							 | 
						|||
| 
								 | 
							
												GBuffer.ToonSecondaryShadowSmoothness = InGBufferD.a;
							 | 
						|||
| 
								 | 
							
									            GBuffer.Metallic = 0.0;
							 | 
						|||
| 
								 | 
							
									            GBuffer.Specular = 1.0;
							 | 
						|||
| 
								 | 
							
									            GBuffer.Roughness = 1.0;
							 | 
						|||
| 
								 | 
							
									            GBuffer.GBufferAO = 0.0;
							 | 
						|||
| 
								 | 
							
									            GBuffer.IndirectIrradiance = 1.0;
							 | 
						|||
| 
								 | 
							
									            GBuffer.PrecomputedShadowFactors = !(GBuffer.SelectiveOutputMask & SKIP_PRECSHADOW_MASK) ? float4(InGBufferE.r, 1.0, 1.0, 1.0) : ((GBuffer.SelectiveOutputMask & ZERO_PRECSHADOW_MASK) ? 0 :  1);
							 | 
						|||
| 
								 | 
							
									            GBuffer.StoredMetallic = 0.0;
							 | 
						|||
| 
								 | 
							
									            GBuffer.StoredSpecular = 1.0;
							 | 
						|||
| 
								 | 
							
									            break;
							 | 
						|||
| 
								 | 
							
									        case SHADINGMODELID_TOON_PBR:
							 | 
						|||
| 
								 | 
							
									            GBuffer.ToonSpecularColor = InGBufferE.gba;
							 | 
						|||
| 
								 | 
							
									            GBuffer.ToonShadowColor = InGBufferD.rgb;
							 | 
						|||
| 
								 | 
							
									            GBuffer.ToonShadowLocation = InGBufferB.g;
							 | 
						|||
| 
								 | 
							
									            GBuffer.ToonShadowSmoothness = InGBufferD.a;
							 | 
						|||
| 
								 | 
							
												GBuffer.ToonSecondaryShadowColor = GBuffer.ToonShadowColor;
							 | 
						|||
| 
								 | 
							
												GBuffer.ToonForceShadow = 1.0;
							 | 
						|||
| 
								 | 
							
												GBuffer.ToonSpecularLocation = 1.0;
							 | 
						|||
| 
								 | 
							
									            GBuffer.Specular = 1.0;
							 | 
						|||
| 
								 | 
							
									            GBuffer.PrecomputedShadowFactors = !(GBuffer.SelectiveOutputMask & SKIP_PRECSHADOW_MASK) ? float4(InGBufferE.r, 1.0, 1.0, 1.0) : ((GBuffer.SelectiveOutputMask & ZERO_PRECSHADOW_MASK) ? 0 :  1);
							 | 
						|||
| 
								 | 
							
									            break;
							 | 
						|||
| 
								 | 
							
									        case SHADINGMODELID_TOON_SKIN:
							 | 
						|||
| 
								 | 
							
									            GBuffer.ToonShadowColor = InGBufferD.rgb;
							 | 
						|||
| 
								 | 
							
									            GBuffer.ToonShadowLocation = InGBufferB.r;
							 | 
						|||
| 
								 | 
							
									            GBuffer.ToonShadowSmoothness = InGBufferD.a;
							 | 
						|||
| 
								 | 
							
												GBuffer.ToonSecondaryShadowColor = GBuffer.ToonShadowColor;
							 | 
						|||
| 
								 | 
							
												GBuffer.ToonForceShadow = 1.0;
							 | 
						|||
| 
								 | 
							
									            GBuffer.Metallic = 0.0;
							 | 
						|||
| 
								 | 
							
												GBuffer.StoredMetallic = 0.0;
							 | 
						|||
| 
								 | 
							
									            GBuffer.PrecomputedShadowFactors = !(GBuffer.SelectiveOutputMask & SKIP_PRECSHADOW_MASK) ? float4(InGBufferE.r, 1.0, 1.0, 1.0) : ((GBuffer.SelectiveOutputMask & ZERO_PRECSHADOW_MASK) ? 0 :  1);
							 | 
						|||
| 
								 | 
							
									            break;
							 | 
						|||
| 
								 | 
							
									        default:
							 | 
						|||
| 
								 | 
							
									            break;
							 | 
						|||
| 
								 | 
							
									    }
							 | 
						|||
| 
								 | 
							
									...
							 | 
						|||
| 
								 | 
							
								};
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								# BasePass
							 | 
						|||
| 
								 | 
							
								BasePassPixelShader.usf
							 | 
						|||
| 
								 | 
							
								1. `#if 1` => `#if GBUFFER_REFACTOR && 0`,以此关闭自动生成Encode/Decode GBufferData代码,并使用硬编码调用Encode/Decode GBufferData。
							 | 
						|||
| 
								 | 
							
								2. 在FPixelShaderInOut_MainPS()中添加写入FGBufferData逻辑。代码如下:
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								...
							 | 
						|||
| 
								 | 
							
								switch(GBuffer.ShadingModelID)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									case SHADINGMODELID_TOON_BASE:
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonShadowColor = ToonShadingPerMaterialCustomData.ToonShadowColor.rgb;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonShadowLocation = ToonShadingPerMaterialCustomData.ToonShadowLocation;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonShadowSmoothness = ToonShadingPerMaterialCustomData.ToonShadowSmoothness;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonForceShadow = ToonShadingPerMaterialCustomData.ToonForceShadow;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonSecondaryShadowColor = ToonShadingPerMaterialCustomData.ToonSecondaryShadowColor.rgb;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonSecondaryShadowLocation = ToonShadingPerMaterialCustomData.ToonSecondaryShadowLocation;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonSecondaryShadowSmoothness = ToonShadingPerMaterialCustomData.ToonSecondaryShadowSmoothness;
							 | 
						|||
| 
								 | 
							
										GBuffer.Specular = 1.0;
							 | 
						|||
| 
								 | 
							
										GBuffer.GBufferAO = 0.0;
							 | 
						|||
| 
								 | 
							
										GBuffer.PrecomputedShadowFactors.gba = 1;
							 | 
						|||
| 
								 | 
							
										break;
							 | 
						|||
| 
								 | 
							
									case SHADINGMODELID_TOON_PBR:
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonSpecularColor = ToonShadingPerMaterialCustomData.ToonSpecularColor.rgb;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonShadowColor = ToonShadingPerMaterialCustomData.ToonShadowColor.rgb;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonShadowLocation = ToonShadingPerMaterialCustomData.ToonShadowLocation;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonShadowSmoothness = ToonShadingPerMaterialCustomData.ToonShadowSmoothness;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonSecondaryShadowColor = ToonShadingPerMaterialCustomData.ToonShadowColor.rgb;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonForceShadow = 1.0;
							 | 
						|||
| 
								 | 
							
										GBuffer.Specular = 1.0;
							 | 
						|||
| 
								 | 
							
										GBuffer.PrecomputedShadowFactors.gba = 1;
							 | 
						|||
| 
								 | 
							
										break;
							 | 
						|||
| 
								 | 
							
									case SHADINGMODELID_TOON_SKIN:
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonShadowColor = ToonShadingPerMaterialCustomData.ToonShadowColor.rgb;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonShadowLocation = ToonShadingPerMaterialCustomData.ToonShadowLocation;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonShadowSmoothness = ToonShadingPerMaterialCustomData.ToonShadowSmoothness;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonSecondaryShadowColor = ToonShadingPerMaterialCustomData.ToonShadowColor.rgb;
							 | 
						|||
| 
								 | 
							
										GBuffer.ToonForceShadow = 1.0;
							 | 
						|||
| 
								 | 
							
										GBuffer.PrecomputedShadowFactors.g = 1;
							 | 
						|||
| 
								 | 
							
										break;
							 | 
						|||
| 
								 | 
							
									default:
							 | 
						|||
| 
								 | 
							
										break;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								...
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								# Lighting
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## ShadingModels
							 | 
						|||
| 
								 | 
							
								### ShadingCommon.ush
							 | 
						|||
| 
								 | 
							
								**添加ShadingModelID宏**:
							 | 
						|||
| 
								 | 
							
								- SHADINGMODELID_TOON_BASE           13
							 | 
						|||
| 
								 | 
							
								- SHADINGMODELID_TOON_PBR             14  
							 | 
						|||
| 
								 | 
							
								- SHADINGMODELID_TOON_SKIN            15  
							 | 
						|||
| 
								 | 
							
								- SHADINGMODELID_NUM                       16
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								判断是否是IsToonShadingModel:
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								bool IsToonShadingModel(uint ShadingModel)  
							 | 
						|||
| 
								 | 
							
								{  
							 | 
						|||
| 
								 | 
							
								    uint4 ToonShadingModels = uint4(SHADINGMODELID_TOON_BASE, SHADINGMODELID_TOON_PBR, SHADINGMODELID_TOON_SKIN, 0xFF);  
							 | 
						|||
| 
								 | 
							
								    return any(ShadingModel.xxxx == ToonShadingModels);  
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								## DeferredLightingCommon.ush
							 | 
						|||
| 
								 | 
							
								修改了AccumulateDynamicLighting()的逻辑。
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								FLightAccumulator AccumulateDynamicLighting(
							 | 
						|||
| 
								 | 
							
									float3 TranslatedWorldPosition, half3 CameraVector, FGBufferData GBuffer, half AmbientOcclusion, uint ShadingModelID,
							 | 
						|||
| 
								 | 
							
									FDeferredLightData LightData, half4 LightAttenuation, float Dither, uint2 SVPos, 
							 | 
						|||
| 
								 | 
							
									inout float SurfaceShadow)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									FLightAccumulator LightAccumulator = (FLightAccumulator)0;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									half3 V = -CameraVector;
							 | 
						|||
| 
								 | 
							
									half3 N = GBuffer.WorldNormal;
							 | 
						|||
| 
								 | 
							
									BRANCH if( GBuffer.ShadingModelID == SHADINGMODELID_CLEAR_COAT && CLEAR_COAT_BOTTOM_NORMAL)
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										const float2 oct1 = ((float2(GBuffer.CustomData.a, GBuffer.CustomData.z) * 4) - (512.0/255.0)) + UnitVectorToOctahedron(GBuffer.WorldNormal);
							 | 
						|||
| 
								 | 
							
										N = OctahedronToUnitVector(oct1);			
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									
							 | 
						|||
| 
								 | 
							
									float3 L = LightData.Direction;	// Already normalized
							 | 
						|||
| 
								 | 
							
									float3 ToLight = L;
							 | 
						|||
| 
								 | 
							
									float3 MaskedLightColor = LightData.Color;
							 | 
						|||
| 
								 | 
							
									float LightMask = 1;
							 | 
						|||
| 
								 | 
							
									if (LightData.bRadialLight)
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										LightMask = GetLocalLightAttenuation( TranslatedWorldPosition, LightData, ToLight, L );
							 | 
						|||
| 
								 | 
							
										MaskedLightColor *= LightMask;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									LightAccumulator.EstimatedCost += 0.3f;		// running the PixelShader at all has a cost
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									BRANCH
							 | 
						|||
| 
								 | 
							
									if( LightMask > 0 )
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										FShadowTerms Shadow;
							 | 
						|||
| 
								 | 
							
										Shadow.SurfaceShadow = AmbientOcclusion;
							 | 
						|||
| 
								 | 
							
										Shadow.TransmissionShadow = 1;
							 | 
						|||
| 
								 | 
							
										Shadow.TransmissionThickness = 1;
							 | 
						|||
| 
								 | 
							
										Shadow.HairTransmittance.OpaqueVisibility = 1;
							 | 
						|||
| 
								 | 
							
										const float ContactShadowOpacity = GBuffer.CustomData.a;
							 | 
						|||
| 
								 | 
							
										GetShadowTerms(GBuffer.Depth, GBuffer.PrecomputedShadowFactors, GBuffer.ShadingModelID, ContactShadowOpacity,
							 | 
						|||
| 
								 | 
							
											LightData, TranslatedWorldPosition, L, LightAttenuation, Dither, Shadow);
							 | 
						|||
| 
								 | 
							
										SurfaceShadow = Shadow.SurfaceShadow;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										LightAccumulator.EstimatedCost += 0.3f;		// add the cost of getting the shadow terms
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#if SHADING_PATH_MOBILE
							 | 
						|||
| 
								 | 
							
										const bool bNeedsSeparateSubsurfaceLightAccumulation = UseSubsurfaceProfile(GBuffer.ShadingModelID);
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										FDirectLighting Lighting = (FDirectLighting)0;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										half NoL = max(0, dot(GBuffer.WorldNormal, L));
							 | 
						|||
| 
								 | 
							
									#if TRANSLUCENCY_NON_DIRECTIONAL
							 | 
						|||
| 
								 | 
							
										NoL = 1.0f;
							 | 
						|||
| 
								 | 
							
									#endif
							 | 
						|||
| 
								 | 
							
										Lighting = EvaluateBxDF(GBuffer, N, V, L, NoL, Shadow);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										Lighting.Specular *= LightData.SpecularScale;
							 | 
						|||
| 
								 | 
							
												
							 | 
						|||
| 
								 | 
							
										LightAccumulator_AddSplit( LightAccumulator, Lighting.Diffuse, Lighting.Specular, Lighting.Diffuse, MaskedLightColor * Shadow.SurfaceShadow, bNeedsSeparateSubsurfaceLightAccumulation );
							 | 
						|||
| 
								 | 
							
										LightAccumulator_AddSplit( LightAccumulator, Lighting.Transmission, 0.0f, Lighting.Transmission, MaskedLightColor * Shadow.TransmissionShadow, bNeedsSeparateSubsurfaceLightAccumulation );
							 | 
						|||
| 
								 | 
							
								#else // SHADING_PATH_MOBILE
							 | 
						|||
| 
								 | 
							
										//修改了这里
							 | 
						|||
| 
								 | 
							
										bool UseToonShadow = IsToonShadingModel(GBuffer.ShadingModelID);
							 | 
						|||
| 
								 | 
							
										BRANCH
							 | 
						|||
| 
								 | 
							
										if( Shadow.SurfaceShadow + Shadow.TransmissionShadow > 0 || UseToonShadow)//修改结束
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											const bool bNeedsSeparateSubsurfaceLightAccumulation = UseSubsurfaceProfile(GBuffer.ShadingModelID);
							 | 
						|||
| 
								 | 
							
											//修改了这里
							 | 
						|||
| 
								 | 
							
											BRANCH
							 | 
						|||
| 
								 | 
							
											if(UseToonShadow)
							 | 
						|||
| 
								 | 
							
											{
							 | 
						|||
| 
								 | 
							
												float NoL = dot(N, L);
							 | 
						|||
| 
								 | 
							
												float ToonNoL = min(NoL, GBuffer.ToonForceShadow);
							 | 
						|||
| 
								 | 
							
												//合并SurfaceShadow以及Transmision Shadow
							 | 
						|||
| 
								 | 
							
												Shadow.SurfaceShadow = min(Shadow.SurfaceShadow, Shadow.TransmissionShadow);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
												//根据ToonShadowSmoothness、ToonShadowLocation、NoL计算阴影亮度,最后计算主阴影颜色。
							 | 
						|||
| 
								 | 
							
												float RangeHalf = GBuffer.ToonShadowSmoothness * 0.5;
							 | 
						|||
| 
								 | 
							
												float RangeMin  = max(0.0, GBuffer.ToonShadowLocation - RangeHalf);
							 | 
						|||
| 
								 | 
							
												float RangeMax  = min(1.0, GBuffer.ToonShadowLocation + RangeHalf);
							 | 
						|||
| 
								 | 
							
												float ShadowIntensity = Shadow.SurfaceShadow * smoothstep(RangeMin, RangeMax, ToonNoL);
							 | 
						|||
| 
								 | 
							
												GBuffer.ToonCalcShadowColor = lerp(GBuffer.ToonShadowColor * LightData.SpecularScale, (1.0).xxx, ShadowIntensity);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
												//计算次级阴影颜色,并最终合成。
							 | 
						|||
| 
								 | 
							
												RangeHalf = GBuffer.ToonSecondaryShadowSmoothness * 0.5;
							 | 
						|||
| 
								 | 
							
												RangeMin = max(0.0, GBuffer.ToonSecondaryShadowLocation - RangeHalf);
							 | 
						|||
| 
								 | 
							
												RangeMax  = min(1.0, GBuffer.ToonSecondaryShadowLocation + RangeHalf);
							 | 
						|||
| 
								 | 
							
												ShadowIntensity = Shadow.SurfaceShadow * smoothstep(RangeMin, RangeMax, ToonNoL);
							 | 
						|||
| 
								 | 
							
												GBuffer.ToonCalcShadowColor = lerp(GBuffer.ToonSecondaryShadowColor * LightData.SpecularScale, GBuffer.ToonCalcShadowColor, ShadowIntensity);
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											//修改结束
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										#if NON_DIRECTIONAL_DIRECT_LIGHTING
							 | 
						|||
| 
								 | 
							
											float Lighting;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											if( LightData.bRectLight )
							 | 
						|||
| 
								 | 
							
											{
							 | 
						|||
| 
								 | 
							
												FRect Rect = GetRect( ToLight, LightData );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
												Lighting = IntegrateLight( Rect );
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											else
							 | 
						|||
| 
								 | 
							
											{
							 | 
						|||
| 
								 | 
							
												FCapsuleLight Capsule = GetCapsule( ToLight, LightData );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
												Lighting = IntegrateLight( Capsule, LightData.bInverseSquared );
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											float3 LightingDiffuse = Diffuse_Lambert( GBuffer.DiffuseColor ) * Lighting;
							 | 
						|||
| 
								 | 
							
											LightAccumulator_AddSplit(LightAccumulator, LightingDiffuse, 0.0f, 0, MaskedLightColor * Shadow.SurfaceShadow, bNeedsSeparateSubsurfaceLightAccumulation);
							 | 
						|||
| 
								 | 
							
										#else
							 | 
						|||
| 
								 | 
							
											FDirectLighting Lighting;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											if (LightData.bRectLight)
							 | 
						|||
| 
								 | 
							
											{
							 | 
						|||
| 
								 | 
							
												FRect Rect = GetRect( ToLight, LightData );
							 | 
						|||
| 
								 | 
							
												const FRectTexture SourceTexture = ConvertToRectTexture(LightData);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
												#if REFERENCE_QUALITY
							 | 
						|||
| 
								 | 
							
													Lighting = IntegrateBxDF( GBuffer, N, V, Rect, Shadow, SourceTexture, SVPos );
							 | 
						|||
| 
								 | 
							
												#else
							 | 
						|||
| 
								 | 
							
													Lighting = IntegrateBxDF( GBuffer, N, V, Rect, Shadow, SourceTexture);
							 | 
						|||
| 
								 | 
							
												#endif
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											else
							 | 
						|||
| 
								 | 
							
											{
							 | 
						|||
| 
								 | 
							
												FCapsuleLight Capsule = GetCapsule( ToLight, LightData );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
												#if REFERENCE_QUALITY
							 | 
						|||
| 
								 | 
							
													Lighting = IntegrateBxDF( GBuffer, N, V, Capsule, Shadow, SVPos );
							 | 
						|||
| 
								 | 
							
												#else
							 | 
						|||
| 
								 | 
							
													Lighting = IntegrateBxDF( GBuffer, N, V, Capsule, Shadow, LightData.bInverseSquared );
							 | 
						|||
| 
								 | 
							
												#endif
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											//修改了这里
							 | 
						|||
| 
								 | 
							
											float SurfaceShadow = UseToonShadow ? 1.0 : Shadow.SurfaceShadow;
							 | 
						|||
| 
								 | 
							
											float TransmissionShadow = UseToonShadow ? 1.0 : Shadow.TransmissionShadow;
							 | 
						|||
| 
								 | 
							
											Lighting.Specular *= UseToonShadow ? GBuffer.ToonSpecularColor : LightData.SpecularScale;
							 | 
						|||
| 
								 | 
							
												
							 | 
						|||
| 
								 | 
							
											LightAccumulator_AddSplit( LightAccumulator, Lighting.Diffuse, Lighting.Specular, Lighting.Diffuse, MaskedLightColor * SurfaceShadow, bNeedsSeparateSubsurfaceLightAccumulation );
							 | 
						|||
| 
								 | 
							
											LightAccumulator_AddSplit( LightAccumulator, Lighting.Transmission, 0.0f, Lighting.Transmission, MaskedLightColor * TransmissionShadow, bNeedsSeparateSubsurfaceLightAccumulation );
							 | 
						|||
| 
								 | 
							
											//修改结束
							 | 
						|||
| 
								 | 
							
											LightAccumulator.EstimatedCost += 0.4f;		// add the cost of the lighting computations (should sum up to 1 form one light)
							 | 
						|||
| 
								 | 
							
										#endif
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								#endif // SHADING_PATH_MOBILE
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									return LightAccumulator;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## ShadingModels.ush
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								float3 ToonSpecular(float ToonSpecularLocation, float ToonSpecularSmoothness, float3 ToonSpecularColor, float NoL)  
							 | 
						|||
| 
								 | 
							
								{  
							 | 
						|||
| 
								 | 
							
								    float ToonSpecularRangeHalf = ToonSpecularSmoothness * 0.5;  
							 | 
						|||
| 
								 | 
							
								    float ToonSpecularRangeMin  = ToonSpecularLocation - ToonSpecularRangeHalf;  
							 | 
						|||
| 
								 | 
							
								    float ToonSpecularRangeMax  = ToonSpecularLocation + ToonSpecularRangeHalf;  
							 | 
						|||
| 
								 | 
							
								    return smoothstep(ToonSpecularRangeMin, ToonSpecularRangeMax, NoL) * ToonSpecularColor;  
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								创建了ToonCustomBxDF(**SHADINGMODELID_TOON_BASE**)与ToonLitBxDF(**SHADINGMODELID_TOON_PBR**、**SHADINGMODELID_TOON_SKIN**)2个ShadingModel函数。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### ToonCustomBxDF的修改
							 | 
						|||
| 
								 | 
							
								Diffuse里面乘以之前在DeferredShadingCommon.ush中计算好的ShadowColor(已经计算了NoL)
							 | 
						|||
| 
								 | 
							
								`Lighting.Diffuse *= AreaLight.FalloffColor * (Falloff * NoL);`
							 | 
						|||
| 
								 | 
							
								=>
							 | 
						|||
| 
								 | 
							
								`Lighting.Diffuse *= AreaLight.FalloffColor * Falloff * GBuffer.ToonCalcShadowColor;`
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								Speuclar直接归零,具体是在BasePass阶段进行计算了。
							 | 
						|||
| 
								 | 
							
								`Lighting.Specular = 0;`
							 | 
						|||
| 
								 | 
							
								### ToonLitBxDF的修改
							 | 
						|||
| 
								 | 
							
								Diffuse里面乘以之前在DeferredShadingCommon.ush中计算好的ShadowColor(已经计算了NoL)
							 | 
						|||
| 
								 | 
							
								`Lighting.Diffuse *= AreaLight.FalloffColor * (Falloff * NoL);`
							 | 
						|||
| 
								 | 
							
								=>
							 | 
						|||
| 
								 | 
							
								`Lighting.Diffuse *= AreaLight.FalloffColor * Falloff * GBuffer.ToonCalcShadowColor;`
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								Speuclar最后乘以了**Shadow.SurfaceShadow**
							 | 
						|||
| 
								 | 
							
								`Lighting.Specular *= Shadow.SurfaceShadow;`
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								FDirectLighting ToonLitBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, half NoL, FAreaLight AreaLight, FShadowTerms Shadow )
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									BxDFContext Context;
							 | 
						|||
| 
								 | 
							
									FDirectLighting Lighting;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#if SUPPORTS_ANISOTROPIC_MATERIALS
							 | 
						|||
| 
								 | 
							
									bool bHasAnisotropy = HasAnisotropy(GBuffer.SelectiveOutputMask);
							 | 
						|||
| 
								 | 
							
								#else
							 | 
						|||
| 
								 | 
							
									bool bHasAnisotropy = false;
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									float NoV, VoH, NoH;
							 | 
						|||
| 
								 | 
							
									BRANCH
							 | 
						|||
| 
								 | 
							
									if (bHasAnisotropy)
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										half3 X = GBuffer.WorldTangent;
							 | 
						|||
| 
								 | 
							
										half3 Y = normalize(cross(N, X));
							 | 
						|||
| 
								 | 
							
										Init(Context, N, X, Y, V, L);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										NoV = Context.NoV;
							 | 
						|||
| 
								 | 
							
										VoH = Context.VoH;
							 | 
						|||
| 
								 | 
							
										NoH = Context.NoH;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									else
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
								#if SHADING_PATH_MOBILE
							 | 
						|||
| 
								 | 
							
										InitMobile(Context, N, V, L, NoL);
							 | 
						|||
| 
								 | 
							
								#else
							 | 
						|||
| 
								 | 
							
										Init(Context, N, V, L);
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										NoV = Context.NoV;
							 | 
						|||
| 
								 | 
							
										VoH = Context.VoH;
							 | 
						|||
| 
								 | 
							
										NoH = Context.NoH;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										SphereMaxNoH(Context, AreaLight.SphereSinAlpha, true);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									Context.NoV = saturate(abs( Context.NoV ) + 1e-5);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#if MATERIAL_ROUGHDIFFUSE
							 | 
						|||
| 
								 | 
							
									// Chan diffuse model with roughness == specular roughness. This is not necessarily a good modelisation of reality because when the mean free path is super small, the diffuse can in fact looks rougher. But this is a start.
							 | 
						|||
| 
								 | 
							
									// Also we cannot use the morphed context maximising NoH as this is causing visual artefact when interpolating rough/smooth diffuse response. 
							 | 
						|||
| 
								 | 
							
									Lighting.Diffuse = Diffuse_Chan(GBuffer.DiffuseColor, Pow4(GBuffer.Roughness), NoV, NoL, VoH, NoH, GetAreaLightDiffuseMicroReflWeight(AreaLight));
							 | 
						|||
| 
								 | 
							
								#else
							 | 
						|||
| 
								 | 
							
									Lighting.Diffuse = Diffuse_Lambert(GBuffer.DiffuseColor);
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
									// Toon Diffuse
							 | 
						|||
| 
								 | 
							
									Lighting.Diffuse *= AreaLight.FalloffColor * Falloff * GBuffer.ToonCalcShadowColor;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									BRANCH
							 | 
						|||
| 
								 | 
							
									if (bHasAnisotropy)
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										//Lighting.Specular = GBuffer.WorldTangent * .5f + .5f;
							 | 
						|||
| 
								 | 
							
										Lighting.Specular = AreaLight.FalloffColor * (Falloff * NoL) * SpecularGGX(GBuffer.Roughness, GBuffer.Anisotropy, GBuffer.SpecularColor, Context, NoL, AreaLight);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									else
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										if( IsRectLight(AreaLight) )
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											Lighting.Specular = RectGGXApproxLTC(GBuffer.Roughness, GBuffer.SpecularColor, N, V, AreaLight.Rect, AreaLight.Texture);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										else
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											// Toon specular
							 | 
						|||
| 
								 | 
							
											Lighting.Specular = AreaLight.FalloffColor * (Falloff * NoL) * SpecularGGX(GBuffer.Roughness, GBuffer.SpecularColor, Context, NoL, AreaLight);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									Lighting.Specular *= Shadow.SurfaceShadow;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									FBxDFEnergyTerms EnergyTerms = ComputeGGXSpecEnergyTerms(GBuffer.Roughness, Context.NoV, GBuffer.SpecularColor);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// Add energy presevation (i.e. attenuation of the specular layer onto the diffuse component
							 | 
						|||
| 
								 | 
							
									Lighting.Diffuse *= ComputeEnergyPreservation(EnergyTerms);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// Add specular microfacet multiple scattering term (energy-conservation)
							 | 
						|||
| 
								 | 
							
									Lighting.Specular *= ComputeEnergyConservation(EnergyTerms);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									Lighting.Transmission = 0;
							 | 
						|||
| 
								 | 
							
									return Lighting;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								FDirectLighting ToonCustomBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, half NoL, FAreaLight AreaLight, FShadowTerms Shadow )
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									BxDFContext Context;
							 | 
						|||
| 
								 | 
							
									FDirectLighting Lighting;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									float NoV, VoH, NoH;
							 | 
						|||
| 
								 | 
							
								#if SHADING_PATH_MOBILE
							 | 
						|||
| 
								 | 
							
									InitMobile(Context, N, V, L, NoL);
							 | 
						|||
| 
								 | 
							
								#else
							 | 
						|||
| 
								 | 
							
									Init(Context, N, V, L);
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
									NoV = Context.NoV;
							 | 
						|||
| 
								 | 
							
									VoH = Context.VoH;
							 | 
						|||
| 
								 | 
							
									NoH = Context.NoH;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									SphereMaxNoH(Context, AreaLight.SphereSinAlpha, true);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									Context.NoV = saturate(abs( Context.NoV ) + 1e-5);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#if MATERIAL_ROUGHDIFFUSE
							 | 
						|||
| 
								 | 
							
									// Chan diffuse model with roughness == specular roughness. This is not necessarily a good modelisation of reality because when the mean free path is super small, the diffuse can in fact looks rougher. But this is a start.
							 | 
						|||
| 
								 | 
							
									// Also we cannot use the morphed context maximising NoH as this is causing visual artefact when interpolating rough/smooth diffuse response. 
							 | 
						|||
| 
								 | 
							
									Lighting.Diffuse = Diffuse_Chan(GBuffer.DiffuseColor, Pow4(GBuffer.Roughness), NoV, NoL, VoH, NoH, GetAreaLightDiffuseMicroReflWeight(AreaLight));
							 | 
						|||
| 
								 | 
							
								#else
							 | 
						|||
| 
								 | 
							
									Lighting.Diffuse = Diffuse_Lambert(GBuffer.DiffuseColor);
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
									// Toon Diffuse
							 | 
						|||
| 
								 | 
							
									Lighting.Diffuse *= AreaLight.FalloffColor * Falloff * GBuffer.ToonCalcShadowColor;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// Toon specular
							 | 
						|||
| 
								 | 
							
									// Lighting.Specular = AreaLight.FalloffColor * (Falloff * NoL) * ToonSpecular(GBuffer.ToonSpecularLocation, GBuffer.ToonSpecularSmoothness, GBuffer.ToonSpecularColor, NoL);
							 | 
						|||
| 
								 | 
							
									// Lighting.Specular *= Shadow.SurfaceShadow;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// FBxDFEnergyTerms EnergyTerms = ComputeGGXSpecEnergyTerms(GBuffer.Roughness, Context.NoV, GBuffer.SpecularColor);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// Add energy presevation (i.e. attenuation of the specular layer onto the diffuse component
							 | 
						|||
| 
								 | 
							
									// Lighting.Diffuse *= ComputeEnergyPreservation(EnergyTerms);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									Lighting.Specular = 0;
							 | 
						|||
| 
								 | 
							
									Lighting.Transmission = 0;
							 | 
						|||
| 
								 | 
							
									return Lighting;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								FDirectLighting IntegrateBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, half NoL, FAreaLight AreaLight, FShadowTerms Shadow )
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									switch( GBuffer.ShadingModelID )
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_DEFAULT_LIT:
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_SINGLELAYERWATER:
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_THIN_TRANSLUCENT:
							 | 
						|||
| 
								 | 
							
											return DefaultLitBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_SUBSURFACE:
							 | 
						|||
| 
								 | 
							
											return SubsurfaceBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_PREINTEGRATED_SKIN:
							 | 
						|||
| 
								 | 
							
											return PreintegratedSkinBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_CLEAR_COAT:
							 | 
						|||
| 
								 | 
							
											return ClearCoatBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_SUBSURFACE_PROFILE:
							 | 
						|||
| 
								 | 
							
											return SubsurfaceProfileBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_TWOSIDED_FOLIAGE:
							 | 
						|||
| 
								 | 
							
											return TwoSidedBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_HAIR:
							 | 
						|||
| 
								 | 
							
											return HairBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_CLOTH:
							 | 
						|||
| 
								 | 
							
											return ClothBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_EYE:
							 | 
						|||
| 
								 | 
							
											return EyeBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_TOON_BASE:
							 | 
						|||
| 
								 | 
							
											return ToonCustomBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_TOON_PBR:
							 | 
						|||
| 
								 | 
							
										case SHADINGMODELID_TOON_SKIN:
							 | 
						|||
| 
								 | 
							
											return ToonLitBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow );
							 | 
						|||
| 
								 | 
							
										default:
							 | 
						|||
| 
								 | 
							
											return (FDirectLighting)0;
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## DeferredLightPixelShaders.usf
							 | 
						|||
| 
								 | 
							
								在DeferredLightPixelMain()中添加逻辑:
							 | 
						|||
| 
								 | 
							
								1. 非卡通材质正常渲染。
							 | 
						|||
| 
								 | 
							
								2. 材质材质只有在LightingChannel = 2时才会计算卡通光影效果。
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								bool UseToonShadow = IsToonShadingModel(ScreenSpaceData.GBuffer.ShadingModelID);
							 | 
						|||
| 
								 | 
							
								// LightingChannel Toon Shading only calculate light of LightingChannel = 2
							 | 
						|||
| 
								 | 
							
								BRANCH if (!UseToonShadow || (UseToonShadow && DeferredLightUniforms.LightingChannelMask & 0x4))
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									const float SceneDepth = CalcSceneDepth(InputParams.ScreenUV);
							 | 
						|||
| 
								 | 
							
									const FDerivedParams DerivedParams = GetDerivedParams(InputParams, SceneDepth);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									FDeferredLightData LightData = InitDeferredLightFromUniforms(CURRENT_LIGHT_TYPE);
							 | 
						|||
| 
								 | 
							
									UpdateLightDataColor(LightData, InputParams, DerivedParams);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#if USE_HAIR_COMPLEX_TRANSMITTANCE
							 | 
						|||
| 
								 | 
							
									if (ScreenSpaceData.GBuffer.ShadingModelID == SHADINGMODELID_HAIR && ShouldUseHairComplexTransmittance(ScreenSpaceData.GBuffer))
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										LightData.HairTransmittance = EvaluateDualScattering(ScreenSpaceData.GBuffer, DerivedParams.CameraVector, -DeferredLightUniforms.Direction);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									float Dither = InterleavedGradientNoise(InputParams.PixelPos, View.StateFrameIndexMod8);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									float SurfaceShadow = 1.0f;
							 | 
						|||
| 
								 | 
							
									
							 | 
						|||
| 
								 | 
							
									float4 LightAttenuation = GetLightAttenuationFromShadow(InputParams, SceneDepth);
							 | 
						|||
| 
								 | 
							
									float4 Radiance = GetDynamicLighting(DerivedParams.TranslatedWorldPosition, DerivedParams.CameraVector, ScreenSpaceData.GBuffer, ScreenSpaceData.AmbientOcclusion, ScreenSpaceData.GBuffer.ShadingModelID, LightData, LightAttenuation, Dither, uint2(InputParams.PixelPos), SurfaceShadow);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									OutColor += Radiance;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								# PostProcess
							 | 
						|||
| 
								 | 
							
								## ToneMapping
							 | 
						|||
| 
								 | 
							
								c++部分主要修改了:
							 | 
						|||
| 
								 | 
							
								1. PostProcessing.cpp
							 | 
						|||
| 
								 | 
							
								2. PostProcessTonemap.cpp
							 | 
						|||
| 
								 | 
							
								3. PostProcessTonemap.h
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								***实现向ToneMaper Shader传递 `TRDGUniformBufferRef<FSceneTextureUniformParameters>`的功能***
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								之后再PostProcessTonemap.usf中,对**CustomStencil**进行判断,如果为true,则直接返回之前渲染结果。实际上BufferVisualization里根本看不出来。
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								#include "DeferredShadingCommon.ush"
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								// pixel shader entry point
							 | 
						|||
| 
								 | 
							
								void MainPS(
							 | 
						|||
| 
								 | 
							
									in noperspective float2 UV : TEXCOORD0,
							 | 
						|||
| 
								 | 
							
									in noperspective float2 InVignette : TEXCOORD1,
							 | 
						|||
| 
								 | 
							
									in noperspective float4 GrainUV : TEXCOORD2,
							 | 
						|||
| 
								 | 
							
									in noperspective float2 ScreenPos : TEXCOORD3,
							 | 
						|||
| 
								 | 
							
									in noperspective float2 FullViewUV : TEXCOORD4,
							 | 
						|||
| 
								 | 
							
									float4 SvPosition : SV_POSITION,		// after all interpolators
							 | 
						|||
| 
								 | 
							
									out float4 OutColor : SV_Target0
							 | 
						|||
| 
								 | 
							
								#if OUTPUT_LUMINANCE
							 | 
						|||
| 
								 | 
							
									, out float OutLuminance: SV_Target1
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
									)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									float Luminance;
							 | 
						|||
| 
								 | 
							
									FGBufferData SamplerBuffer = GetGBufferData(UV * View.ResolutionFractionAndInv.x, false);
							 | 
						|||
| 
								 | 
							
									if (SamplerBuffer.CustomStencil > 1.0f && abs(SamplerBuffer.CustomDepth - SamplerBuffer.Depth) < 1)
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										OutColor = SampleSceneColor(UV);
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									else
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
								    	OutColor = TonemapCommonPS(UV, InVignette, GrainUV, ScreenPos, FullViewUV, SvPosition, Luminance);
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								#if OUTPUT_LUMINANCE
							 | 
						|||
| 
								 | 
							
									OutLuminance = Luminance;
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## PostProcessCombineLUT.usf
							 | 
						|||
| 
								 | 
							
								主要移植了UE4版本的LUT,以此保证效果统一。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								# 其他
							 | 
						|||
| 
								 | 
							
								## GpuSkinCacheComputeShader.usf
							 | 
						|||
| 
								 | 
							
								注释2行代码,用处不明。
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								#if GPUSKIN_MORPH_BLEND  
							 | 
						|||
| 
								 | 
							
								    {  
							 | 
						|||
| 
								 | 
							
								       Intermediates.UnpackedPosition += Unpacked.DeltaPosition;  
							 | 
						|||
| 
								 | 
							
								       // calc new normal by offseting it with the delta  
							 | 
						|||
| 
								 | 
							
								       LocalTangentZ = normalize( LocalTangentZ + Unpacked.DeltaTangentZ);  
							 | 
						|||
| 
								 | 
							
								       // derive the new tangent by orthonormalizing the new normal against  
							 | 
						|||
| 
								 | 
							
								       // the base tangent vector (assuming these are normalized)       
							 | 
						|||
| 
								 | 
							
								       LocalTangentX = normalize( LocalTangentX - (dot(LocalTangentX, LocalTangentZ) * LocalTangentZ) );  
							 | 
						|||
| 
								 | 
							
								    }#else  
							 | 
						|||
| 
								 | 
							
								#if GPUSKIN_APEX_CLOTH
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								=>
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								#if GPUSKIN_MORPH_BLEND  
							 | 
						|||
| 
								 | 
							
								    {  
							 | 
						|||
| 
								 | 
							
								       Intermediates.UnpackedPosition += Unpacked.DeltaPosition;  
							 | 
						|||
| 
								 | 
							
								       // calc new normal by offseting it with the delta  
							 | 
						|||
| 
								 | 
							
								       //LocalTangentZ = normalize( LocalTangentZ + Unpacked.DeltaTangentZ);  
							 | 
						|||
| 
								 | 
							
								       // derive the new tangent by orthonormalizing the new normal against  
							 | 
						|||
| 
								 | 
							
								       // the base tangent vector (assuming these are normalized)       
							 | 
						|||
| 
								 | 
							
								       //LocalTangentX = normalize( LocalTangentX - (dot(LocalTangentX, LocalTangentZ) * LocalTangentZ) );  
							 | 
						|||
| 
								 | 
							
								    }#else  
							 | 
						|||
| 
								 | 
							
								#if GPUSKIN_APEX_CLOTH
							 | 
						|||
| 
								 | 
							
								```
							 |