You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UE5.5正向渲染:如何扩展HLSL自定义节点实现方向光阴影采样

解决UE5.5材质自定义HLSL节点访问Uniform结构体的问题

以下是针对你的需求,一步步实现可被材质自定义HLSL节点访问的Uniform结构体的具体操作:

1. 用引擎宏正确定义并注册Uniform Buffer结构体

你之前仅在HLSL中定义结构体是不够的,必须在C++层面用UE的UBO宏声明并注册,才能让引擎生成正确的绑定代码。

比如在Engine/Source/Runtime/Engine/Public/MaterialShared.h(或自定义的头文件)中添加:

BEGIN_UNIFORM_BUFFER_STRUCT(FMaterialAccessibleShadowData, ENGINE_API)
    DECLARE_UNIFORM_BUFFER_STRUCT_MEMBER_ARRAY(FMatrix, CascadeViewProjMatrices, [4]) // 按实际级联数调整
    DECLARE_UNIFORM_BUFFER_STRUCT_MEMBER(FVector, LightWorldDirection)
    DECLARE_UNIFORM_BUFFER_STRUCT_MEMBER(FTexture2DArray*, DirectionalShadowAtlas)
    DECLARE_UNIFORM_BUFFER_STRUCT_MEMBER(FVector4, CascadeSplitDistances)
END_UNIFORM_BUFFER_STRUCT(FMaterialAccessibleShadowData)

// 在模块启动代码中注册UBO,比如Engine模块的StartupModule里
IMPLEMENT_UNIFORM_BUFFER_STRUCT(FMaterialAccessibleShadowData, TEXT("/Engine/Generated/UniformBuffers/MaterialAccessibleShadowData"))

这样引擎会自动生成对应的.ush文件,无需手动编写HLSL结构体。

2. 将UBO绑定到材质着色器上下文

需要修改正向渲染材质Shader的C++代码,把UBO绑定到着色器参数槽中:

在ForwardMaterialShader.h中添加UBO声明:

class FForwardMaterialShader : public FMaterialShader
{
    // ... 原有代码
    DECLARE_UNIFORM_BUFFER_BINDING(FMaterialAccessibleShadowData, MaterialAccessibleShadowData)
};

然后在Shader的Setup方法中填充并绑定数据:

void FForwardMaterialShader::SetupUniformBuffers(FRHICommandList& RHICmdList, const FSceneView& View, const FMeshMaterialShaderElementData& MaterialShaderElementData) const
{
    // ... 原有代码
    FMaterialAccessibleShadowData ShadowData;
    FMemory::Memzero(&ShadowData, sizeof(ShadowData));

    // 收集主方向光阴影数据
    if (const FDirectionalLightSceneProxy* DirLightProxy = View.GetPrimaryDirectionalLight())
    {
        ShadowData.LightWorldDirection = DirLightProxy->GetDirection();
        const FCascadeShadowSettings& CascadeSettings = DirLightProxy->GetCascadeSettings();
        
        // 填充级联矩阵
        for (int32 CascadeIdx = 0; CascadeIdx < CascadeSettings.NumCascades; ++CascadeIdx)
        {
            ShadowData.CascadeViewProjMatrices[CascadeIdx] = CascadeSettings.Cascades[CascadeIdx].ViewProjectionMatrix;
        }
        // 填充级联分割距离
        for (int32 i = 0; i < 4; ++i)
        {
            ShadowData.CascadeSplitDistances[i] = i < CascadeSettings.NumCascades ? CascadeSettings.CascadeSplitDistances[i] : 0.0f;
        }
        // 绑定阴影图集
        ShadowData.DirectionalShadowAtlas = DirLightProxy->GetShadowAtlasTexture();
    }

    // 将UBO绑定到着色器
    SetUniformBufferParameter(RHICmdList, GetVertexShader(), GetPixelShader(), MaterialAccessibleShadowData, ShadowData);
}

注意:移动端和PC的阴影实现有差异,可通过PLATFORM_MOBILE宏做分支处理,比如移动端可能不使用级联阴影,直接用单矩阵。

3. 在材质模板中正确引用UBO

在MaterialTemplate.ush中,除了include生成的ush文件,还要用CBUFFER_START/END包裹,确保HLSL能识别:

CBUFFER_START(MaterialAccessibleShadowData)
#include "/Engine/Generated/UniformBuffers/MaterialAccessibleShadowData.ush"
CBUFFER_END

// 声明阴影采样器(按需调整过滤模式)
SAMPLER(SamplerDirectionalShadow, FILTER_BILINEAR, ADDRESS_CLAMP, ADDRESS_CLAMP, ADDRESS_CLAMP);

4. 自定义HLSL节点中安全访问

在你的isInDirectionalLightShadow节点中,先做有效性判断再访问字段,避免崩溃:

bool isInDirectionalLightShadow(float3 WorldPosition, float3 WorldNormal)
{
    // 先判断阴影数据是否有效
    if (MaterialAccessibleShadowData.DirectionalShadowAtlas == nullptr)
    {
        return false;
    }

    // 找到当前位置所属的阴影级联
    int32 CascadeIndex = 0;
    float ViewDepth = FSceneDepth(WorldPosition, View.WorldToView);
    for (int32 i = 1; i < 4; ++i)
    {
        if (ViewDepth < MaterialAccessibleShadowData.CascadeSplitDistances[i])
        {
            break;
        }
        CascadeIndex = i;
    }

    // 转换到阴影裁剪空间
    float4 ShadowClipPos = mul(float4(WorldPosition, 1.0), MaterialAccessibleShadowData.CascadeViewProjMatrices[CascadeIndex]);
    float2 ShadowUV = ShadowClipPos.xy / ShadowClipPos.w * 0.5 + 0.5;

    // 采样阴影图并做深度对比
    float ShadowDepth = Texture2DArraySample(MaterialAccessibleShadowData.DirectionalShadowAtlas, SamplerDirectionalShadow, ShadowUV, CascadeIndex).r;
    float CurrentDepth = ShadowClipPos.z / ShadowClipPos.w;

    // 加入偏移避免阴影 acne
    return CurrentDepth > ShadowDepth + 0.001f;
}

内容的提问来源于stack exchange,提问作者wild-ptr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 05:07:07