UE5 母材质 编写笔记

什么时候用材质节点什么时候用贴图?

先看清两种方案的真实代价

复制代码
                        贴图                          节点(程序化)
─────────────────────────────────────────────────────────────
一次性成本     贴图制作时间(美术画/烘焙)        TA 写材质图的时间
每帧成本       纹理采样 + 显存带宽               ALU 指令数
内存成本       显存占用(持久)                  无(零内存)
变化能力       改贴图 = 重新导入                 改参数 = 即时
精度           看分辨率                          数学精确
独特性          每张贴图都是唯一的                 同参数 = 同结果

核心公式:

贴图贵在带宽和内存,节点贵在指令数。带宽是 GPU 最稀缺的资源,ALU 反而是最充裕的。


判断框架:什么必须用贴图

必须用贴图的 4 种情况

① 无法用数学描述的信息

复制代码
人脸肤色分布、衣服褶皱、木纹的年轮走势
→ 没有数学公式能描述"这张特定的脸"
→ 只能贴图

② 一次性烘焙比实时算便宜很多

复制代码
高模烘焙的 AO、曲率、厚度、Normal
→ 离线烘焙 1 秒 = 运行时永远不花钱
→ 这个交易永远是划算的

③ 美术需要手绘/精细控制

复制代码
角色脸上的伤痕位置、Logo 的具体形状
→ 美术要在 Photoshop 里一像素一像素地画
→ 不能用 Noise 节点拼

④ 低频 + 需要多种不同变化

复制代码
同一个材质,不同道具需要不同的图案(不换 Shader)
→ 换贴图 = 不增加 Shader 排列数
→ 换逻辑 = 多一个 Static Switch = 多一种 Shader 排列

判断框架:什么应该用节点

应该用节点的 5 种情况

① 数学规律明确的图案

复制代码
棋盘格、条纹、同心圆、网格线、渐变
→ 3-5 条指令能解决的事,用贴图纯属浪费

② 需要实时动态变化的

复制代码
碰撞点的冲击波扩散、能量盾的扫描线、
时间驱动的溶解效果
→ 贴图做不到(除非用 Flipbook,但那也是多张贴图)

③ 高频重复 + 大面积使用

复制代码
地面的碎石纹理、墙体剥落、锈迹斑斑
→ 如果贴图要覆盖整个场景 → 纹理内存爆炸
→ 用节点程序化生成 → 零内存,平铺到任意大小

④ 作为细节叠加而非主体

复制代码
细节法线(Detail Normal)、微粗糙度变化
→ 一张 256×256 的小贴图叠加在 UV 上
→ 成本 ≈ 1 次采样 + 2-3 条 Blend 指令
→ 性价比极高

UE5 母材质以及母材质 - 材质实例 合批条件

材质实例、Shader 变体与 PSO 笔记

1. 母材质的作用

母材质主要用于:

  • 复用材质节点和 Shader 逻辑。
  • 统一材质效果和参数。
  • 降低材质维护成本。
  • 控制 Shader permutation 数量。
  • 方便后续统一修改。

但:

复制代码
有母材质 ≠ 一定能合批 Draw Call

母材质主要解决的是材质逻辑复用,不是直接解决角色 Draw Call。

2. 材质实例的作用

材质实例可以修改:

  • 颜色
  • 粗糙度
  • 金属度
  • 普通纹理
  • 其他材质参数

普通参数变化通常不会产生新的 Shader permutation。

但材质实例也可以覆盖部分静态属性,例如:

  • Blend Mode
  • Shading Model
  • Static Switch
  • Static Component Mask
  • 是否使用某些静态功能

这些静态属性变化可能产生新的 Shader permutation 和 PSO。

3. Shader permutation 是什么

Shader permutation 就是 Shader 的编译变体。

复制代码
Shader 结构
+ 静态编译条件
= 一个 Shader permutation

例如:

复制代码
UseDetailNormal = true
UseDetailNormal = false

会生成两个不同的 Shader 变体。

多个 Static Switch 组合时,变体数量可能快速增加:

复制代码
5 个二值 Static Switch
→ 理论上最多 2^5 = 32 种组合

4. 材质实例不是自带所有变体

一个材质实例不是同时包含所有 Blend Mode 或 Static Switch 变体。

它实际使用的是:

复制代码
当前静态参数组合
→ 对应的一套 Shader permutation / PSO

例如:

复制代码
MI_A:Opaque
MI_B:Translucent

这两个材质实例会使用不同的 Shader 变体和 PSO。

所以准确说法是:

材质实例可以通过不同的静态参数组合形成不同变体,但不会天然拥有所有变体。

复制代码
你不切到另一个静态分支,那个分支一般不会进入当前 shader bytecode。
没有被材质实例使用的静态组合,通常也不会在运行时占用 shader / PSO 内存。

5. 普通参数和静态参数的区别

普通动态参数

例如:

  • 颜色
  • 粗糙度
  • 金属度
  • 普通纹理参数

通常:

复制代码
不改变 Shader permutation
不改变 PSO

静态参数

例如:

  • Blend Mode
  • Shading Model
  • Static Switch
  • Static Component Mask
  • 是否启用 WPO 等功能

通常:

复制代码
可能改变 Shader permutation
可能改变 PSO

6. 贴图不同是否会产生 PSO 变体

如果两个材质实例:

复制代码
来自同一个母材质
+ 只使用不同普通贴图
+ 其他参数和静态状态相同

通常可以:

复制代码
使用相同 Shader permutation
复用相同或兼容的 PSO

但是:

复制代码
纹理绑定不同
→ 通常仍然是不同 Draw Call

也就是说:

复制代码
贴图不同 → 通常影响材质绑定和 Draw Call
静态参数不同 → 影响 Shader permutation 和 PSO

特殊情况可能改变变体,例如:

  • 普通 Texture2D 和 Virtual Texture 的使用方式不同。
  • 采样类型不同。
  • Static Switch 决定是否使用某张贴图。
  • Blend Mode 或 Shading Model 不同。

7. PSO 与 Draw Call 的区别

复制代码
PSO 相同
≠
一定可以合并 Draw Call

要合并 Draw Call,通常还需要:

  • 相同 Mesh。
  • 相同 Mesh Section。
  • 相同材质资源绑定。
  • 相同纹理和 Sampler。
  • 相同 Vertex Factory。
  • 相同渲染 Pass。
  • 对象差异可以通过实例数据传入。

8. 角色材质为什么难以合批

角色通常是 Skeletal Mesh,具有:

  • 独立骨骼姿势。
  • 多个身体部位。
  • 不同贴图。
  • 多个 Material Slot。
  • 多个 Mesh Section。
  • 不同装备和材质状态。

因此角色之间的传统 Draw Call 合批能力比较有限。

角色优化通常优先考虑:

复制代码
减少 Material Slot
减少 Mesh Section
减少纹理采样
减少 Shader 指令
减少 Static Switch
减少不必要的材质功能

9. ISM 和 HISM

ISM

Instanced Static Mesh,适合批量绘制大量相同 Static Mesh。

HISM

Hierarchical Instanced Static Mesh,在 ISM 基础上增加空间层级剔除,适合大范围分布的大量静态物体。

典型用途:

  • 球体
  • 树木
  • 岩石
  • 路灯
  • 大量重复装饰物

ISM/HISM 主要用于 Static Mesh,不适合直接用于每个角色都有独立骨骼动画的 Skeletal Mesh。

10. 角色和 ISM/HISM 的关系

对于普通静态物体:

复制代码
同一个 Mesh
+ 同一个 MI
+ ISM/HISM
+ Per Instance Custom Data

可以让每个实例拥有不同颜色等数据,同时保持较好的批处理能力。

但对于角色:

复制代码
不同角色
+ 独立骨骼动画
+ 不同贴图

通常不能直接使用 ISM/HISM,也不应把角色 Draw Call 优化完全建立在传统实例化合批上。

11. 不做母材质的影响

如果每个角色都创建独立材质:

复制代码
独立材质数量增加
→ Shader Map 管理增加
→ 编译和缓存成本增加
→ 维护成本增加

如果每个材质的 Shader 功能也不同:

复制代码
材质结构不同
→ Shader permutation 增加
→ PSO 种类增加

但如果独立材质只是换贴图:

复制代码
通常不会因为贴图本身产生新的 permutation

主要代价是:

  • 材质资源重复。
  • 维护困难。
  • 不利于统一优化。
  • 不一定减少 Draw Call。

12. 每个角色专用材质什么时候合理

适合以下情况:

  • 角色数量较少。
  • 每个角色效果差异很大。
  • 可以删除大量不需要的材质功能。
  • 能减少纹理采样和 Shader 指令。
  • 项目不依赖角色之间的 Draw Call 合批。

如果只是复制相同材质节点,然后替换贴图,性能收益通常有限。

更折中的方式是按类型建立少量母材质:

复制代码
M_Character_Skin
M_Character_Cloth
M_Character_Armor
M_Character_Hair

角色再使用对应的材质实例。

最终结论

复制代码
母材质:
复用材质逻辑,控制 Shader 结构和静态变体

材质实例:
复用材质逻辑,修改具体参数

Shader permutation:
Shader 的编译变体

PSO:
固定 GPU 管线状态

Draw Call:
一次实际绘制提交

最关键的三句话:

普通贴图不同,通常不会产生新的 PSO,但会影响材质绑定和 Draw Call。
Static Switch、Blend Mode、Shading Model 等静态属性不同,才更容易产生新的 Shader permutation 和 PSO。
对角色来说,重点通常不是角色之间合批,而是减少 Material Slot、Mesh Section、材质采样和 Shader 复杂度。

所以如果两个角色都用同一个母材质、同一套静态开关、同一个 Blend Mode、同一个 Shading Model,只是材质实例里换了 BaseColor / Normal / ORM 贴图,通常:

复制代码
不会产生新的 shader
不会产生新的 PSO
但会产生不同的材质资源绑定

不过它确实会影响 Draw Call/合批:

复制代码
同 mesh + 同 material instance + 同贴图:更容易合批/实例化
同 mesh + 同母材质但不同 material instance / 不同贴图:通常需要不同 draw

更准确说,贴图不同不是"直接增加 PSO",而是让每次绘制前绑定的资源不同,因此 UE 很难把它们当成完全相同的 draw 来合并。

在substrate材质中:

相关推荐
远离UE416 分钟前
UE5 HLSLTranslator 与 ShaderCompiler
ue5
kyrie_sakura22 分钟前
python学习笔记 7--- 文件(IO)操作
笔记·python·学习
北风toto1 小时前
软件设计师(中级)做题笔记
笔记
从零开始的嵌入式之旅1 小时前
day32
linux·c语言·经验分享·笔记·嵌入式硬件
ouynagda2 小时前
Linux信号与进程间通信学习笔记
linux·笔记·学习
️学习的小王2 小时前
AI Agent Skills进阶:调试、排错、实战开发与工程化落地
人工智能·经验分享·笔记·学习
kkkkkkkkkk_Z2 小时前
学嵌入式和Linux应用编程|学习日记Day26:Linux进程完整学习笔记
linux·笔记·学习
kmomo..2 小时前
Linux 进程间通信(IPC)学习笔记
linux·笔记·学习
zhonyu鱼2 小时前
Drawpile:多人实时协作绘画,一起在同一块画布上画画
笔记·pdf·开源·开源软件