Why

在原生的 DirectX 开发中,想要给 Shader 传递数据,通常需要使用常量数据 (Constant Buffer / cbuffer)资源绑定 (SRV / UAV / Sampler),它们的无论在定义阶段还是使用阶段都十分繁琐,为此,虚幻引擎封装了Shader Parameter Struct

What

Shader Parameter Struct 是虚幻引擎中用于在 CPU(C++ 端)GPU(Shader 端 / USF) 之间传递数据的标准化数据结构。 它通过一组特定的 C++ 宏来定义。这套宏在底层通过编译期元编程,为原本不支持反射的 C++ 结构体生成了静态反射信息(包括变量名、数据类型、内存偏移量等)。

CPP
// 声明一个简单的 Shader 参数结构体
BEGIN_SHADER_PARAMETER_STRUCT(结构体名, )
    // 普通数据
    SHADER_PARAMETER(数据类型, 参数名称)
    
    // RDG 资源 (比如一张输入的贴图和它的采样器)
    SHADER_PARAMETER_RDG_TEXTURE(纹理类型, 参数名称)
    SHADER_PARAMETER_SAMPLER(采样器类型, 参数名称)
    
    // 输出目标 (Render Target)
    RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
点击展开查看更多

只需要写简单的几行代码,宏在背后就帮你把严格的内存对齐、编译期防呆检查、以及运行时需要的内存布局信息全部打理好了。

How

Unreal Shader File (.usf)

HLSL
// 这些变量名必须和 C++ 中宏定义的名字一模一样
float4 TintColor;
float  Intensity;

Texture2D MyInputTexture;
SamplerState MyTextureSampler;

void MainPS(
    in float2 UV : TEXCOORD0,
    out float4 OutColor : SV_Target0)
{
    float4 TexColor = MyInputTexture.Sample(MyTextureSampler, UV);
    OutColor = TexColor * TintColor * Intensity;
}
点击展开查看更多

相应的C++定义

CPP
BEGIN_SHADER_PARAMETER_STRUCT(FMyTestShaderParameters, )
    SHADER_PARAMETER(FVector4f, TintColor)
    SHADER_PARAMETER(float,     Intensity)
    
    SHADER_PARAMETER_RDG_TEXTURE(Texture2D, MyInputTexture)
    SHADER_PARAMETER_SAMPLER(SamplerState,  MyTextureSampler)
    
    RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
点击展开查看更多

创建并填充数据

CPP
// 1. 获取图构建器
FRDGBuilder& GraphBuilder = ...; 

// 2. 分配参数结构体的内存 (必须通过 RDG 分配,不能在栈上自己 new)
FMyTestShaderParameters* PassParameters = GraphBuilder.AllocParameters<FMyTestShaderParameters>();

// 3. 填充数据
PassParameters->TintColor = FVector4f(1.0f, 0.5f, 0.2f, 1.0f);
PassParameters->Intensity = 2.0f;
PassParameters->MyInputTexture = SomeRDGTexture; // 传入你的 RDG 贴图
PassParameters->MyTextureSampler = TStaticSamplerState<SF_Bilinear>::GetRHI();
PassParameters->RenderTargets[0] = FRenderTargetBinding(OutputTexture, ERenderTargetLoadAction::EClear);
点击展开查看更多

More

常量数据

这类宏用于传递基础的数值型数据(如标量、向量、矩阵)。在 DirectX 中,UE 会自动将结构体中所有的这些普通参数打包成一个 Constant Buffer(常量缓冲区,CBV)

UE 宏定义 对应的 DirectX / HLSL 概念
SHADER_PARAMETER(Type, Name) Constant Buffer (cbuffer) 中的变量。
SHADER_PARAMETER_ARRAY(Type, Name, Size) Constant Buffer 中的定长数组。

着色器资源视图 (SRV - Shader Resource View)

这类宏用于绑定着色器中只读的资源(贴图、结构化缓冲区等)。

UE 宏定义 对应的 DirectX / HLSL 概念 补充说明
SHADER_PARAMETER_TEXTURE(Type, Name) SRV (Texture2D, Texture3D 等) 非 RDG 管理的常规贴图(通常是常驻内存的全局贴图)。
SHADER_PARAMETER_SRV(Type, Name) SRV (StructuredBuffer, ByteAddressBuffer) 非 RDG 管理的只读 Buffer。
SHADER_PARAMETER_RDG_TEXTURE(Type, Name) SRV (Texture2D 等) RDG 托管 的贴图。DirectX 层面与普通 SRV 无异,但 C++ 侧 RDG 会自动处理同步、内存复用和资源屏障(Resource Barrier)。
SHADER_PARAMETER_RDG_BUFFER_SRV(Type, Name) SRV (StructuredBuffer 等) RDG 托管 的只读 Buffer。
SHADER_PARAMETER_RDG_TEXTURE_SRV(Type, Name) SRV (Texture2D 等) 显式绑定一个 RDG 贴图的特定 SRV(比如只读取贴图的某一个 Mip 层)。

无序访问视图 (UAV - Unordered Access View)

这类宏用于绑定着色器中可读可写的资源。通常用于 Compute Shader 或 Pixel Shader 中的写入操作。

UE 宏定义 对应的 DirectX / HLSL 概念 补充说明
SHADER_PARAMETER_UAV(Type, Name) UAV (RWTexture2D, RWStructuredBuffer) 非 RDG 管理的读写资源。
SHADER_PARAMETER_RDG_BUFFER_UAV(Type, Name) UAV (RWStructuredBuffer 等) RDG 托管 的可读写 Buffer。在 Compute Shader 计算完后,RDG 会自动插入屏障以供后续阶段使用。
SHADER_PARAMETER_RDG_TEXTURE_UAV(Type, Name) UAV (RWTexture2D 等) RDG 托管 的可读写贴图。

采样器 (Samplers)

用于贴图采样的状态配置(过滤模式、寻址模式等)。

UE 宏定义 对应的 DirectX / HLSL 概念
SHADER_PARAMETER_SAMPLER(Type, Name) SamplerState。映射到 DirectX 的采样器状态对象(Sampler State Object)。

嵌套结构体与 Uniform Buffers

用于将其他数据块复用到当前的参数结构体中。

UE 宏定义 对应的 DirectX / HLSL 概念
SHADER_PARAMETER_STRUCT(Type, Name) 将另一个结构体的参数**内联(Inline)**到当前的 Constant Buffer 中。
SHADER_PARAMETER_STRUCT_REF(Type, Name) 绑定到一个外部独立的 Constant Buffer View (CBV),而不是将数据拷贝进来。
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(Type, Name) CBV。绑定一个 RDG 生命周期管理的 Uniform Buffer (Constant Buffer)。

渲染目标 (Render Targets)

这是 RDG 特有的宏,不对应 HLSL 代码中的变量,而是对应图形渲染管线的输出合并阶段(Output Merger Stage)

UE 宏定义 对应的 DirectX 概念
RENDER_TARGET_BINDING_SLOTS() 映射到 DirectX 的 RTV (Render Target View)DSV (Depth Stencil View)。在 C++ 层配置渲染通道时,告诉管线像素着色器的输出应该写到哪些缓冲(Color Buffer / Depth Buffer)中。

版权声明

作者: Cheyne Xie

链接: https://chaim.eu.org/posts/49bfcff8/

许可证: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.

开始搜索

输入关键词搜索文章内容

↑↓
ESC
⌘K 快捷键