Tien-Yi
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.

      Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Explore these features while you wait
      Complete general settings
      Bookmark and like published notes
      Write a few more notes
      Complete general settings
      Write a few more notes
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    *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 ``` 擴充 `HasXXXXConnected` functions ```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 ``` 必要時調整`DecalCommonOutput`之下 `EncodeGBuffer` 部分 ``` // [Toon][Modified begin] @cc5568135 #if DECAL_RENDERTARGETMODE == DECAL_RENDERTARGETMODE_GBUFFER { EncodeGBuffer(Data, Out.MRT[1], Out.MRT[2], Out.MRT[3], OutTarget4, OutTarget5, OutTarget6, OutTarget7); } #elif DECAL_RENDERTARGETMODE == DECAL_RENDERTARGETMODE_GBUFFER_NONORMAL { EncodeGBuffer(Data, OutTarget1, Out.MRT[1], Out.MRT[2], OutTarget4, OutTarget5, OutTarget6, OutTarget7); } #endif // DECAL_RENDERTARGETMODE // [Toon][Modified end] @cc5568135 ``` ## 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)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Google Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully