*Last update 2025.05.16* *持續踩坑,不定時更新文件* *主要為記錄哪些東西要去修改的筆記,並非某特定渲染效果的教學* *歡迎留下feedback* # 前置作業: 取得Source Code 要先取得 Unreal Github 權限;需要連動 Epic Games 以及 Github 帳號。 申請方法與連結: https://www.unrealengine.com/en-US/ue-on-github 有了權限以後就可以 Clone 或 Fork `Unreal Engine Source Code` 來用。 # 備註 * 有關 Visual Studio 編譯 * 如果沒有修改 `.h` `.cpp` 檔案,只有修改 `.ush` `.usf` 檔案,直接開專案重新Compile Shaders 即可。 * 本篇的環境版本 * Unreal Engine version: fork from Epic's 5.5 branch * IDE: Visual Studio 2022 17.13.6 * 硬體建議 * 請務必把 Source code 裝在 SSD,不然完整Build都要8-9小時起跳 * CPU 越好 Build 越快 * 當然RAM也不要太小,建議至少40G以上,32G有時候會爆 (個人觀察RAM用量大概在25-33G左右) ~~48G雙通道CP值真不錯~~ * ~~貴,從來都不是它的缺點。而是你的缺點。~~ ![image alt](https://memeprod.sgp1.digitaloceanspaces.com/user-wtf/1663763124197.jpg =200x) # 相關檔案 ### C++ header(.h) and source (.cpp) | file | purpose | |:---------------------------------------------- |:-------------------------------------------------------------------------- | | **EngineTypes.h** | 主要用於定義引擎相關設置, `Material Shading Model` Enum在此處擴充 | | **SceneTypes.h** | 主要用於定義渲染相關Enum等 ,在此擴充Material Parameters | | **Material.h** | 主要用於Material系統相關設置, 需要在此新增MSM UPROPERTY | | **Material.cpp** | 主要用於Material系統相關設置,e.g.設定各個MSM要用哪些MP | | **ShaderMaterial.h** | 主要用於定義輔助的Struct, functions以及參數;需要在此新增輔助參數給新的MSM | | **MaterialExpressionMakeMaterialAttributes.h** | 擴充Material Attributes | | **PixelInspectorResult.h** | 擴充Pixel Inspector工具中的 Shading model 定義 | | **PixelInspectorResult.cpp** | 擴充Pixel Inspector工具中的 Shading model 定義 | | **ShaderGenerationUtil.cpp** | 定義新的 Shading model 所需要使用的 Gbuffer slots | | **HLSLMaterialTranslator.cpp** | 修改材質轉譯成HLSL相關設定, 包含 Shading model, GBuffer slot 相關 | | **MaterialAttributeDefinitionMap.cpp** | 擴充 Material Attributes | | **MaterialHLSLEmitter.cpp** | 擴充 HLSL 編譯器的 Shading model 定義 | | **MaterialEditor.cpp** | 擴充 Material Pin 參數類型定義 | | **MaterialGraph.cpp** | 擴充 Material Graph 介面的 Material parameters 相關定義 | | **MaterialShader.cpp** | 擴充Material Attributes | | **MaterialExpressions.cpp** | 擴充MaterialExpressions, Material Attributes | | **MaterialCachedData.cpp** | 修改 Material Expression 相關設定 | | **ShaderMaterialDerivedHelpers.cpp** | 修改 GBuffer 相關使用設定 | | **GBufferInfo.h** | 擴充 GBuffer slot 相關內容 | | **GBufferInfo.cpp** | 擴充 GBuffer slot 相關內容 | | **SceneRendering.cpp** | 擴充 GBuffer slot 相關內容 | | **SceneTextureParameters.h** | 擴充 GBuffer slot 相關內容 | | **SceneTextureParameters.cpp** | 擴充 GBuffer slot 相關內容 | | **SceneTexturesConfig.h** | 擴充 GBuffer slot 相關內容 | | SceneTexturesConfig.cpp | 擴充 GBuffer slot 相關內容 | | **SceneTextures.h** | 擴充 GBuffer slot 相關內容 | | **SceneTextures.cpp** | 擴充 GBuffer slot 相關內容 | | **MaterialSceneTextureId.h** | 擴充 SceneTexture (PPI, Post Process Input) 相關 | | **MaterialShared.h** | 擴充 SceneTexture (PPI, Post Process Input) 相關 | | **SceneRenderTargetParameters.h** | 擴充 GBuffer slot, SceneTexture 相關 | | **PostProcessBufferInspector.cpp** | 擴充 GBuffer slot, SceneTexture 相關 | ### Unreal shader headers and format (.ush & .usf) | file | purpose | |:------------------------------------------- |:-------------------------------------------------------------------------- | | **Definitions.usf** | 擴充 Shading model 定義 | | **ShadingCommon.ush** | 擴充 Material models 相關定義 | | **MaterialTemplate.ush** | 擴充材質hlsl基礎模板 Material parameters 相關定義, 及 PPI 相關內容&定義 | | **Common.ush** | 擴充 MRT (Multi Render Target) 大小 | | **DecalCommon.ush** | 擴充 GBuffer slot 相關 | | **SceneTexturesCommon.ush** | 擴充 GBuffer slot, SceneTexture 相關 | | **BasePassCommon.ush** | 擴充一些基礎Pass定義 | | **BasePassPixelShader.usf** | 修改 Gbuffer 相關參數內容,及擴充 GBuffer slot 相關 | | **DeferredShadingCommon.ush** | 擴充 GBuffer slot 相關,以及 GBufferData, GBuffer slot 間的 Encode, Decode | | **ShaderOutputCommon.ush** | 擴充 GBuffer slot 相關內容 | | **PixelShaderOutputCommon.ush** | 擴充 GBuffer slot 相關內容 | | **SSDCommon.ush** | 擴充 GBuffer slot, GBufferData 相關 | | **ShadingModelsMaterial.ush** | 擴充參數解碼到 Shading Model 的內容(GbufferData) | | **GBufferHelpers.ush** | 修改GBuffer Encode, Decode 用的輔助 functions | | **ShadingModels.ush** | 每個MSM對應的BxDF都定義在這裡,可以調整或自定義 BxDF functions | | **RayTracingDeferredShadingCommon.ush** | 擴充 GBuffer slot, GBufferData 相關 | | **ShadingModelsSampling.ush** | 材質sampling相關function, 例如計算取樣PDF等 | | **ClusteredDeferredShadingPixelShader.usf** | 擴充 Shading model 相關 | | **ReflectionEnvironmentPixelShader.usf** | 調整反射相關Functions | | **DeferredLightingCommon.ush** | 修改或擴充光照積分的function | ### 其他 | file | purpose | | ----------------------------- | ------------------------- | | **ConsoleVariables.ini** | 調整Shader Development 相關設定 | # Expand Material Shading Model ## EngineTypes.h Path: `Runtime/Engine/Classes/Engine/EngineTypes.h` 在這裡將自定義的 `Material Shading Model` 擴充到 EMaterialShadingModel。 * 擴充的項目必須在MSM_NUM前面 * 用MSM作前綴 (不確定前綴不是MSM是否導致無法編譯,UE編譯時在很多地方會強制某些Class要有對應前綴) ```cpp ... MSM_Strata UMETA(DisplayName="Substrate", Hidden), // [Toon][Add-Begin] @cc5568135 MSM_TOON UMETA(DisplayName = "Toon"), // [Toon][Add-End] @cc5568135 MSM_NUM UMETA(Hidden), ... ``` ## MaterialShader.cpp Path: `Runtime/Engine/Private/Materials/MaterialShader.cpp` 擴充GetShadingModelString。 ```cpp ... case MSM_ThinTranslucent: ShadingModelName = TEXT("MSM_ThinTranslucent"); break; // [Toon][Add-Begin] @cc5568135 case MSM_TOON: ShadingModelName = TEXT("MSM_TOON"); break; // [Toon][Add-End] @cc5568135 default: ShadingModelName = TEXT("Unknown"); break; ... ``` 擴充`UpdateMaterialShaderCompilingStats` ```cpp // [Toon][Modify-Begin] @cc5568135 - Toon //else if (ShadingModels.HasAnyShadingModel({ MSM_DefaultLit, MSM_Subsurface, MSM_PreintegratedSkin, MSM_ClearCoat, MSM_Cloth, MSM_SubsurfaceProfile, MSM_TwoSidedFoliage, MSM_SingleLayerWater, MSM_ThinTranslucent })) else if (ShadingModels.HasAnyShadingModel({ MSM_DefaultLit, MSM_Subsurface, MSM_PreintegratedSkin, MSM_ClearCoat, MSM_Cloth, MSM_SubsurfaceProfile, MSM_TwoSidedFoliage, MSM_SingleLayerWater, MSM_ThinTranslucent, MSM_TOON })) // [Toon][Modify-End] @cc5568135 2024/10/25 { INC_DWORD_STAT_BY(STAT_ShaderCompiling_NumLitMaterialShaders, 1); } ``` ## HLSLMaterialTranslator.cpp Path: `Runtime/Engine/Private/Materials/HLSLMaterialTranslator.cpp` 在 `GetMaterialEnvironment` 新增 Define。 ```cpp if (EnvironmentDefines->HasShadingModel(MSM_ThinTranslucent)) { OutEnvironment.SetDefine(TEXT("MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT"), TEXT("1")); bMaterialRequestsDualSourceBlending = true; } // [Toon][Add-Begin] @cc5568135 - Add Toon define if (EnvironmentDefines->HasShadingModel(MSM_TOON)) { OutEnvironment.SetDefine(TEXT("MATERIAL_SHADINGMODEL_TOON"), TEXT("1")); } // [Toon][Add-End] @cc5568135 if (EnvironmentDefines->bDisableForwardLocalLights) { OutEnvironment.SetDefine(TEXT("DISABLE_FORWARD_LOCAL_LIGHTS"), TEXT("1")); } ``` ## MaterialHLSLEmitter.cpp Path: `Runtime/Engine/Private/Materials/MaterialHLSLEmitter.cpp` 在 `GetMaterialEnvironment` 新增 Define。 ```cpp if (ShadingModels.HasShadingModel(MSM_ThinTranslucent)) { OutEnvironment.SetDefine(TEXT("MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT"), TEXT("1")); NumSetMaterials++; bMaterialRequestsDualSourceBlending = true; } // [Toon][Add-Begin] @cc5568135 - Add Toon define if (ShadingModels.HasShadingModel(MSM_TOON)) { OutEnvironment.SetDefine(TEXT("MATERIAL_SHADINGMODEL_TOON"), TEXT("1")); NumSetMaterials++; } // [Toon][Add-End] @cc5568135 2024/10/24 if (ShadingModels.HasShadingModel(MSM_SingleLayerWater) && FDataDrivenShaderPlatformInfo::GetRequiresDisableForwardLocalLights(InPlatform)) { OutEnvironment.SetDefine(TEXT("DISABLE_FORWARD_LOCAL_LIGHTS"), TEXT("1")); } ``` ## ShaderMaterial.h Path: `Runtime/RenderCore/Public/ShaderMaterial.h` 在`FShaderMaterialPropertyDefines` 新增新的MSM。 ```cpp uint8 MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT : 1; // [Toon][Add-Begin] @cc5568135 - Add Toon shading model uint8 MATERIAL_SHADINGMODEL_TOON : 1; // [Toon][Add-End] @cc5568135 2024/10/24 uint8 TRANSLUCENCY_LIGHTING_VOLUMETRIC_NONDIRECTIONAL : 1; ``` ## PixelInspectorResult.h Path: `Editor\PixelInspector\Private\PixelInspectorResult.h` 擴充define ```cpp #define PIXEL_INSPECTOR_SHADINGMODELID_SUBSTRATE 12 // [Toon][Add-Begin] @cc5568135 - Toon #define PIXEL_INSPECTOR_SHADINGMODELID_TOON 13 // [Toon][Add-End] @cc5568135 2024/10/25 #define PIXEL_INSPECTOR_SHADINGMODELID_MASK 0xF ``` ## PixelInspectorResult.cpp Path: `Editor/PixelInspector/Private/PixelInspectorResult.cpp` 擴充`PixelInspectorResult::DecodeShadingModel` ```cpp case PIXEL_INSPECTOR_SHADINGMODELID_THIN_TRANSLUCENT: return EMaterialShadingModel::MSM_ThinTranslucent; // [Toon][Add-Begin] @cc5568135 case PIXEL_INSPECTOR_SHADINGMODELID_TOON: return EMaterialShadingModel::MSM_TOON; // [Toon][Add-End] @cc5568135 Last modified 2025/05/03 ``` 擴充`PixelInspectorResult::DecodeCustomData` ```cpp case EMaterialShadingModel::MSM_Strata: // [Toon][Modified begin] @cc5568135 case EMaterialShadingModel::MSM_TOON: // [Toon][Modified end] @cc5568135 Last modified 2025/05/03 ``` ## ShaderGenerationUtil.cpp Path: `Runtime\Engine\Private\ShaderCompiler\ShaderGenerationUtil.cpp` 擴充`ApplyFetchEnvironmentInternal` ```cpp FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT); // [Toon][Add-Begin] @cc5568135 FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_TOON); // [Toon][Add-End] @cc5568135 2024/10/24 FETCH_COMPILE_BOOL(SINGLE_LAYER_WATER_SEPARATED_MAIN_LIGHT); ``` 並在`DetermineUsedMaterialSlots` 設定新的MSM的 GBuffer Slots,設定CudstomData。 ```cpp // doesn't write to GBuffer if (Mat.MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT) { } // [Toon][Add-Begin] @cc5568135 - Add Toon if (Mat.MATERIAL_SHADINGMODEL_TOON) { SetStandardGBufferSlots(Slots, bWriteEmissive, bHasTangent, bHasVelocity, bWritesVelocity, bHasStaticLighting, bIsSubstrateMaterial); Slots[GBS_CustomData] = GetGBufferSlotUsage(bUseCustomData); } // [Toon][Add-End] @cc5568135 2024/10/24 ``` # Expand Material Parameters ## SceneTypes.h Path: `Runtime\Engine\Public\SceneTypes.h` 新增Material Parameter到EMaterialProperty。 ``` MP_Displacement UMETA(Hidden), // [Toon][Add-Begin] @cc5568135 - Toon MP_ShadowColor UMETA(DisplayName = "Shadow Color"), // [Toon][Add-End] @cc5568135 2024/10/24 ``` ## MaterialAttributeDefinitionMap.cpp Path: `Runtime/Engine/Private/Materials/MaterialAttributeDefinitionMap.cpp` 在這裡設定MP的顯示名稱, 預設值, Guid。 **注意:`InitializeAttributeMap()` 這邊不能設定參數為`MCT_Float4`。** ```cpp // 顯示名稱 FMaterialAttributeDefintion::CompileDefaultValue ... if (Property == MP_ShadowColor && Compiler->GetCompiledShadingModels().HasShadingModel(MSM_TOON)) { check(ValueType == MCT_Float3); return Compiler->Constant3(0.0f, 0.0f, 0.0f); } // 預設值 FMaterialAttributeDefinitionMap::GetAttributeOverrideForMaterial ... case MP_ShadowColor: return LOCTEXT("ShadowColor", "Shadow Color"); ... //Guid FMaterialAttributeDefinitionMap::InitializeAttributeMap ... Add(FGuid(0xf3ba8d73, 0x74144e85, 0xa49c806a, 0xfa83734a), TEXT("ShadowColor"), MP_ShadowColor, MCT_Float3, FVector4(0, 0, 0, 0), SF_Pixel); ... ``` 擴充`GetAttributeOverrideForMaterial(...)` ``` // [Toon][Modified begin] @cc5568135 case MP_ShadowColor: return LOCTEXT("ShadowColor", "Shadow Color"); ... // [Toon][Modified end] @cc5568135 Last modified 2025/05/03 ``` ## Material.h path: `Runtime\Engine\Public\Materials\Material.h` 擴充 class `UMaterialEditorOnlyData` ```cpp ... UPROPERTY() FColorMaterialInput ShadowColor; ... ``` ```cpp // [Toon][Modified begin] @cc5568135 ENGINE_API bool HasShadowColorConnected() const; ... // [Toon][Modified end] @cc5568135 Last modified 2025/05/03 ``` ## Material.cpp path: `Runtime\Engine\Private\Materials\Material.cpp` 首先要調整`MP_MAX`大小 ```cpp // [Toon][Modify-Begin] @cc5568135 - Toon //static_assert(MP_MAX == 35, "New material properties must have DoMaterialAttributeReorder called on them to ensure that any future reordering of property pins is correctly applied."); static_assert(MP_MAX == 35 + 2, "New material properties must have DoMaterialAttributeReorder called on them to ensure that any future reordering of property pins is correctly applied."); // [Toon][Modify-End] @cc5568135 2024/10/25 ``` 擴充`PostLoad` ```cpp DoMaterialAttributeReorder(&EditorOnly->PixelDepthOffset, UEVer, RenderObjVer, UE5MainVer); // [Toon][Add-Begin] @cc5568135 - Toon DoMaterialAttributeReorder(&EditorOnly->ShadowColor, UEVer, RenderObjVer, UE5MainVer); DoMaterialAttributeReorder(&EditorOnly->FaceForwardVector, UEVer, RenderObjVer, UE5MainVer); // [Toon][Add-End] @cc5568135 2024/10/25 DoMaterialAttributeReorder(&EditorOnly->ShadingModelFromMaterialExpression, UEVer, RenderObjVer, UE5MainVer); ``` 擴充`GetExpressionInputDescription` ```cpp case MP_FrontMaterial: SetMaterialInputDescription(EditorOnly->FrontMaterial, false, OutDescription); return true; // [Toon][Add-Begin] @cc5568135 - Toon case MP_ShadowColor: SetMaterialInputDescription(EditorOnly->ShadowColor, false, OutDescription); return true; case MP_FaceForwardVector: SetMaterialInputDescription(EditorOnly->FaceForwardVector, false, OutDescription); return true; // [Toon][Add-End] @cc5568135 2024/10/25 ``` 擴充`CompilePropertyEx` ```cpp // [Toon][Modified begin] @cc5568135 case MP_ShadowColor: return EditorOnly->ShadowColor.CompileWithDefault(Compiler, Property); ... // [Toon][Modified end] @cc5568135 Last modified 2025/05/03 ``` ```cpp // [Toon][Modify-Begin] @cc5568135 - No Reflection for Toon //const bool bUnlitMaterial = ShadingModelID == SHADINGMODELID_UNLIT; const bool bUnlitMaterial = ShadingModelID == SHADINGMODELID_UNLIT || ShadingModelID == SHADINGMODELID_TOON; // [Toon][Modify-End] @cc5568135 2024/10/24 ``` 擴充`IsPropertyActive_Internal` 最下面`if (bSubstrateEnabled){...}else{/*add here*/}` 這裡設定Material parameters,在甚麼條件下才需要被顯示。 ```cpp // [Toon][Add-Begin] @cc5568135 - Toon case MP_ShadowColor: case MP_FaceForwardVector: Active = ShadingModels.HasShadingModel(MSM_TOON); break; // [Toon][Add-End] @cc5568135 2024/10/25 ``` 擴充function ```cpp // [Toon][Modified begin] @cc5568135 bool UMaterial::HasShadowColorConnected() const { return IsPropertyConnected(MP_ShadowColor); } ... // [Toon][Modified end] @cc5568135 Last modified 2025/05/03 ``` ## MaterialEditor.cpp Path: `Editor/MaterialEditor/Private/MaterialEditor.cpp` 擴充`GetOnPromoteToParameterClass` ```cpp case MP_Tangent: // [Toon][Add-Begin] @cc5568135 - Toon case MP_ShadowColor: case MP_FaceForwardVector: // [Toon][Add-End] @cc5568135 2024/10/25 return UMaterialExpressionVectorParameter::StaticClass(); ``` ## MaterialGraph.cpp Path: `Editor/UnrealEd/Private/MaterialGraph.cpp` 擴充`RebuildGraphInternal`,可以加在最下面 ```cpp // [Toon][Add-Begin] @cc5568135 - Toon MaterialInputs.Add(FMaterialInputInfo(FMaterialAttributeDefinitionMap::GetDisplayNameForMaterial(MP_ShadowColor, Material), MP_ShadowColor, LOCTEXT("ShadowColorToolTip", "Shadow Color"))); MaterialInputs.Add(FMaterialInputInfo(FMaterialAttributeDefinitionMap::GetDisplayNameForMaterial(MP_FaceForwardVector, Material), MP_FaceForwardVector, LOCTEXT("FaceForwardVectorToolTip", "Face Forward Vector"))); // [Toon][Add-End] @cc5568135 2024/10/25 ``` ## MaterialExpressionMakeMaterialAttributes.h Path: `Runtime/Engine/Classes/Materials/MaterialExpressionMakeMaterialAttributes.h` 擴充`UMaterialExpressionMakeMaterialAttributes ` ```cpp UPROPERTY() FExpressionInput Displacement; // [Toon][Add-Begin] @cc5568135 - Toon UPROPERTY() FExpressionInput ShadowColor; UPROPERTY() FExpressionInput FaceForwardVector; // [Toon][Add-End] @cc5568135 2024/10/25 ``` ## MaterialExpressions.cpp Path: `Runtime/Engine/Private/Materials/MaterialExpressions.cpp` 調整`MP_MAX`大小,有**兩個地方**要改 ```cpp // [Toon][Modify-Begin] @cc5568135 - Toon //static_assert(MP_MAX == 35, // "New material properties should be added to the end of the outputs for this expression. \ // The order of properties here should match the material results pins, the make material attributes node inputs and the mapping of IO indices to properties in GetMaterialPropertyFromInputOutputIndex().\ // Insertions into the middle of the properties or a change in the order of properties will also require that existing data is fixed up in DoMaterialAttributesReorder().\ // "); static_assert(MP_MAX == 35 + 2, "New material properties should be added to the end of the outputs for this expression. \ The order of properties here should match the material results pins, the make material attributes node inputs and the mapping of IO indices to properties in GetMaterialPropertyFromInputOutputIndex().\ Insertions into the middle of the properties or a change in the order of properties will also require that existing data is fixed up in DoMaterialAttributesReorder().\ "); // [Toon][Modify-End] @cc5568135 2024/10/25 ``` 擴充`GetExpressionInput` ```cpp // [Toon][Add-Begin] @cc5568135 - Toon case MP_ShadowColor: return &ShadowColor; case MP_FaceForwardVector: return &FaceForwardVector; // [Toon][Add-End] @cc5568135 2024/10/25 ``` 擴充`UMaterialExpressionMakeMaterialAttributes::Compile` ```cpp // [Toon][Add-Begin] @cc5568135 - Toon case MP_ShadowColor: Ret = ShadowColor.Compile(Compiler); Expression = ShadowColor.Expression; break; case MP_FaceForwardVector: Ret = FaceForwardVector.Compile(Compiler); Expression = FaceForwardVector.Expression; break; // [Toon][Add-End] @cc5568135 2024/10/25 ``` **注意`Serialize` `UMaterialExpressionBreakMaterialAttributes` `BuildPropertyToIOIndexMap`參數順序/Index要一致** 擴充`BuildPropertyToIOIndexMap` ```cpp // [Toon][Modify-Begin] @cc5568135 - Toon //PropertyToIOIndexMap.Add(MP_ShadingModel, 25); //PropertyToIOIndexMap.Add(MP_Displacement, 26); PropertyToIOIndexMap.Add(MP_ShadowColor, 25); PropertyToIOIndexMap.Add(MP_FaceForwardVector, 26); PropertyToIOIndexMap.Add(MP_ShadingModel, 27); PropertyToIOIndexMap.Add(MP_Displacement, 28); // [Toon][Modify-End] @cc5568135 2024/10/25 ``` 擴充`UMaterialExpressionBreakMaterialAttributes::Serialize` ```cpp // [Toon][Add-Begin] @cc5568135 - Toon Outputs[OutputIndex].SetMask(1, 1, 1, 1, 0); ++OutputIndex; // ShadowColor Outputs[OutputIndex].SetMask(1, 1, 1, 1, 0); ++OutputIndex; // FaceForwardVector // [Toon][Add-End] @cc5568135 2024/10/25 ``` 擴充`UMaterialExpressionBreakMaterialAttributes::UMaterialExpressionBreakMaterialAttributes` ```cpp Outputs.Add(FExpressionOutput(TEXT("PixelDepthOffset"), 1, 1, 0, 0, 0)); // [Toon][Add-Begin] @cc5568135 - Toon Outputs.Add(FExpressionOutput(TEXT("ShadowColor"), 1, 1, 1, 1, 0)); Outputs.Add(FExpressionOutput(TEXT("FaceForwardVector"), 1, 1, 1, 1, 0)); // [Toon][Add-End] @cc5568135 2024/10/25 ``` 擴充`GetConnectedInputs()` ```cpp // [Toon][Modified begin] @cc5568135 if (ShadowColor.Expression != nullptr) Out |= (1ull << uint64(MP_ShadowColor)); ... ``` ## HLSLMaterialTranslator.cpp 在上一章有增加MSM的部分,這邊是PM的部分。 擴充 Construction (`FHLSLMaterialTranslator::FHLSLMaterialTranslator`) ```cpp SharedPixelProperties[MP_Displacement] = true; // [Toon][Add-Begin] @cc5568135 - Toon SharedPixelProperties[MP_ShadowColor] = true; SharedPixelProperties[MP_FaceForwardVector] = true; // [Toon][Add-End] @cc5568135 2024/10/25 ``` 擴充`TranslateMaterial()` ```cpp Chunk[MP_Displacement] = Material->CompilePropertyAndSetMaterialProperty(MP_Displacement, this); // [Toon][Add-Begin] @cc5568135 - Toon Chunk[MP_ShadowColor] = Material->CompilePropertyAndSetMaterialProperty(MP_ShadowColor, this); Chunk[MP_FaceForwardVector] = Material->CompilePropertyAndSetMaterialProperty(MP_FaceForwardVector, this); // [Toon][Add-End] @cc5568135 2024/10/25 ``` ## MaterialHLSLEmitter.cpp 擴充 `bool MaterialEmitHLSL(...)` ``` SharedPixelProperties[MP_Displacement] = true; // [Toon][Add-Begin] @cc5568135 - Toon SharedPixelProperties[MP_ShadowColor] = true; ... // [Toon][Add-End] @cc5568135 Last modified 2025/05/02 ``` ## MaterialCachedData.cpp Path: `Runtime/Engine/Public/MaterialCachedData.h` 擴充`UpdateForExpressions` ```cpp SetMatAttributeConditionally(EMaterialProperty::MP_Displacement, MakeMatAttributes->Displacement.IsConnected()); // [Toon][Add-Begin] @cc5568135 - Toon SetMatAttributeConditionally(EMaterialProperty::MP_ShadowColor, MakeMatAttributes->ShadowColor.IsConnected()); SetMatAttributeConditionally(EMaterialProperty::MP_FaceForwardVector, MakeMatAttributes->FaceForwardVector.IsConnected()); // [Toon][Add-End] @cc5568135 2024/10/25 ``` ## ShaderMaterialDerivedHelpers.cpp Path: `Runtime/RenderCore/Private/ShaderMaterialDerivedHelpers.cpp` 如果要在GBuffer寫入CustomData,在`ShaderMaterialDerivedHelpers.cpp`修改`Dst.WRITES_CUSTOMDATA_TO_GBUFFER = ...` ```cpp // Only some shader models actually need custom data. // [Toon][Modified begin] @cc5568135 // Dst.WRITES_CUSTOMDATA_TO_GBUFFER = (Dst.USES_GBUFFER && (Mat.MATERIAL_SHADINGMODEL_SUBSURFACE || Mat.MATERIAL_SHADINGMODEL_PREINTEGRATED_SKIN || Mat.MATERIAL_SHADINGMODEL_SUBSURFACE_PROFILE || Mat.MATERIAL_SHADINGMODEL_CLEAR_COAT || Mat.MATERIAL_SHADINGMODEL_TWOSIDED_FOLIAGE || Mat.MATERIAL_SHADINGMODEL_HAIR || Mat.MATERIAL_SHADINGMODEL_CLOTH || Mat.MATERIAL_SHADINGMODEL_EYE)); Dst.WRITES_CUSTOMDATA_TO_GBUFFER = (Dst.USES_GBUFFER && (Mat.MATERIAL_SHADINGMODEL_SUBSURFACE || Mat.MATERIAL_SHADINGMODEL_PREINTEGRATED_SKIN || Mat.MATERIAL_SHADINGMODEL_SUBSURFACE_PROFILE || Mat.MATERIAL_SHADINGMODEL_CLEAR_COAT || Mat.MATERIAL_SHADINGMODEL_TWOSIDED_FOLIAGE || Mat.MATERIAL_SHADINGMODEL_HAIR || Mat.MATERIAL_SHADINGMODEL_CLOTH || Mat.MATERIAL_SHADINGMODEL_EYE || Mat.MATERIAL_SHADINGMODEL_TOON)); // [Toon][Modified end] @cc5568135 Last modified 2025/05/03 ``` # Expand Gbuffer ## Gbuffer slots 說明 Material Parameters 並非一個參數對應一個獨立的 Gbuffer slots,而是在不同設定下寫進不同的 Gbuffer slots。 原始 Source code 有 `GBufferA` 至 `GBufferF`, `GBufferVelocity` 7 個 half4 參數的GBuffer。 Gbuffer Slots 對應如下: | Slot / Channel | r | g | b | a | |:--------------- | -------------------------- | -------------------------- |:-------------------------- |:-------------------------- | | GBufferA | WorldNormal.r | WorldNormal.g | WorldNormal.b | PerObjectGBufferData | | GBufferB | Metallic | Specular | Roughness | ShadingModelID | | GBufferC | BaseColor.r | BaseColor.g | BaseColor.b | AO | | GBufferD | CustomData.r | CustomData.g | CustomData.b | CustomData.a | | GBufferE | PrecomputedShadowFactors.r | PrecomputedShadowFactors.g | PrecomputedShadowFactors.b | PrecomputedShadowFactors.a | | GBufferF | WorldTangent.x | WorldTangent.y | WorldTangent.z | Anisotropy | | GBufferVelocity | Velocity.r | Velocity.g | Velocity.b | Velocity.a | CustomData 通常被用來存不同 Shading model 所需要的參數,設定位置在`ShadingModelsMaterial.ush` 的`void SetGBufferForShadingModel`。 例如 Shading model = Subsurface時: ```cpp GBuffer.CustomData.rgb = EncodeSubsurfaceColor(SubsurfaceColor); GBuffer.CustomData.a = Opacity; ``` 可以自行判斷是不是需要增加 Slot。 ## Gbuffer Encode, Decode 自動生成說明 似乎在UE5版本之後(應該5.0開始就已經改了,5.3確定是如此),官方把原本在`DeferredShadingCommon.ush`定義的`EncodeGBuffer(...)` `DecodeGBufferData(...)` 內容都以捨棄,改用`GBufferInfo.cpp`等檔案來做設定並自動生成 hlsl。 可以在`BasePassPixelShader`看到以下Code,改用自動生成的`EncodeGBufferToMRT(...)`來達到Encode目的。 ```cpp // this is the new encode, the older encode is the #else, keeping it around briefly until the new version is confirmed stable. #if 1 ``` ### 踩雷心得 想要在Gbuffer裡面塞進新的參數,必須先在`enum EGBufferSlot`定義新的GBS內容,然後在`GBufferInfo.cpp`新增對應TargetGBuffer欄位的對應。 我新增了兩個GBuffer: GBufferG, GBufferH,不過途中遇到不少問題。 造成Compile錯誤的踩雷整理,***並不是非常確定***這些就是造成錯誤的確切原因,可以當作參考。 注意點: * TargetGBufferG 每個欄位應該都需要有被設定,不能有部分被設定、部分沒有的情況。 ```cpp // 四個欄位都有設定,這樣應該比較沒問題 Info.Slots[GBS_ShadowColor] = FGBufferItem(GBS_ShadowColor, GBC_Raw_Unorm_8_8_8_8, GBCH_Both); Info.Slots[GBS_ShadowColor].Packing[0] = FGBufferPacking(TargetGBufferG, 0, 0); Info.Slots[GBS_ShadowColor].Packing[1] = FGBufferPacking(TargetGBufferG, 1, 1); Info.Slots[GBS_ShadowColor].Packing[2] = FGBufferPacking(TargetGBufferG, 2, 2); Info.Slots[GBS_ShadowColor].Packing[3] = FGBufferPacking(TargetGBufferG, 3, 3); ``` * 不能有重複設定到欄位的部分,像是我想要對CstomData再做設定會造成錯誤。 ```cpp // 應該會造成錯誤, TargetGBufferD 是給 CustomData用。已經被設定過了 Info.Slots[GBS_FaceVectors] = FGBufferItem(GBS_FaceForwwardVector, GBC_Raw_Unorm_8_8, GBCH_Both); Info.Slots[GBS_FaceVectors].Packing[0] = FGBufferPacking(TargetGBufferD, 0, 0); Info.Slots[GBS_FaceVectors].Packing[1] = FGBufferPacking(TargetGBufferD, 1, 1); ``` * 如果新增的GBS要設定到新的GBuffer slot,建議兩者都是 float4 (四維數)。用兩個float2 的 GBS 去塞一個 GBuffer slot 會出錯。 ```cpp! //寫這樣出錯 Info.Slots[GBS_FaceForwardVector] = FGBufferItem(GBS_FaceForwardVector, GBC_Raw_Unorm_8_8, GBCH_Both); Info.Slots[GBS_FaceForwardVector].Packing[0] = FGBufferPacking(TargetGBufferH, 0, 0); Info.Slots[GBS_FaceForwardVector].Packing[1] = FGBufferPacking(TargetGBufferH, 1, 1); Info.Slots[GBS_FaceRightwardVector] = FGBufferItem(GBS_FaceRightwardVector, GBC_Raw_Unorm_8_8, GBCH_Both); Info.Slots[GBS_FaceRightwardVector].Packing[0] = FGBufferPacking(TargetGBufferH, 2, 2); Info.Slots[GBS_FaceRightwardVector].Packing[1] = FGBufferPacking(TargetGBufferH, 3, 3); //改成這樣就沒問題 Info.Slots[GBS_FaceVectors] = FGBufferItem(GBS_FaceVectors, GBC_Raw_Unorm_8_8_8_8, GBCH_Both); Info.Slots[GBS_FaceVectors].Packing[0] = FGBufferPacking(TargetGBufferH, 0, 0); Info.Slots[GBS_FaceVectors].Packing[1] = FGBufferPacking(TargetGBufferH, 1, 1); Info.Slots[GBS_FaceVectors].Packing[2] = FGBufferPacking(TargetGBufferH, 2, 2); Info.Slots[GBS_FaceVectors].Packing[3] = FGBufferPacking(TargetGBufferH, 3, 3); ``` * `ShaderGenerationUtil.cpp`當中的`FString GetSlotTextName(EGBufferSlot Slot)` return的字串對應到 `struct FGBufferData` 裡面的名稱。當然,value type 的維度也需要對上。 * 呈上兩項,如果 MP (Materail parameter) 的參數設定不是 float4 (確實也沒辦法是float4),可以在 `struct FGBufferData` 新增一個對應 GBS 的 half4 ,並在 `BasePassPixelShader.usf` Out.MRT 被設定之前,Gbuffer參數互換過去就可以了。 ```cpp // 舉例來說,定義了 MP_FaceForwardVector MP_FaceRightwardVector (不需要z值) // BasePassPixelShader.usf FPixelShaderInOut_MainPS, Out.MRT 被設定之前 GBuffer.FaceVectors.rg = GBuffer.FaceForwardVector.rg; GBuffer.FaceVectors.ba = GBuffer.FaceRightwardVector.rg; // DeferredShadingCommon.ush struct FGBufferData half3 FaceForwardVector; half3 FaceRightwardVector; half4 FaceVectors; ``` ## GBufferInfo.h Path`Runtime\RenderCore\Public\GBufferInfo.h` 擴充`EGBufferSlot`,在GBS_Num上面。 ```cpp // [Toon][Modified begin] @cc5568135 GBS_ShadowColor, // RGB8 // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` 擴充`FGBufferBindings` ```cpp FGBufferBinding GBufferE; // [Toon][Modified begin] @cc5568135 FGBufferBinding GBufferG; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 FGBufferBinding GBufferVelocity; ``` 調整`FGBufferInfo` MaxTargets ```cpp // [Toon][Modified begin] @cc5568135 // static const int MaxTargets = 8; static const int MaxTargets = 8 + 1 ; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` ## GBufferInfo.cpp 擴充`FetchLegacyGBufferInfo` 這裡是對應Render Target (RT)的 index,預設未啟用是-1 ```cpp int32 TargetGBufferF = -1; // [Toon][Modified begin] @cc5568135 int32 TargetGBufferG = -1; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 int32 TargetVelocity = -1; ``` 增加 Info.NumTargets ```cpp else { Info.NumTargets = Params.bHasPrecShadowFactor ? 7 : 6; } // [Toon][Modified begin] @cc5568135 Info.NumTargets++; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 // good to see the quality loss due to precision in the gbuffer const bool bHighPrecisionGBuffers = (Params.LegacyFormatIndex >= EGBufferFormat_Force16BitsPerChannel); ``` 擴充`if (Params.bHasVelocity == 0 && Params.bHasTangent == 0)`底下內容 ```cpp // This code should match TBasePassPS if (Params.bHasVelocity == 0 && Params.bHasTangent == 0) { TargetGBufferD = 4; Info.Targets[4].Init(GBT_Unorm_8_8_8_8, TEXT("GBufferD"), false, true, true, true); TargetSeparatedMainDirLight = 5; if (Params.bHasPrecShadowFactor) { TargetGBufferE = 5; Info.Targets[5].Init(GBT_Unorm_8_8_8_8, TEXT("GBufferE"), false, true, true, true); TargetSeparatedMainDirLight = 6; } // [Toon][Modified begin] @cc5568135 TargetGBufferG = TargetGBufferE == -1 ? 5 : TargetGBufferE + 1; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 } else if (Params.bHasVelocity) { TargetVelocity = 4; TargetGBufferD = 5; // note the false for use extra flags for velocity, not quite sure of all the ramifications, but this keeps it consistent with previous usage Info.Targets[4].Init(Params.bUsesVelocityDepth ? GBT_Unorm_16_16_16_16 : (IsAndroidOpenGLESPlatform(Params.ShaderPlatform) ? GBT_Float_16_16 : GBT_Unorm_16_16), TEXT("Velocity"), false, true, true, false); Info.Targets[5].Init(GBT_Unorm_8_8_8_8, TEXT("GBufferD"), false, true, true, true); TargetSeparatedMainDirLight = 6; if (Params.bHasPrecShadowFactor) { TargetGBufferE = 6; Info.Targets[6].Init(GBT_Unorm_8_8_8_8, TEXT("GBufferE"), false, true, true, false); TargetSeparatedMainDirLight = 7; } // [Toon][Modified begin] @cc5568135 TargetGBufferG = TargetGBufferE == -1 ? 6 : TargetGBufferE + 1; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 } else if (Params.bHasTangent) { TargetGBufferF = 4; TargetGBufferD = 5; Info.Targets[4].Init(GBT_Unorm_8_8_8_8, TEXT("GBufferF"), false, true, true, true); Info.Targets[5].Init(GBT_Unorm_8_8_8_8, TEXT("GBufferD"), false, true, true, true); TargetSeparatedMainDirLight = 6; if (Params.bHasPrecShadowFactor) { TargetGBufferE = 6; Info.Targets[6].Init(GBT_Unorm_8_8_8_8, TEXT("GBufferE"), false, true, true, true); TargetSeparatedMainDirLight = 7; } // [Toon][Modified begin] @cc5568135 TargetGBufferG = TargetGBufferE == -1 ? 6 : TargetGBufferE + 1; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 } else { // should never hit this path check(0); } // [Toon][Modified begin] @cc5568135 Info.Targets[TargetGBufferG].Init(GBT_Unorm_8_8_8_8, TEXT("GBufferG"), false, true, true, true); // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` ```cpp Info.Slots[GBS_CustomData].Packing[2] = FGBufferPacking(TargetGBufferD, 2, 2); Info.Slots[GBS_CustomData].Packing[3] = FGBufferPacking(TargetGBufferD, 3, 3); // [Toon][Modified begin] @cc5568135 Info.Slots[GBS_ShadowColor] = FGBufferItem(GBS_ShadowColor, GBC_Raw_Unorm_8_8_8, GBCH_Both); Info.Slots[GBS_ShadowColor].Packing[0] = FGBufferPacking(TargetGBufferG, 0, 0); Info.Slots[GBS_ShadowColor].Packing[1] = FGBufferPacking(TargetGBufferG, 1, 1); Info.Slots[GBS_ShadowColor].Packing[2] = FGBufferPacking(TargetGBufferG, 2, 2); // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` ## SceneRendering.h Path `Runtime\Renderer\Private\SceneRendering.h` ```cpp ETextureCreateFlags GBufferF; // [Toon][Modified begin] @cc5568135 ETextureCreateFlags GBufferG; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ETextureCreateFlags GBufferVelocity; ``` ## SceneRendering.cpp Path `Runtime\Renderer\Private\SceneRendering.cpp` ```cpp // [Toon][Modified begin] @cc5568135 FASTVRAM_CVAR(GBufferG, 0); // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 FASTVRAM_CVAR(GBufferVelocity, 0); ``` 擴充`Update()` ```cpp bDirty |= UpdateTextureFlagFromCVar(CVarFastVRam_GBufferF, GBufferF); // [Toon][Modified begin] @cc5568135 bDirty |= UpdateTextureFlagFromCVar(CVarFastVRam_GBufferG, GBufferG); // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 bDirty |= UpdateTextureFlagFromCVar(CVarFastVRam_GBufferVelocity, GBufferVelocity); ``` ## SceneTextureParameters.h Path `Runtime\Renderer\Private\SceneTextureParameters.h` 擴充`FSceneTextures` ```cpp SHADER_PARAMETER_RDG_TEXTURE(Texture2D, GBufferFTexture) // [Toon][Modified begin] @cc5568135 SHADER_PARAMETER_RDG_TEXTURE(Texture2D, GBufferGTexture) // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 SHADER_PARAMETER_RDG_TEXTURE(Texture2D, GBufferVelocityTexture) ``` ## SceneTextureParameters.cpp 擴充`GetSceneTextureParameters` Path`Runtime\Renderer\Private\SceneTextureParameters.cpp` ```cpp Parameters.GBufferFTexture = GetIfProduced(SceneTextures.GBufferF, SystemTextures.MidGrey); // [Toon][Modified begin] @cc5568135 Parameters.GBufferGTexture = GetIfProduced(SceneTextures.GBufferG); // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` 擴充另一個`GetSceneTextureParameters` ```cpp Parameters.GBufferFTexture = (*SceneTextureUniformBuffer)->GBufferFTexture; // [Toon][Modified begin] @cc5568135 Parameters.GBufferGTexture = (*SceneTextureUniformBuffer)->GBufferGTexture; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 Parameters.GBufferVelocityTexture = (*SceneTextureUniformBuffer)->GBufferVelocityTexture; ``` ## SceneTexturesConfig.h Path`Runtime\Engine\Private\SceneTexturesConfig.h` 擴充`FSceneTextureUniformParameters` ```cpp SHADER_PARAMETER_RDG_TEXTURE(Texture2D, GBufferFTexture) // [Toon][Modified begin] @cc5568135 SHADER_PARAMETER_RDG_TEXTURE(Texture2D, GBufferGTexture) // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` ## SceneTexturesConfig.cpp Path`Runtime\Engine\Private\SceneTexturesConfig.cpp` 擴充`SetupMobileGBufferFlags` ```cpp Bindings.GBufferE.Flags |= AddFlags; // [Toon][Modified begin] @cc5568135 Bindings.GBufferG.Flags |= AddFlags; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ... Bindings.GBufferE.Flags &= (~RemoveFlags); // [Toon][Modified begin] @cc5568135 Bindings.GBufferG.Flags &= (~RemoveFlags); // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ... OverrideB8G8R8A8(Bindings.GBufferE); // [Toon][Modified begin] @cc5568135 OverrideB8G8R8A8(Bindings.GBufferG); // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` 擴充`Init` ```cpp BindingCache.Bindings[Layout].GBufferE = FindGBufferBindingByName(GBufferInfo, TEXT("GBufferE"), ShaderPlatform); // [Toon][Modified begin] @cc5568135 BindingCache.Bindings[Layout].GBufferG = FindGBufferBindingByName(GBufferInfo, TEXT("GBufferG"), ShaderPlatform); // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 BindingCache.Bindings[Layout].GBufferVelocity = FindGBufferBindingByName(GBufferInfo, TEXT("Velocity"), ShaderPlatform); ``` 擴充`GetGBufferRenderTargetsInfo` ```cpp IncludeBindingIfValid(Bindings.GBufferE); // [Toon][Modified begin] @cc5568135 IncludeBindingIfValid(Bindings.GBufferG); // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 IncludeBindingIfValid(Bindings.GBufferVelocity); ``` ## SceneTextures.h Path `Runtime\Renderer\Private\SceneTextures.h` ```cpp FRDGTextureRef GBufferF{}; // [Toon][Modified begin] @cc5568135 FRDGTextureRef GBufferG{}; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` ## SceneTextures.cpp Path`Runtime\Renderer\Private\SceneTextures.cpp` 擴充`InitializeViewFamily` ```cpp ... SceneTextures.GBufferF = GraphBuilder.CreateTexture(Desc, TEXT("GBufferF")); } // [Toon][Modified begin] @cc5568135 if (Bindings.GBufferG.Index >= 0) { const FRDGTextureDesc Desc(Config.bRequireMultiView ? FRDGTextureDesc::Create2DArray(Config.Extent, Bindings.GBufferG.Format, FClearValueBinding::Transparent, Bindings.GBufferG.Flags | FlagsToAdd | GFastVRamConfig.GBufferG, 2) : FRDGTextureDesc::Create2D(Config.Extent, Bindings.GBufferG.Format, FClearValueBinding::Transparent, Bindings.GBufferG.Flags | FlagsToAdd | GFastVRamConfig.GBufferG)); SceneTextures.GBufferG = GraphBuilder.CreateTexture(Desc, TEXT("GBufferG")); } // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` 擴充`FGBufferEntry GBufferEntries[]` ```cpp { TEXT("GBufferE"), GBufferE, Bindings.GBufferE.Index }, // [Toon][Modified begin] @cc5568135 { TEXT("GBufferG"), GBufferG, Bindings.GBufferG.Index }, // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` 擴充 `GetSceneTexture` ```cpp case ESceneTexture::GBufferF: return SceneTextures.GBufferF; // [Toon][Modified begin] @cc5568135 case ESceneTexture::GBufferG: return SceneTextures.GBufferG; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` 擴充`SetupSceneTextureUniformParameters` ```cpp SceneTextureParameters.GBufferFTexture = SystemTextures.MidGrey; // [Toon][Modified begin] @cc5568135 SceneTextureParameters.GBufferGTexture = SystemTextures.Black; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` ```cpp if (EnumHasAnyFlags(SetupMode, ESceneTextureSetupMode::GBufferF) && HasBeenProduced(SceneTextures->GBufferF)) { SceneTextureParameters.GBufferFTexture = SceneTextures->GBufferF; } // [Toon][Modified begin] @cc5568135 if (EnumHasAnyFlags(SetupMode, ESceneTextureSetupMode::GBufferG) && HasBeenProduced(SceneTextures->GBufferG)) { SceneTextureParameters.GBufferGTexture = SceneTextures->GBufferG; } // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` ## MaterialSceneTextureId.h Path `Runtime\Engine\Public\MaterialSceneTextureId.h` 擴充`ESceneTextureId`,可以讓SceneTexture擷取到新的Gbuffer。要注意這個Enum的上限為31。 ``` /** Material anisotropy, single channel (GBuffer) */ PPI_Anisotropy UMETA(DisplayName = "Anisotropy"), // [Toon][Modified begin] @cc5568135 PPI_CustomExtraDataA UMETA(DisplayName = "ToonShadowColor"), // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` ## MaterialShared.h Path `Runtime\Engine\Public\MaterialShared.h` 擴充`NeedsGBuffer` ```cpp IsSceneTextureUsed(PPI_StoredSpecular) || // [Toon][Modified begin] @cc5568135 IsSceneTextureUsed(PPI_CustomExtraDataA) || // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 IsSceneTextureUsed(PPI_Velocity); ``` ## SceneRenderTargetParameters.h Path `Runtime\Renderer\Public\SceneRenderTargetParameters.h` 擴充`ESceneTexture` ```cpp GBufferF, // [Toon][Modified begin] @cc5568135 GBufferG, // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` 修改`ESceneTextureSetupMode` ```cpp GBufferF = 1 << 8, // [Toon][Modified begin] @cc5568135 // SSAO = 1 << 9, //CustomDepth = 1 << 10, //GBuffers = GBufferA | GBufferB | GBufferC | GBufferD | GBufferE | GBufferF, GBufferG = 1 << 9, SSAO = 1 << 10, CustomDepth = 1 << 11, GBuffers = GBufferA | GBufferB | GBufferC | GBufferD | GBufferE | GBufferF | GBufferG, // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` ## PostProcessBufferInspector.cpp Path `Runtime\Renderer\Private\PostProcess\PostProcessBufferInspector.cpp` 擴充`FPixelInspectorParameters` ```cpp RDG_TEXTURE_ACCESS(GBufferF, ERHIAccess::CopySrc) // [Toon][Modified begin] @cc5568135 RDG_TEXTURE_ACCESS(GBufferG, ERHIAccess::CopySrc) // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` 擴充`ProcessPixelInspectorRequests` (// GBuffer BCDEF) ```cpp if (Parameters.GBufferF) { FRHITexture* SourceBufferF = Parameters.GBufferF->GetRHI(); if (DestinationBufferBCDEF->GetFormat() == SourceBufferF->GetFormat()) { FRHICopyTextureInfo CopyInfo; CopyInfo.SourcePosition = SourcePoint; CopyInfo.Size = FIntVector(1, 1, 1); RHICmdList.CopyTexture(SourceBufferF, DestinationBufferBCDEF, CopyInfo); } } // [Toon][Modified begin] @cc5568135 if (Parameters.GBufferG) { FRHITexture* SourceBufferG = Parameters.GBufferG->GetRHI(); if (DestinationBufferBCDEF->GetFormat() == SourceBufferG->GetFormat()) { FRHICopyTextureInfo CopyInfo; CopyInfo.SourcePosition = SourcePoint; CopyInfo.DestPosition = FIntVector(4, 0, 0); CopyInfo.Size = FIntVector(1, 1, 1); RHICmdList.CopyTexture(SourceBufferG, DestinationBufferBCDEF, CopyInfo); } } ``` 擴充`AddPixelInspectorPass` ```cpp PassParameters->GBufferF = SceneTextures.GBufferFTexture; // [Toon][Modified begin] @cc5568135 PassParameters->GBufferG = SceneTextures.GBufferGTexture; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` ## ShaderGenerationUtil.cpp Path `Runtime\Engine\Private\ShaderCompiler\ShaderGenerationUtil.cpp` 擴充`GetSlotTextName`,*這裡return TEXT 字串要與FGBufferData名稱一致* (待確認)。 ```cpp case GBS_SeparatedMainDirLight: return TEXT("SeparatedMainDirLight"); // [Toon][Modified begin] @cc5568135 case GBS_ShadowColor: return TEXT("ShadowColor"); // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` 擴充前一章修改過的`DetermineUsedMaterialSlots` ```cpp // [Toon][Modified begin] @cc5568135 if (Mat.MATERIAL_SHADINGMODEL_TOON) { SetStandardGBufferSlots(Slots, bWriteEmissive, bHasTangent, bHasVelocity, bWritesVelocity, bHasStaticLighting, bIsSubstrateMaterial); Slots[GBS_CustomData] = GetGBufferSlotUsage(bUseCustomData); Slots[GBS_ShadowColor] = GetGBufferSlotUsage(bUseCustomData); } // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` # Expand Unreal Shaders 只修改 `.ush` `.usf` 檔案時,直接重開專案 Compile Shaders 即可,不用重新VS Build,也不用重新開一次 `UnrealEditor.exe` ## Definitions.usf Path: `Shaders/Private/Definitions.usf` 新增 `#define` ```cpp // [Toon][Add-Begin] @cc5568135 - Toon #ifndef MATERIAL_SHADINGMODEL_TOON #define MATERIAL_SHADINGMODEL_TOON 0 #endif // [Toon][Add-End] @cc5568135 2024/10/24 ``` ## ShadingCommon.ush Path: `Shaders/Private/ShadingCommon.ush` 擴充`SHADINGMODELID`,需要改原本`SHADINGMODELID_NUM`的數值。 ```cpp // #define SHADINGMODELID_NUM 13 // [Toon][Modify-Begin] @cc5568135 - Toon #define SHADINGMODELID_TOON 13 #define SHADINGMODELID_NUM 14 // [Toon][Modify-End] @cc5568135 2024/10/24 ``` 擴充`GetShadingModelColor` ```cpp else if (ShadingModelID == SHADINGMODELID_THIN_TRANSLUCENT) return float3(1.0f, 0.8f, 0.3f); // [Toon][Add-Begin] @cc5568135 - Toon else if (ShadingModelID == SHADINGMODELID_TOON) return float3(0.2f, 0.8f, 0.8f); // [Toon][Add-End] @cc5568135 2024/10/24 ``` ```cpp case SHADINGMODELID_THIN_TRANSLUCENT: return float3(1.0f, 0.8f, 0.3f); // [Toon][Add-Begin] @cc5568135 - Toon case SHADINGMODELID_TOON: return float3(0.2f, 0.8f, 0.8f); // [Toon][Add-End] @cc5568135 2024/10/24 ``` ## MaterialTemplate.ush Path: `Shaders/Private/MaterialTemplate.ush` 擴充 ```cpp // [Toon][Add-Begin] @cc5568135 - Toon half3 GetMaterialShadowColorRaw(FPixelMaterialInputs PixelMaterialInputs) { return PixelMaterialInputs.ShadowColor; } half3 GetMaterialShadowColor(FPixelMaterialInputs PixelMaterialInputs) { return saturate(GetMaterialShadowColorRaw(PixelMaterialInputs)); } half3 GetMaterialFaceForwardVectorRaw(FPixelMaterialInputs PixelMaterialInputs) { return PixelMaterialInputs.FaceForwardVector; } half3 GetMaterialFaceForwardVector(FPixelMaterialInputs PixelMaterialInputs) { return saturate(GetMaterialFaceForwardVectorRaw(PixelMaterialInputs)); } // [Toon][Add-End] @cc5568135 2024/10/26 half GetMaterialAmbientOcclusionRaw(FPixelMaterialInputs PixelMaterialInputs) { return PixelMaterialInputs.AmbientOcclusion; } ``` 如有需要,新增PPI ```cpp #define PPI_Anisotropy 30 // [Toon][Modified begin] @cc5568135 #define PPI_ShadowColor 31 // [Toon][Modified end] @cc5568135 Last modified 2025/05/08 ``` ```cpp case PPI_Anisotropy: return ScreenSpaceData.GBuffer.Anisotropy; // [Toon][Modified begin] @cc5568135 case PPI_ShadowColor: return float4(ScreenSpaceData.GBuffer.ShadowColor, 0); // [Toon][Modified end] @cc5568135 Last modified 2025/05/09 ``` ## Common.ush Path `Shaders\Private\Common.ush` 擴充`FPixelShaderOut`,如有增加 Gbuffer Slots 才要調整。 ```cpp struct FPixelShaderOut { // [0..7], only usable if PIXELSHADEROUTPUT_MRT0, PIXELSHADEROUTPUT_MRT1, ... is 1 // [Toon][Modified begin] @cc5568135 // float4 MRT[8]; float4 MRT[8 + 1]; // [Toon][Modified end] @cc5568135 Last modified 2025/05/07 ``` ## DecalCommon.ush Path `Shaders\Private\DecalCommon.ush` 如有新增GBuffer Slot,擴充`DecalCommonOutput` ```cpp float4 OutTarget5 = 0; float4 OutTarget6 = 0; // [Toon][Modified begin] @cc5568135 float4 OutTarget7 = 0; // [Toon][Modified end] @cc5568135 Last modified 2025/05/08 ``` ## SceneTexturesCommon.ush Path `Shaders\Private\SceneTexturesCommon.ush` 如有新增GBuffer,擴充 #define `SceneTexturesStruct` ```cpp #define SceneTexturesStruct_GBufferFTextureSampler SceneTexturesStruct.PointClampSampler // [Toon][Modified begin] @cc5568135 #define SceneTexturesStruct_GBufferGTextureSampler SceneTexturesStruct.PointClampSampler // [Toon][Modified end] @cc5568135 Last modified 2025/05/08 #define SceneTexturesStruct_GBufferVelocityTextureSampler SceneTexturesStruct.PointClampSampler ``` ## BasePassCommon.ush Path: `Shaders/Private/BasePassCommon.ush` 這裡可以透過修改`#define WRITES_CUSTOMDATA_TO_GBUFFER` 設定新的MSM要不要把CustomData加進GBuffer。 ```cpp // Only some shader models actually need custom data. // [Toon][Modified begin] @cc5568135 //#define WRITES_CUSTOMDATA_TO_GBUFFER (USES_GBUFFER && (MATERIAL_SHADINGMODEL_SUBSURFACE || MATERIAL_SHADINGMODEL_PREINTEGRATED_SKIN || MATERIAL_SHADINGMODEL_SUBSURFACE_PROFILE || MATERIAL_SHADINGMODEL_CLEAR_COAT || MATERIAL_SHADINGMODEL_TWOSIDED_FOLIAGE || MATERIAL_SHADINGMODEL_HAIR || MATERIAL_SHADINGMODEL_CLOTH || MATERIAL_SHADINGMODEL_EYE)) #define WRITES_CUSTOMDATA_TO_GBUFFER (USES_GBUFFER && (MATERIAL_SHADINGMODEL_SUBSURFACE || MATERIAL_SHADINGMODEL_PREINTEGRATED_SKIN || MATERIAL_SHADINGMODEL_SUBSURFACE_PROFILE || MATERIAL_SHADINGMODEL_CLEAR_COAT || MATERIAL_SHADINGMODEL_TWOSIDED_FOLIAGE || MATERIAL_SHADINGMODEL_HAIR || MATERIAL_SHADINGMODEL_CLOTH || MATERIAL_SHADINGMODEL_EYE || MATERIAL_SHADINGMODEL_TOON)) // [Toon][Modified end] @cc5568135 Last modified 2025/05/03 ``` ## DeferredShadingCommon.ush Path: `Shaders/Private/DeferredShadingCommon.ush` 如有新增GBuffer Slot,擴充`Texture2D`等#define定義 ```cpp Texture2D GBufferFTexture; // [Toon][Modified begin] @cc5568135 Texture2D GBufferGTexture; // [Toon][Modified end] @cc5568135 Last modified 2025/05/08 Texture2D<uint> SceneLightingChannels; ... #define GBufferFTextureSampler GlobalPointClampedSampler // [Toon][Modified begin] @cc5568135 #define GBufferGTextureSampler GlobalPointClampedSampler // [Toon][Modified end] @cc5568135 Last modified 2025/05/08 #define GBufferVelocityTextureSampler GlobalPointClampedSampler ``` 擴充`HasCustomGBufferData` ```cpp ... || ShadingModelID == SHADINGMODELID_CLOTH // [Toon][Add-Begin] @cc5568135 - Toon || ShadingModelID == SHADINGMODELID_TOON // [Toon][Add-End] @cc5568135 2024/10/26 || ShadingModelID == SHADINGMODELID_EYE; ``` 擴充`FGBufferData` ```cpp ... // Curvature for mobile subsurface profile half Curvature; // [Toon][Add-Begin] @cc5568135 - Toon // 0..1, only needed by SHADINGMODELID_TOON half3 ShadowColor; // 0..1, only needed by SHADINGMODELID_TOON half3 FaceForwardVector; // [Toon][Add-End] @cc5568135 2024/10/26 }; ``` 擴充`EncodeGBuffer`,如有新增GBuffer Slot 可以自行調整內容 ```cpp out float4 OutGBufferE, // [Toon][Modified begin] @cc5568135 out float4 OutGBufferG, // [Toon][Modified end] @cc5568135 Last modified 2025/05/08 out float4 OutGBufferVelocity, ``` *裡面的內容,再UE5已由自動生成的Code替代。所以可以不用管。* ```cpp if (GBuffer.ShadingModelID == SHADINGMODELID_UNLIT) { OutGBufferA = 0; SetGBufferForUnlit(OutGBufferB); OutGBufferC = 0; OutGBufferD = 0; OutGBufferE = 0; // [Toon][Modified begin] @cc5568135 OutGBufferG = 0; // [Toon][Modified end] @cc5568135 Last modified 2025/05/09 ... OutGBufferE = GBuffer.PrecomputedShadowFactors; // [Toon][Modified begin] @cc5568135 if (GBuffer.ShadingModelID != SHADINGMODELID_TOON) { OutGBufferG = 0; } else { OutGBufferG.rgb = GBuffer.ShadowColor.rgb; OutGBufferG.a = GBuffer.FaceForwardVector.z; } // [Toon][Modified end] @cc5568135 Last modified 2025/05/08 ``` 擴充`DecodeGBufferData`,如有新增GBuffer Slot 可以自行調整內容。 *裡面的內容,再UE5已由自動生成的Code替代。所以可以不用管。* ```cpp float4 InGBufferF, // [Toon][Modified begin] @cc5568135 float4 InGBufferG, // [Toon][Modified end] @cc5568135 Last modified 2025/05/08 float4 InGBufferVelocity, ``` ```cpp GBuffer.BaseColor = DecodeBaseColor(InGBufferC.rgb); // [Toon][Modified begin] @cc5568135 GBuffer.ShadowColor = 0; ... // [Toon][Modified end] @cc5568135 Last modified 2025/05/05 ``` 修改`return DecodeGBufferData`符合新input格式,有3處。 ```cpp float SceneDepth = CalcSceneDepth(PixelPos); // [Toon][Modified begin] @cc5568135 float4 GBufferG = SceneTexturesStruct.GBufferGTexture.Load(int3(PixelPos, 0)); //return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferF, GBufferVelocity, CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromPixelPos(PixelPos)); return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferF, GBufferG, GBufferVelocity, CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromPixelPos(PixelPos)); // [Toon][Modified end] @cc5568135 Last modified 2025/05/08 ``` ```cpp float4 GBufferF = GBufferFTexture.SampleLevel(GBufferFTextureSampler, UV, 0); // [Toon][Modified begin] @cc5568135 float4 GBufferG = GBufferGTexture.SampleLevel(GBufferGTextureSampler, UV, 0); // [Toon][Modified end] @cc5568135 Last modified 2025/05/08 ... float DeviceZ = SampleDeviceZFromSceneTextures(UV); float SceneDepth = ConvertFromDeviceZ(DeviceZ); // [Toon][Modified begin] @cc5568135 // return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferF, GBufferVelocity, CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromSceneColorUV(UV)); return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferF, GBufferG, GBufferVelocity, CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromSceneColorUV(UV)); // [Toon][Modified end] @cc5568135 Last modified 2025/05/08 ``` ```cpp float SceneDepth = CalcSceneDepth(UV); // [Toon][Modified begin] @cc5568135 float4 GBufferG = Texture2DSampleLevel(SceneTexturesStruct.GBufferGTexture, SceneTexturesStruct_GBufferGTextureSampler, UV, 0); // return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferF, GBufferVelocity, CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromSceneColorUV(UV)); return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferF, GBufferG, GBufferVelocity, CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromSceneColorUV(UV)); // [Toon][Modified end] @cc5568135 Last modified 2025/05/08 ``` ## BasePassPixelShader.usf Path: `Shaders/Private/BasePassPixelShader.usf` 擴充`FPixelShaderInOut_MainPS` ```cpp // 0..1, SubsurfaceProfileId = int(x * 255) float SubsurfaceProfile = 0; // [Toon][Add-Begin] @cc5568135 - Toon float3 ShadowColor = GetMaterialShadowColor(PixelMaterialInputs); float3 FaceForwardVector = GetMaterialFaceForwardVector(PixelMaterialInputs); // [Toon][Add-End] @cc5568135 2024/10/26 ``` 擴充`SetGBufferForShadingModel` 這裡設定來自Material系統的參數數值,要插入的Gbuffer slot位置。 ```cpp Dither, // [Toon][Add-Begin] @cc5568135 - Toon ShadowColor, FaceForwardVector, // [Toon][Add-End] @cc5568135 2024/10/26 ShadingModel ); ``` 在設定 Out.MRT 之前,替換 GBuffer 參數位置。 ```cpp #if USES_GBUFFER // -0.5 .. 0.5, could be optimzed as lower quality noise would be sufficient float QuantizationBias = PseudoRandom( MaterialParameters.SvPosition.xy ) - 0.5f; GBuffer.IndirectIrradiance = IndirectIrradiance; // [Toon][Modified begin] @cc5568135 #if MATERIAL_SHADINGMODEL_TOON if (GBuffer.ShadingModelID == SHADINGMODELID_TOON) { GBuffer.CustomData.rgb = GBuffer.FaceShadowTexture.rgb; GBuffer.PrecomputedShadowFactors.rg = GBuffer.FaceForwardVector.xy; GBuffer.PrecomputedShadowFactors.ba = GBuffer.FaceRightwardVector.xy; GBuffer.ShadowColor.rgb = GBuffer.ShadowColor.rgb; } #endif // [Toon][Modified end] @cc5568135 Last modified 2025/05/09 ``` 若有擴充 GBuffer slot, 新增 `GBufferG` 相關 ```cpp // PreShadowFactor float4 OutGBufferE = 0; // [Toon][Modified begin] @cc5568135 float4 OutGBufferG = 0; // [Toon][Modified end] @cc5568135 Last modified 2025/05/09 ... float4 OutGBufferB = 0; float4 OutGBufferC = 0; // [Toon][Modified begin] @cc5568135 //EncodeGBuffer(GBuffer, OutGBufferA, OutGBufferB, OutGBufferC, OutGBufferD, OutGBufferE, OutVelocity, QuantizationBias); float4 OutGBufferG = 0; EncodeGBuffer(GBuffer, OutGBufferA, OutGBufferB, OutGBufferC, OutGBufferD, OutGBufferE, OutGBufferG, OutVelocity, QuantizationBias); // [Toon][Modified end] @cc5568135 Last modified 2025/05/09 ... #if GBUFFER_HAS_PRECSHADOWFACTOR Out.MRT[GBUFFER_HAS_VELOCITY ? 6 : 5] = OutGBufferE; #endif // [Toon][Modified begin] @cc5568135 Out.MRT[6] = OutGBufferG; // [Toon][Modified end] @cc5568135 Last modified 2025/05/09 ``` ## ShaderOutputCommon.ush Path`Shaders\Private\ShaderOutputCommon.ush` 如有新增GBuffer Slot,新增`PIXELSHADEROUTPUT_MRT8`定義 ```cpp #ifndef PIXELSHADEROUTPUT_MRT7 #define PIXELSHADEROUTPUT_MRT7 0 #endif // [Toon][Modified begin] @cc5568135 #ifndef PIXELSHADEROUTPUT_MRT8 #define PIXELSHADEROUTPUT_MRT8 0 #endif // [Toon][Modified end] @cc5568135 Last modified 2025/05/08 ``` ## PixelShaderOutputCommon.ush Path `Shaders\Private\PixelShaderOutputCommon.ush` 如有新增GBuffer Slot,新增 `OutTarget8` ```cpp #if PIXELSHADEROUTPUT_MRT7 , out float4 OutTarget7 : SV_Target7 #endif // [Toon][Modified begin] @cc5568135 #if PIXELSHADEROUTPUT_MRT8 , out float4 OutTarget8 : SV_Target8 #endif // [Toon][Modified end] @cc5568135 Last modified 2025/05/09 ... #if PIXELSHADEROUTPUT_MRT7 OutTarget7 = PixelShaderOut.MRT[7]; #endif // [Toon][Modified begin] @cc5568135 #if PIXELSHADEROUTPUT_MRT8 OutTarget8 = PixelShaderOut.MRT[8]; #endif // [Toon][Modified end] @cc5568135 Last modified 2025/05/09 ``` ## SSDCommon.ush Path `Shaders\Private\ScreenSpaceDenoise\SSDCommon.ush` 如有新增GBuffer Slot,新增 `GBufferG` 參數並修改 `DecodeGBufferData` ```cpp float4 GBufferF = 0.5f; // [Toon][Modified begin] @cc5568135 float4 GBufferG = 0.0; // [Toon][Modified end] @cc5568135 Last modified 2025/05/09 float4 GBufferVelocity = 0.0; ... // [Toon][Modified begin] @cc5568135 //GBufferData = DecodeGBufferData( // GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferF, GBufferVelocity, // CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromSceneColorUV(BufferUV)); GBufferData = DecodeGBufferData( GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferF, GBufferG, GBufferVelocity, CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromSceneColorUV(BufferUV)); // [Toon][Modified end] @cc5568135 Last modified 2025/05/09 ``` ## ShadingModelsMaterial.ush Path: `Shaders/Private/ShadingModelsMaterial.ush` 這個Function可以修改GBuffer對每個MSM的數值。 擴充`SetGBufferForShadingModel`, Inputs & 後方要設定GBuffer。 ```cpp ... const float Dither, // [Toon][Add-Begin] @cc5568135 - Toon const float3 ShadowColor, const float3 FaceForwardVector, // [Toon][Add-End] @cc5568135 2024/10/26 const uint ShadingModel) ... // [Toon][Modified begin] @cc5568135 #if MATERIAL_SHADINGMODEL_TOON else if (ShadingModel == SHADINGMODELID_TOON){ GBuffer.ShadowColor = ShadowColor; GBuffer.FaceForwardVector = FaceForwardVector; } #endif // [Toon][Modified end] @cc5568135 Last modified 2025/05/03 #if MATERIAL_SHADINGMODEL_EYE ``` ## GBufferHelpers.ush GBufferPostDecode 可以修改gbuffer後解碼的內容 ## ShadingModels.ush Path: `Shaders/Private/ShadingModels.ush` 在這裡可以調整或是新增BxDF 修改`IntegrateBxDF`設定新MSM跑自訂的BxDF ```cpp ... case SHADINGMODELID_EYE: return EyeBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); // [Toon][Add-Begin] @cc5568135 - Toon case SHADINGMODELID_TOON: return ToonBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); // [Toon][Add-End] @cc5568135 2024/10/26 default: return (FDirectLighting)0; ... ``` ## RayTracingDeferredShadingCommon.ush Path `Shaders\Private\RayTracing\RayTracingDeferredShadingCommon.ush` 如有新增GBuffer Slot,修改`GetGBufferDataFromSceneTexturesLoad`內容。 ```cpp float4 GBufferF = GBufferFTexture.Load(int3(PixelCoord, 0)); // [Toon][Modified begin] @cc5568135 float4 GBufferG = GBufferGTexture.Load(int3(PixelCoord, 0)); // [Toon][Modified end] @cc5568135 Last modified 2025/05/09 ... // [Toon][Modified begin] @cc5568135 // return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferF, GBufferVelocity, CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromPixelPos(PixelCoord)); return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferF, GBufferG, GBufferVelocity, CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromPixelPos(PixelCoord)); // [Toon][Modified end] @cc5568135 Last modified 2025/05/09 ``` ## ShadingModelsSampling.ush Path: `Engine/Shaders/Private/ShadingModelsSampling.ush` Path tracing & Ray tracing sampling相關, 例如計算取樣的PDF等 可以不用加東西 ## ReflectionEnvironmentPixelShader.usf `Shaders/Private/ReflectionEnvironmentPixelShader.usf` 可在這裡調整各個MSM的反射Function。 例如Toon不要有反射: ```cpp // [Toon][Modify-Begin] @cc5568135 - No Reflection for Toon //const bool bUnlitMaterial = ShadingModelID == SHADINGMODELID_UNLIT; const bool bUnlitMaterial = ShadingModelID == SHADINGMODELID_UNLIT || ShadingModelID == SHADINGMODELID_TOON; // [Toon][Modify-End] @cc5568135 2024/10/24 ``` ## ClusteredDeferredShadingPixelShader.usf Path: `Engine/Shaders/Private/ClusteredDeferredShadingPixelShader.usf` 擴充`#if USE_PASS_PER_SHADING_MODEL`下面內容 ```cpp // [Toon][Modified begin] @cc5568135 GET_LIGHT_GRID_LOCAL_LIGHTING_SINGLE_SM(SHADINGMODELID_TOON, PixelShadingModelID, CompositedLighting, ScreenUV, CulledLightGridHeader, Dither, FirstNonSimpleLightIndex); // [Toon][Modified end] @cc5568135 Last modified 2025/05/03 ``` ## DeferredLightingCommon.ush 修改`GetDynamicLightingSplit`可以讓不同SM用不同的光照Function ```cpp // [Toon][Modify-Add] @cc5568135 - Toon if (GBuffer.ShadingModelID == SHADINGMODELID_TOON) { FLightAccumulator LightAccumulator = AccumulateToonLighting(TranslatedWorldPosition, CameraVector, GBuffer, AmbientOcclusion, LightData, LightAttenuation, Dither, SVPos, SurfaceShadow); return LightAccumulator_GetResultSplit(LightAccumulator); } // [Toon][Modify-End] @cc5568135 2024/10/28 FLightAccumulator LightAccumulator = AccumulateDynamicLighting(TranslatedWorldPosition, CameraVector, GBuffer, AmbientOcclusion, LightData, LightAttenuation, Dither, SVPos, SurfaceShadow); return LightAccumulator_GetResultSplit(LightAccumulator); ``` ## TODO Lumen & PT & others `Engine/Shaders/Private/Lumen/LumenMaterial.ush` `Engine/Shaders/Private/PathTracing/...` `Engine\Shaders\Private\RayTracing\...` # 其他 ## Enable ShaderDevelopmentMode 在`...\Engine\Config\ConsoleVariables.ini`檔案中可以啟用`r.ShaderDevelopmentMode=1`。 啟用後在Compile shader階段引擎會顯示詳細error資訊,幫助開發Unreal shader。 ```ini ; Uncomment to get detailed logs on shader compiles and the opportunity to retry on errors, and enable showing shader warnings r.ShaderDevelopmentMode=1 ``` `r.DumpShaderDebugInfo`可以調整Dump shaders 內容 預設狀況下,有問題的.ush .usf 會自訂複製一份到 `\Saved\ShaderDebugInfo\PCD3D_SM6` (Engine 或 Project都會有),不過不會自動刪除,記得手動去刪掉避免因為歷史紀錄而誤判。 --- --- # References UE5でつくるセルシェーディング 第4-6回 https://cgworld.jp/regular/unreal_engine/ 【UE5 渲染管线篇】素描风格渲染管线实现:(2)添加光照模型与材质接口 https://zhuanlan.zhihu.com/p/680177835 UE5新增Toon管线实践 https://zhuanlan.zhihu.com/p/647312365 Adding a new Shading Model in Unreal5 https://neozheng.cn/2022/08/14/Adding%20a%20new%20Shading%20Model/ [写一个自己的移动端shading model!](https://blog.csdn.net/weixin_43369654/article/details/116149833?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-8-116149833-blog-82990302.235^v43^pc_blog_bottom_relevance_base7&spm=1001.2101.3001.4242.5&utm_relevant_index=11)