GPU Shaders (.ush)
Source/MassBattle/HLSL/*.ush
着色器总览 Overview
MassBattle 的 GPU 侧由 5 个 .ush 包含文件构成,全部位于 Source/MassBattle/HLSL/:三个预测/插值文件在 Niagara Custom HLSL 节点里把 CPU 逻辑帧数据外推到渲染帧(这正是"CPU 逻辑帧 + GPU 渲染帧插值 → 同屏数量翻倍"的实现),两个解码文件在材质 Custom 节点里解压位打包的 DynamicParams0 通道与跳字数值。GPU 只做插值、外推与解码,不产生任何模拟状态。
The GPU side of MassBattle consists of five .ush include files under Source/MassBattle/HLSL/: three prediction/interpolation files that extrapolate CPU logic-frame data to the render frame inside Niagara Custom HLSL nodes (this is what makes "CPU logic frame + GPU render-frame interpolation → double the on-screen count" work), and two decode files that unpack the bit-packed DynamicParams0 channels and text-pop numbers inside material Custom nodes. The GPU only interpolates, extrapolates and decodes — it never produces simulation state.
引用方式:插件模块启动时(FMassBattleModule::StartupModule)调用 AddShaderSourceDirectoryMapping("/MassBattle", Source/MassBattle/HLSL) 注册虚拟着色器路径;Niagara Custom HLSL 节点与材质 Custom 节点通过 VirtualIncludeFilePaths="/MassBattle/<文件名>.ush" 包含。位布局变更必须三端同步:CPU 编码(RenderBatchData)、GPU 解包/重打包(预测 .ush)、材质解码(MaterialDecode)。
How they are referenced: at plugin module startup (FMassBattleModule::StartupModule) the virtual shader path is registered via AddShaderSourceDirectoryMapping("/MassBattle", Source/MassBattle/HLSL); Niagara Custom HLSL nodes and material Custom nodes include them through VirtualIncludeFilePaths="/MassBattle/<file>.ush". Bit-layout changes must stay in sync across all three ends: the CPU encoder (RenderBatchData), the GPU unpack/repack (the prediction .ush), and the material decode (MaterialDecode).
① Agent 网格预测 MassBattle_AgentMeshPrediction.ush
Agent 网格渲染的一体化 GPU 预测(约 520 行):位置/旋转/缩放预测 + 插值 + 速度/角速度透传;DynamicParams0 在本文件内完整处理——位压缩动画帧按经过时间外推推进,材质特效/混合/溶解在 GPU 端插值,身份令牌变化时直接跳变(防止池复用串帧)。消费点:Content/Core/AgentRenderer/NS_AgentRenderer_Template 与发射器模块 NM_UpdateAgentMeshDataFromArray_GPU。
The all-in-one GPU prediction for agent mesh rendering (~520 lines): position/rotation/scale prediction + interpolation + velocity/angular-velocity pass-through; DynamicParams0 is fully processed here — bit-packed animation frames advance by extrapolated elapsed time, material FX/lerps/dissolve interpolate on the GPU, and identity-token changes snap (preventing cross-entity frames on pool reuse). Consumers: Content/Core/AgentRenderer/NS_AgentRenderer_Template and the emitter module NM_UpdateAgentMeshDataFromArray_GPU.
| 关键函数Key functions | 说明Description |
|---|---|
MassBattle_UnpackMatFx / PackMatFx | DP0.Z 位解包/重打包:HitGlow / IceFx / FireFx / PoisonFxDP0.Z bit unpack / repack: HitGlow / IceFx / FireFx / PoisonFx |
MassBattle_UnpackFlags / PackFlags | DP0.W 位解包/重打包:Team / Dissolve / LODIndex / DrawLOD / BeingSelect / SelectedDP0.W bit unpack / repack: Team / Dissolve / LODIndex / DrawLOD / BeingSelect / Selected |
MassBattle_UnpackTracksA / TracksB | DP0.X/Y 三轨道动画位解包(起帧/末帧/FPS/循环)DP0.X/Y three-track animation bit unpack (start/end frame, FPS, loop) |
MassBattle_AdvanceFrame | 帧推进(循环回绕/外推上限/无外推模式)Frame advance (loop wrap / extrapolation cap / no-extrapolation mode) |
MassBattle_InterpAlpha | 插值速度 → 帧间阿尔法(引擎 DeltaTime)Interp speed → per-frame alpha (engine DeltaTime) |
相关 API:Related API: MassBattleAgentRenderer · RenderBatchData (DP0 layout) · AgentRenderProcessor
② 附加 FX 预测 MassBattle_FxPrediction.ush
附加 FX(跟随父级的特效)的 GPU 预测/插值(约 220 行):以父级为中心——用父级真值 + 速度平滑父级变换,再叠加固定的相对偏移重新合成;FX 从不插值自己的世界位置,每帧由平滑后的父级新鲜合成,因此始终钉在插槽上。镜像旧 CPU 路径(RelativeTransform × ParentInterpTransform,父级缩放已应用于相对偏移与输出缩放),并透传父级速度/角速度供 ribbon 采样。消费点:Content/Core/FxRenderer/NS_FxRendererTemplate 与 NM_UpdateAttachedFxParams_GPU。
GPU prediction/interpolation for ATTACHED FX (~220 lines): parent-centric — smooth the PARENT's transform from its ground truth + velocity, then re-compose the fixed relative offset on top; the FX never interpolates its own world position, it is freshly composed every frame from the smoothed parent so it stays glued to its socket. Mirrors the old CPU path (RelativeTransform × ParentInterpTransform, with parent scale applied to the relative offset and output scale) and passes parent velocity + angular velocity through for ribbon sampling. Consumers: Content/Core/FxRenderer/NS_FxRendererTemplate and NM_UpdateAttachedFxParams_GPU.
| 关键函数Key functions | 说明Description |
|---|---|
MassBattle_PredictAttachedFx | 入口:父级平滑 + 相对偏移合成 + 速度透传Entry point: parent smoothing + relative-offset re-compose + velocity pass-through |
MassBattle_FxVInterpTo / FxQInterpTo | 向量插值与四元数球面插值(VInterpTo/Slerp 的 HLSL 版)Vector interp and quaternion slerp (HLSL versions of VInterpTo/Slerp) |
MassBattle_FxQMul / FxQRotate / FxQAxisAngle | 四元数哈密顿积/旋转向量/轴角构造Quaternion Hamilton product / vector rotation / axis-angle construction |
相关 API:Related API: FxRenderProcessor · Fragments/Render.h (event anchors)
③ 血条预测 MassBattle_HealthBarPrediction.ush
GPU 血条预测(约 135 行):位置插值 + Z 偏移 + 血量比例插值 + 池复用跳变。血条是 sprite 渲染的附着粒子(始终面朝摄像机,无旋转/角速度);位置 = 父级位置(LocationArray)+ Z 偏移,纯平移外推,不重组旋转。消费点:NM_UpdateHealthBarFromArray 与 NM_UpdateAgentHealthBarFromArray。
GPU health-bar prediction (~135 lines): position interpolation + Z offset + ratio interpolation + pool-reuse snap. Health bars are sprite-rendered attached particles (always camera-facing, no rotation/angular velocity); position = parent position (LocationArray) + Z offset — pure translational extrapolation, no rotation recombine. Consumers: NM_UpdateHealthBarFromArray and NM_UpdateAgentHealthBarFromArray.
| 关键函数Key functions | 说明Description |
|---|---|
MassBattle_PredictHealthBar | 入口:父级位置 + Z 偏移 + 比例插值 + 复用跳变Entry point: parent position + Z offset + ratio interp + reuse snap |
MassBattle_VInterpTo / FInterpTo / InterpAlpha | 向量/标量插值工具Vector / scalar interp helpers |
相关 API:Related API: Fragments/HealthBar.h
④ 材质解码 MassBattle_MaterialDecode.ush
材质 Custom 节点解码辅助(约 70 行):解压 DynamicParams0 四个位打包通道。DP0.W 位布局:Team(8b,0-7) | Dissolve(8b,8-15) | LODIndex(4b,16-19) | DrawLOD(20) | BeingSelect(21) | Selected(22) | Reserved(23-31)。消费点:VAT 主材质 Content/Core/AgentRenderer/VAT/M_VATMaster 与材质层 VAT/MF/ML_VATMatLayer。
Material Custom-node decode helpers (~70 lines): unpack the four bit-packed DynamicParams0 channels. DP0.W layout: Team(8b,0-7) | Dissolve(8b,8-15) | LODIndex(4b,16-19) | DrawLOD(20) | BeingSelect(21) | Selected(22) | Reserved(23-31). Consumers: the VAT master material Content/Core/AgentRenderer/VAT/M_VATMaster and the material layer VAT/MF/ML_VATMatLayer.
| 关键函数Key functions | 说明Description |
|---|---|
MassBattle_UnpackMatFx | DP0.Z → HitGlow / IceFx / FireFx / PoisonFx(材质端浮点输出)DP0.Z → HitGlow / IceFx / FireFx / PoisonFx (float outputs for materials) |
相关 API:Related API: RenderBatchData (DP0 encoder) · Render.h (material FX bits)
⑤ 跳字解码 MassBattle_TextPopDecode.ush
TextPop 数字串图集解码器(约 230 行),材质 Custom 节点辅助:从横向字符图集(18 格,1:1)渲染带 K/M/B/T 后缀的数字、+/- 符号、暴击 * 与最多 3 位小数;不在任何字符内的像素输出透明。数值本身由 CPU 端位打包进 DP0,经 Niagara Renderer Visibility 标签/NDC 通道下发。消费点:Content/Core/AgentRenderer/TextPopUp/M_TextPopUp。
The TextPop number-string atlas decoder (~230 lines), a material Custom-node helper: renders K/M/B/T-suffixed numbers, +/- signs, crit * and up to 3 decimals from a horizontal character atlas (18 cells, 1:1); pixels outside any character output transparent. The value itself is bit-packed on the CPU into DP0 and delivered via the Niagara NDC channel. Consumer: Content/Core/AgentRenderer/TextPopUp/M_TextPopUp.
| 关键函数Key functions | 说明Description |
|---|---|
MassBattle_TextPopDecode | 入口:UV → 图集字符采样与透明裁剪Entry point: UV → atlas character sampling with transparency cutout |
相关 API:Related API: Fragments/TextPop.h · Fragments/TextPopConfig.h
补充说明 Notes
开发版仓库中另有骨骼 CS(MassBattle_CSBoneSkin.ush 等)与 Sprite 表示层的 WIP 着色器,它们不属于 1.19.20 发布内容,本页不覆盖;发布树以 Source/MassBattle/HLSL/ 下这 5 个文件为准。修改位布局时的纪律:CPU 编码、GPU 解包/重打包、材质解码三端同步,改后 grep 旧掩码确保零残留;2026-08 起材质解码器已文件化(即本目录方案),不再在材质图里内联长段 HLSL。
The development repository additionally carries WIP shaders for the bone-CS path (MassBattle_CSBoneSkin.ush etc.) and the sprite representation tier; they are not part of the 1.19.20 release and are out of scope here — the release ships exactly the five files under Source/MassBattle/HLSL/. Discipline for layout changes: keep the CPU encoder, the GPU unpack/repack and the material decode in sync, and grep for stale masks afterwards (zero residue). Since 2026-08 the material decoders are file-based (this directory) instead of long inline HLSL in material graphs.