Files
BlueRoseNote/03-UnrealEngine/卡通渲染相关资料/渲染功能/ARC/Rendering/屏幕对齐网格.md

5.0 KiB
Raw Blame History

title, date, excerpt, tags, rating
title date excerpt tags rating
屏幕对齐网格 2026-05-03 00:00:00 将网格直接渲染到屏幕空间,用于 UI/HUD 叠加元素
ARC
Rendering
VertexFactory

屏幕对齐网格

返回 Rendering

概述

屏幕对齐网格ScreenAlignedMesh将 3D 网格直接投影到屏幕空间坐标系中渲染,用于实现 UI 元素、HUD 叠加或其他需要固定屏幕位置的网格效果。

实现

在所有顶点着色器中通过 USES_SCREEN_ALIGNED_MESH 宏启用:

#if USES_SCREEN_ALIGNED_MESH
    {
        float2 p = Input.Position.xz * flip;
        float3 offset = GetMaterialScreenAlignedMeshOffset(VertexParameters);
        float3 scale  = GetMaterialScreenAlignedMeshScale(VertexParameters);

        // 基于 1280x720 的参考分辨率
        float2 ScreenPos = p.xy * scale.xy;
        ScreenPos.x +=  offset.x / 640.0f;
        ScreenPos.y += -offset.y / 360.0f;
        ScreenPos.xy += GetMaterialWorldPositionOffset(VertexParameters).xy;

        const float z = 1.0f - 0.00001f;  // 接近远裁面
        WorldPosition = 0;
        Output.Position = float4(ScreenPos, z, 1);
    }
#endif

关键点:

  • 使用 Input.Position.xz(不是 xy作为屏幕坐标输入
  • 参考分辨率为 1280x720offset 以像素为单位
  • 深度设为接近远裁面(1.0 - 0.00001),确保不遮挡 3D 场景
  • 跳过雾效计算(TRANSLUCENCY_NEEDS_BASEPASS_FOGGING 对 ScreenAlignedMesh 禁用)

材质控制

通过 自定义材质属性 中的两个属性控制:

  • MP_ScreenAlignedMeshOffset — 屏幕偏移(像素,基于 1280x720
  • MP_ScreenAlignedMeshScale — 缩放系数

材质标记 bScreenAlignedMesh 启用此模式。

完整代码解析

BasePassVertexShader.usf — 屏幕对齐变换

// ASW Change : 2016/05/16 13:56:33 Takuro.K
// 屏幕对齐网格将3D网格直接投影到屏幕空间
#if USES_SCREEN_ALIGNED_MESH
    {
        // 获取 LocalToWorld 矩阵(区分实例化和非实例化模式)
        #if PARTICLE_MESH_INSTANCED
            float4x4 LocalToWorld = VertexParameters.InstanceLocalToWorld;
        #else
            float3x3 LocalToWorld = GetLocalToWorld3x3(VertexParameters.PrimitiveId);
        #endif

        // 从 LocalToWorld 矩阵的对角元素获取翻转方向
        // 这样网格在镜像 Transform 下仍然正确显示
#if PARTICLE_MESH_INSTANCED
        float2 flip = sign( float2( Input.Transform1.x, LocalToWorld[1][1] ) );
#else
        float2 flip = sign( float2( LocalToWorld[0][0], LocalToWorld[1][1] ) );
#endif
        
        // 使用顶点的 X 和 Z 坐标作为屏幕坐标(不是 XY
        // 这是因为网格在 DCC 中通常面向 Z 轴建模
        float2 p = Input.Position.xz * flip;
        
        // 从材质图获取偏移和缩放参数
        float3 offset = GetMaterialScreenAlignedMeshOffset(VertexParameters);
        float3 scale  = GetMaterialScreenAlignedMeshScale(VertexParameters);
        
        // 基于 1280x720 参考分辨率计算屏幕坐标
        // NDC 范围 [-1, 1],所以 /640 和 /360 将像素单位转为 NDC
        float2 ScreenPos = p.xy * scale.xy;
        ScreenPos.x +=  offset.x / 640.0f;     // X 偏移(向右为正)
        ScreenPos.y += -offset.y / 360.0f;      // Y 偏移向上为正NDC Y 轴反转)
        
        // WorldPositionOffset 也可以叠加微调
        ScreenPos.xy += GetMaterialWorldPositionOffset(VertexParameters).xy;

        // 深度设为接近远裁面,确保不遮挡 3D 场景
        const float z = 1.0f - 0.00001f;

        // 清零世界坐标(屏幕空间渲染不需要)
        WorldPosition = 0;
        // 直接设置裁剪空间输出w=1 表示无透视除法)
        Output.Position = float4( ScreenPos, z, 1 );
    }
#endif

BasePassCommon.ush — 禁用雾效

// ASW Change : 2017/01/30 18:00:41 Takuro.K
// 屏幕对齐网格不需要雾效(它们是屏幕空间元素)
#define TRANSLUCENCY_NEEDS_BASEPASS_FOGGING (
    MATERIAL_ENABLE_TRANSLUCENCY_FOGGING && 
    MATERIALBLENDING_ANY_TRANSLUCENT && 
    !MATERIAL_USES_SCENE_COLOR_COPY && 
    !USES_SCREEN_ALIGNED_MESH)    // <-- 新增条件

代码修改情况

文件路径 行号 修改类型 修改内容
Shaders/Private/BasePassVertexShader.usf L118~L155 新增 屏幕对齐网格变换逻辑1280x720基准/深度设置/WorldPosition清零
Shaders/Private/BasePassCommon.ush L28~L34 修改 TRANSLUCENCY_NEEDS_BASEPASS_FOGGING 禁用 ScreenAlignedMesh 雾效
Shaders/Private/DepthOnlyVertexShader.usf 新增 同上变换逻辑DepthOnly Pass
Shaders/Private/HitProxyVertexShader.usf 新增 同上HitProxy Pass
Shaders/Private/DebugViewModeVertexShader.usf 新增 同上DebugViewMode Pass
Shaders/Private/MaterialTemplate.ush L2243~L2252 新增 GetMaterialScreenAlignedMeshOffset/Scale 材质访问函数