Keywords: UE4, Shader Development Notes

Environment Setup

Steps
  1. Set LoadingPhase as PostConfigInit, default is Default.
    e.g. TestProj.uproject:

     {
         "FileVersion": 3,
         "EngineAssociation": "4.25",
         "Category": "",
         "Description": "",
         "Modules": [
             {
                 "Name": "TestProj",
                 "Type": "Runtime",
                 "LoadingPhase": "PostConfigInit"
             }
         ]
     }
    

    Otherwise there’s error on building:

     Shader type was loaded after engine init, use ELoadingPhase::PostConfigInit on your module to cause it to load earlier.
    
  1. Turn on r.ShaderDevelopmentMode in \Engine\Config\ConsoleVariables.ini.
    ConsoleVariables.ini:

     [Startup]
     ; Uncomment to get detailed logs on shader compiles and the opportunity to retry on errors
     r.ShaderDevelopmentMode=1
    

    Otherwise there’s error on building:

     Failed to compile global shader XXXX. Enable `r.ShaderDevelopmentMode` in ConsoleVariables.ini for retries.
    
  1. Add RenderCore, Renderer in your .Build.cs. Maybe RHI is also need to be added.

     PublicDependencyModuleNames.AddRange(new string[] { "RenderCore", "Renderer", "RHI" });
    
  2. Now you can setup your shader source in your game source, and these shader would be compiled on editor starting.
    MyActor.cpp (example code were quoted from Engine\Source\Runtime\Renderer\Private\PostProcess\PostProcessVisualizeBuffer.cpp):

     namespace
     {
         class FVisualizeBufferPS : public FGlobalShader
         {
         public:
             DECLARE_GLOBAL_SHADER(FVisualizeBufferPS);
             SHADER_USE_PARAMETER_STRUCT(FVisualizeBufferPS, FGlobalShader);
    
             BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
                 SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, Output)
                 SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InputTexture)
                 SHADER_PARAMETER_SAMPLER(SamplerState, InputSampler)
                 SHADER_PARAMETER(FLinearColor, SelectionColor)
                 RENDER_TARGET_BINDING_SLOTS()
             END_SHADER_PARAMETER_STRUCT()
    
             static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
             {
                 return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::ES3_1);
             }
         };
    
         IMPLEMENT_GLOBAL_SHADER(FVisualizeBufferPS, "/Engine/Private/PostProcessVisualizeBuffer.usf", "MainPS", SF_Pixel);
    
         FScreenPassTexture AddVisualizeBufferPass(FRDGBuilder& GraphBuilder, const FViewInfo& View, const FVisualizeBufferInputs& Inputs)
         {
             ...
             FVisualizeBufferPS::FParameters* PassParameters = GraphBuilder.AllocParameters<FVisualizeBufferPS::FParameters>();
             PassParameters->Output = GetScreenPassTextureViewportParameters(OutputViewport);
             PassParameters->RenderTargets[0] = Output.GetRenderTargetBinding();
             PassParameters->InputTexture = Tile.Input.Texture;
             PassParameters->InputSampler = BilinearClampSampler;
             PassParameters->SelectionColor = SelectionColor;
                
             TShaderMapRef<FVisualizeBufferPS> PixelShader(View.ShaderMap);
             ...
         }
            
         void Test_RenderThread(FRHICommandListImmediate& RHICmdList)
         {
             ...
             TShaderMapRef<FDownsamplePS> PixelShader(ShaderMap, PermutationVector);
             ...
         }
     }
        
     AMyActor::TestFun()
     {
         ENQUEUE_RENDER_COMMAND(FDownsampleTestCommand)(
         [](FRHICommandListImmediate& RHICmdList)
         {
             Test_RenderThread(RHICmdList);
         });
     }
    

Reference

Examples

A tutorial project that shows how to implement HLSL Pixel and Compute shaders in UE4
https://github.com/Temaran/UE4ShaderPluginDemo

A compute shader plugin that is capable of sorting positional data in parallel directly on the GPU.
https://github.com/ValentinKraft/UE4_SortingComputeShader


Business has only two functions — marketing and innovation. ― Peter Drucker