Hi there, I’ve tried to add a global shader and use it.
I know the official documents are out of date for a long time so I’ve also modified the codes as following:
First, it’s a Render function in deferred shading scene renderer.
It’s called before RenderFinish() in DeferredShadingRenderer.cpp
void FDeferredShadingSceneRenderer::RenderSceneInverse(FRHICommandList& RHICmdList)
{
// Get the collection of Global Shaders
auto ShaderMap = GetGlobalShaderMap(FeatureLevel);
// Get the actual shader instances off the ShaderMap
TShaderMapRef<FSceneInverseVS> SceneInverseVS(ShaderMap);
TShaderMapRef<FSceneInversePS> SceneInversePS(ShaderMap);
// Declare a bound shader state using those shaders and apply it to the command list
FGraphicsPipelineStateInitializer GraphicsPSOInitializer;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInitializer);
GraphicsPSOInitializer.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
GraphicsPSOInitializer.BlendState = TStaticBlendState<>::GetRHI();
GraphicsPSOInitializer.RasterizerState = TStaticRasterizerState<>::GetRHI();
GraphicsPSOInitializer.PrimitiveType = PT_TriangleStrip;
GraphicsPSOInitializer.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInitializer.BoundShaderState.VertexShaderRHI = SceneInverseVS.GetVertexShader();
GraphicsPSOInitializer.BoundShaderState.PixelShaderRHI = SceneInversePS.GetPixelShader();
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInitializer);
// create vertex buffer
FRHIResourceCreateInfo CreateInfo;
FVertexBufferRHIRef VertexBufferRHI = RHICreateVertexBuffer(sizeof(FFilterVertex) * 4, BUF_Volatile, CreateInfo);
void* VoidPtr = RHILockVertexBuffer(VertexBufferRHI, 0, sizeof(FFilterVertex) * 4, RLM_WriteOnly);
FFilterVertex* Vertices = (FFilterVertex*)VoidPtr;
Vertices[0].Position = FVector4(-1.0f, 1.0f, 0, 1.0f);
Vertices[1].Position = FVector4(1.0f, 1.0f, 0, 1.0f);
Vertices[2].Position = FVector4(-1.0f, -1.0f, 0, 1.0f);
Vertices[3].Position = FVector4(1.0f, -1.0f, 0, 1.0f);
Vertices[0].UV = FVector2D(0, 0);
Vertices[1].UV = FVector2D(1, 0);
Vertices[2].UV = FVector2D(0, 1);
Vertices[3].UV = FVector2D(1, 1);
RHIUnlockVertexBuffer(VertexBufferRHI);
RHICmdList.SetStreamSource(0, VertexBufferRHI, 0);
RHICmdList.DrawPrimitive(0, 2, 1);
}
As we can see, pipeline and shader should be set properly.
The shader code and shader class are shown as below:
#include "/Engine/Public/Platform.ush"
// Simple pass-through vertex shader
void MainVS(
in float4 InPosition : ATTRIBUTE0,
out float4 Output : SV_POSITION
)
{
Output = InPosition;
}
// Simple solid color pixel shader
float4 MainPS() : SV_Target0
{
return float4(1,1,0,1);
}
Just a simple yellow output shader.
In header:
#pragma once
#include "GlobalShader.h"
class FSceneInverseVS : public FGlobalShader
{
public:
DECLARE_EXPORTED_SHADER_TYPE(FSceneInverseVS, Global, /*MYMODULE_API*/);
FSceneInverseVS() { }
FSceneInverseVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
}
static bool ShouldCache(EShaderPlatform Platform)
{
return true;
}
};
class FSceneInversePS : public FGlobalShader
{
DECLARE_EXPORTED_SHADER_TYPE(FSceneInversePS, Global, /*MYMODULE_API*/);
FSceneInversePS() { }
FSceneInversePS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
}
static bool ShouldCache(EShaderPlatform Platform)
{
// Could skip compiling for Platform == SP_METAL for example
return true;
}
};
And in cpp:
#include "SceneInverse.h"
IMPLEMENT_SHADER_TYPE(, FSceneInverseVS, TEXT("/Engine/SceneInverse.usf"), TEXT("MainVS"), SF_Vertex);
IMPLEMENT_SHADER_TYPE(, FSceneInversePS, TEXT("/Engine/SceneInverse.usf"), TEXT("MainPS"), SF_Pixel);
Am I missing anything here?
Thanks!