Overriding Unreal Engine Shaders in Local Project or Plugin

I originally posted this on the Unreal Engine forums, but I’m going to post it here as well just in case.

So, I’ve been looking for an answer to locally overriding engine shaders for a while. I found a solution that works, but I’d like to find a better one. Here’s how I did it on my end.

In my case I wanted to test by overriding the MobileFog.usf file from the engine’s Shaders/Private folder. So, I tricked the engine by virtually mapping the private subfolder like so. You can do this in a plugin or in a project level module.

void FCustomShadersModule::StartupModule()
{
  FString BaseDir = FPaths::Combine(FPaths::GameSourceDir(), TEXT("CustomShadersModule));
  FString ModuleShaderDir = FPaths::Combine(BaseDir, TEXT("Shaders"));
  AddShaderSourceDirectoryMapping(TEXT("/Engine/Private"), ModuleShaderDir);
};

void FCustomShadersModule::ShutdownModule()
{
  ResetAllShaderSourceDirectoryMappings();
};

After doing this, the engine couldn’t find any other files in the directory, so I ended up having to copy the entire private folder into my module / plugin and not just the single file.

The module also needs to be set to PostConfigInit.

{
        "Name": "CustomShadersModule",
        "Type": "Runtime",
        "LoadingPhase": "PostConfigInit",
        "AdditionalDependencies": [
            "Engine"
        ]
}

Everything else is common sense build.cs and includes.


It would be great to find a way to get the file system to override a single file locally.
I feel like I might find answers by digging into this macro.

IMPLEMENT_SHADER_TYPE(, FCombineShaderPS, TEXT("/Engine/Private/MyShaders.usf"), TEXT("CombineMainPS"), SF_Pixel);
IMPLEMENT_SHADER_TYPE(, FUVMaskShaderPS, TEXT("/Engine/Private/MyShaders.usf"), TEXT("UVMaskMainPS"), SF_Pixel);

Otherwise, I’ve been digging into FShaderType::GetTypeList()" which returns a linked list you can itterate and which you can call:

 // Create permutation parameters, using android example
     FShaderPermutationParameters Parameters(EShaderPlatform::SP_VULKAN_ES3_1_ANDROID);
     FShaderCompilerEnvironment OutEnvironment;
     ShaderType->ModifyCompilationEnvironment(Parameters, OutEnvironment);
 // Now add your custom modification to the environment
     OutEnvironment.SetDefine(TEXT("CUSTOM_SHADER_PATH"), *CustomShaderFilePath);

I have not figured out the right way to work with this data. It seems most of these are now wrapped with getters and have no settings. GPT suggests static linking a new global shader instead.

Leave a Reply