注意
Global Shader 是一种不依赖材质系统的底层 GPU 程序,用于实现与具体材质或网格无关的渲染 Pass。 与 Material Shader 不同,Global Shader 不自动绑定场景数据或渲染状态,需要在 C++ 中手动组织资源和调度渲染。但这也使其更加灵活,适用于实现自定义渲染管线、GPU计算以及引擎级渲染功能。
提示
如果需要 Global Shader 进行依赖大量现有的场景上下文的复杂渲染,则应当插入 render pipeline 中以获取场景上下文,而非自行组织数据。
小心
截至 UE 5.7,官方文档中的 Global Shader 相关内容仍是 UE4 时代的写法,建议直接参考引擎源码,而非官方文档。(/Engine/Source/Runtime/Renderer/Private)
修改配置
修改 LoadingPhase
打开你的 .uproject(或 .uplugin)文件,将 Modules 的 "LoadingPhase" 改为 "PostConfigInit"
添加依赖
/Source/<ProjectName>/<ProjectName>.Build.cs中的PublicDependencyModuleNames添加:RenderCoreRendererRHI
- 关闭IDE,右键
<ProjectName>.uproject,执行Generate Visual Studio project files
创建 USF
在对应位置创建 .usf 文件并写入 HLSL 代码。
注意需要包含#include "/Engine/Public/Platform.ush"。
Shader 文件路径
虚幻着色器文件(Unreal Shader) .usf 文件存储在 <引擎安装目录>/Engine/Shaders 文件夹中。这有个致命缺点:不方便版本管理和迁移,这里有两个办法解决这个问题:
- 创建插件:将着色器作为插件的一部分,可将其存储在
Plugin/Shaders。 - 使用路径映射:
在C++中是声明并关联
- 引入必要的头文件,
#include "CoreMinimal.h"
#include "GlobalShader.h"
#include "ShaderParameterStruct.h"- 声明 Shader Parameter Struct,在
.h中,
BEGIN_SHADER_PARAMETER_STRUCT(FMyTestShaderParameters, )
// 各种参数
SHADER_PARAMETER...
END_SHADER_PARAMETER_STRUCT()更多信息
- 声明 C++ 类,在
.h中,
class FMyTestShaderPS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FMyTestShaderPS);
SHADER_USE_PARAMETER_STRUCT(FMyTestShaderPS, FGlobalShader);
using FParameters = FMyTestShaderParameters; // 上面声明的Shader Parameter Struct
};- C++类关联 USF,在
.cpp中,
IMPLEMENT_GLOBAL_SHADER(
FMyTestShaderPS,
"USF 文件路径",
"函数名", // MainVS、MainPS、MainCS等
SF_Pixel
);使用 RDG 渲染
- 获取 Shader 实例
TShaderMapRef<FMyTestShaderPS> MyTestShader(GetGlobalShaderMap(GMaxRHIFeatureLevel));- 分配并填充Shader Parameter Struct
// 分配
FMyTestShaderParameters* PassParameters = GraphBuilder.AllocParameters<FMyTestShaderParameters>();
// 填充
PassParameters->XXX = ...参考
- 将 Pass 添加到 RDG 中
// 全屏像素着色器(用于后处理)
FPixelShaderUtils::AddFullscreenPass(
GraphBuilder,
GetGlobalShaderMap(GMaxRHIFeatureLevel),
FRDGEventName(TEXT("MyTestShaderPass")), // 在 GPU 抓帧工具中显示的名字
MyTestShader,
PassParameters,
FIntRect(FIntPoint::ZeroValue, OutputTexture->Desc.Extent) // 渲染区域(全屏)
);
// 计算着色器 Compute Shader
FComputeShaderUtils::AddPass(
GraphBuilder,
FRDGEventName(TEXT("MyTestShaderPass")), // 在 GPU 抓帧工具中显示的名字
MyTestShader,
PassParameters,
GroupCount // 线程组的数量(FIntVector类型)
);