# 着色器与视觉特效(VFX)
> **视觉特效是游戏的语法** —— 它告诉玩家发生了什么、什么重要、以及该如何感受。
---
## 目录
1. [VFX 设计哲学](#vfx-设计哲学)
2. [着色器基础](#着色器基础)
3. [粒子系统](#粒子系统)
4. [后处理效果](#后处理效果)
5. [材质系统](#材质系统)
6. [常见 VFX 类型实现](#常见-vfx-类型实现)
7. [三大引擎 VFX 工具对比](#三大引擎-vfx-工具对比)
8. [VFX 性能优化](#vfx-性能优化)
9. [经典案例分析](#经典案例分析)
---
## VFX 设计哲学
### VFX 的三大功能
| 功能 | 说明 | 示例 |
|------|------|------|
| **反馈(Feedback)** | 响应玩家输入,确认操作 | 击中火花、拾取闪光 |
| **沟通(Communication)** | 传达游戏状态信息 | 低血量红屏、可交互高亮 |
| **氛围(Atmosphere)** | 建立情绪和世界感 | 雨、雾、魔法光效 |
### VFX 设计原则
```
READ 原则:
R - Readable(可读性)
└── 玩家一眼能理解效果含义
└── 避免过度复杂导致信息淹没
E - Efficient(效率)
└── 用最少的粒子/材质达到效果
└── 考虑性能预算
A - Appropriate(恰当性)
└── 风格与世界观一致
└── 不破坏游戏美术方向
D - Dynamic(动态感)
└── 避免静态、重复感
└── 利用动画、随机性、响应性
```
### VFX 与游戏设计的关系
```
游戏反馈层次:
Layer 1: 音频反馈
└── 最即时,不可见时仍能感知
Layer 2: UI 反馈
└── 数值变化、血条、提示文字
Layer 3: 角色动画
└── 受击动画、施法前摇
Layer 4: 粒子特效
└── 火花、烟雾、魔法光芒
Layer 5: 屏幕效果
└── 震动、模糊、颜色变化
Layer 6: 环境变化
└── 天气、光照、破坏残留
```
---
## 着色器基础
### 着色器类型
| 类型 | 阶段 | 功能 | 每帧调用 |
|------|------|------|----------|
| **Vertex Shader** | 顶点处理 | 变换、变形、位移 | 每个顶点 |
| **Fragment/Pixel Shader** | 片元处理 | 颜色、光照、纹理采样 | 每个像素 |
| **Geometry Shader** | 图元处理 | 动态生成几何体 | 每个图元 |
| **Compute Shader** | 通用计算 | 粒子模拟、后处理 | 按需 |
| **Tessellation** | 细分曲面 | LOD 动态细分 | 每个面片 |
### 着色器语言对比
| 语言 | 平台 | 特点 | 示例引擎 |
|------|------|------|----------|
| **HLSL** | DirectX | 微软生态,功能丰富 | Unreal, Unity (DX) |
| **GLSL** | OpenGL/Vulkan | 跨平台,版本碎片化 | Unity (GL), Godot |
| **Shader Graph** | 跨平台 | 节点可视化,无需编码 | Unity, Unreal |
| **Material Editor** | 跨平台 | 节点式,功能强大 | Unreal |
| **VisualShader** | 跨平台 | Godot 内置可视化 | Godot |
| **SPIR-V** | Vulkan | 中间表示,编译目标 | 现代跨平台 |
### 常用 Shader 技术
#### 1. 消融效果(Dissolve)
```hlsl
// HLSL 伪代码
float dissolveEdge = 0.05;
float noise = tex2D(_NoiseTex, uv).r;
float mask = noise - _DissolveAmount;
// 主体
clip(mask);
// 边缘发光
float edge = smoothstep(0, dissolveEdge, mask);
float3 finalColor = lerp(_EdgeColor, baseColor, edge);
```
#### 2. 全息投影(Hologram)
```hlsl
// 扫描线 + 故障 + 透明度
float scanline = frac(uv.y * _ScanlineDensity + _Time.y);
scanline = step(_ScanlineThreshold, scanline);
float glitch = frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453);
glitch = step(_GlitchThreshold, glitch);
float alpha = baseAlpha * scanline * glitch;
float3 color = lerp(_HologramColor, baseColor, _ColorBlend);
```
#### 3. 卡通渲染(Toon Shading)
```hlsl
// 漫反射阶梯化
float NdotL = dot(normal, lightDir);
float toon = floor(NdotL * _Steps) / _Steps;
// 边缘光(Rim Light)
float rim = 1 - dot(viewDir, normal);
rim = pow(rim, _RimPower);
// 描边(Outline Pass)
// 顶点沿法线外扩 + 黑色纯色渲染
```
---
## 粒子系统
### 粒子系统核心参数
| 参数 | 说明 | 典型值 |
|------|------|--------|
| **发射率** | 每秒生成粒子数 | 10-1000 |
| **生命周期** | 粒子存在时间 | 0.5-5s |
| **初始速度** | 发射时的速度 | 1-20 m/s |
| **初始大小** | 发射时的大小 | 0.1-5 |
| **重力** | 影响粒子运动 | -9.81 或自定义 |
| **拖尾** | 速度衰减 | 0-1 |
| **颜色生命周期** | 随时间变化颜色 | 白→黄→红→透明 |
| **大小生命周期** | 随时间变化大小 | 小→大→小 |
### 粒子发射模式
```
发射器形状:
├── 点(Point)→ 爆炸、火花
├── 球体(Sphere)→ 魔法球、爆炸
├── 锥体(Cone)→ 喷射、火焰、喷水
├── 盒子(Box)→ 环境效果、瀑布
├── 网格(Mesh)→ 表面效果、溶解
├── 边缘(Edge)→ 激光、扫描线
└── 自定义(Custom)→ 沿路径、沿骨骼
```
### 粒子性能分级
| 等级 | 最大粒子数 | 每粒子开销 | 适用场景 |
|------|-----------|-----------|----------|
| **Ultra** | 10,000+ | GPU Simulation | 过场动画、截图 |
| **High** | 5,000 | GPU + 复杂 Shader | PC 高端 |
| **Medium** | 2,000 | 简化 Shader | PC 主流 |
| **Low** | 500 | 最简 Shader | 移动端 |
| **Minimal** | 100 | billboard 精灵 | 低端移动 |
### 粒子系统最佳实践
```
1. 生命周期管理
├── 粒子死亡后回收,不销毁
├── 预分配粒子池
└── 避免运行时创建/销毁
2. 材质优化
├── 使用 Additive 混合减少 overdraw
├── 简单 Shader(无光照计算)
└── 纹理图集(减少 Draw Call)
3. LOD 系统
├── 远距离减少粒子数量
├── 远距离用简单贴图替代粒子
└── 距离过远直接禁用
4. 碰撞控制
├── 粒子碰撞极昂贵
├── 限制碰撞粒子比例
└── 简化碰撞体(Sphere 优先)
```
---
## 后处理效果
### 后处理管线
```
后处理执行顺序:
1. 颜色校正(Color Correction)
├── 白平衡
├── 色调映射(Tone Mapping)
└── LUT 颜色分级
2. 光照效果
├── Bloom(泛光)
├── Vignette(暗角)
└── Lens Flare(镜头光晕)
3. 屏幕空间效果
├── SSAO / SSGI
├── SSR(屏幕空间反射)
└── 接触阴影
4. 镜头效果
├── 景深(Depth of Field)
├── 运动模糊(Motion Blur)
└── 色差(Chromatic Aberration)
5. 风格化
├── 边缘检测(Outline)
├── 像素化
└── 调色板限制
```
### 关键后处理技术
#### Bloom(泛光)
```
实现步骤:
1. 提取高亮区域(阈值过滤)
2. 降采样到 1/2, 1/4, 1/8
3. 每层高斯模糊
4. 上采样并叠加
5. 与原图混合
参数:
- Threshold: 0.8-1.2(什么亮度开始泛光)
- Intensity: 0.5-2.0(泛光强度)
- Scatter: 0.5-1.0(扩散程度)
```
#### 色调映射(Tone Mapping)
| 算法 | 特点 | 适用 |
|------|------|------|
| **Reinhard** | 简单,整体压暗 | 保守风格 |
| **ACES** | 电影感,色彩保留好 | 3A 游戏标准 |
| **AgX** | 最新的,更佳暗部 | 现代渲染器 |
| **Uncharted 2** | 可调参数丰富 | 定制化需求 |
#### 景深(Depth of Field)
```
实现方式:
1. 基于深度图判断对焦距离
2. 模糊远离对焦平面的区域
3. 模糊方式:
├── 高斯模糊(快,效果一般)
├── Bokeh 模糊(慢,真实散景)
└── 圆形/六边形/八边形 Bokeh
游戏应用:
- 瞄准镜:前景模糊突出准心
- 对话:背景模糊聚焦角色
- 受伤:全局模糊表现眩晕
```
---
## 材质系统
### PBR 材质工作流
```
PBR 输入贴图:
Albedo/BaseColor(RGB)
└── 漫反射颜色,无光照信息
Normal(RGB)
└── 表面法线方向,增加细节
Metallic(R)
└── 0=非金属,1=金属
Roughness(R)
└── 0=镜面光滑,1=完全粗糙
Ambient Occlusion(R)
└── 间接光照遮蔽
Emission(RGB,可选)
└── 自发光颜色
Height/Displacement(R,可选)
└── 位移/视差映射
```
### 材质类型速查
| 材质 | Albedo | Metallic | Roughness | 特殊 |
|------|--------|----------|-----------|------|
| **混凝土** | 灰色 | 0.0 | 0.9-1.0 | — |
| **金属** | 深色 | 1.0 | 0.2-0.4 | — |
| **塑料** | 彩色 | 0.0 | 0.1-0.3 | — |
| **皮肤** | 肤色 | 0.0 | 0.5-0.8 | Subsurface |
| **水** | 蓝绿 | 0.0 | 0.0 | 透明、折射 |
| **叶子** | 绿色 | 0.0 | 0.6-0.9 | 双面、半透明 |
| **发光体** | 颜色 | 0.0 | 1.0 | Emission |
### 高级材质技术
#### Subsurface Scattering(次表面散射)
```
适用:皮肤、蜡、玉、牛奶
原理:光线进入表面内部散射后射出
实现方式:
1. 预积分皮肤 LUT
2. 屏幕空间散射(SSS)
3. 可分离的次表面散射
参数:
- Scatter Distance: 散射距离
- Scatter Color: 内部散射颜色
- Thickness: 材质厚度图
```
#### Parallax Occlusion Mapping(POM)
```
效果:比法线贴图更强的深度感
原理:沿视线方向步进,找到正确纹理坐标
vs 其他技术:
├── 法线贴图:改变光照,无遮挡
├── 视差映射:简单偏移,无遮挡
├── POM:步进搜索,有自遮挡
└── 置换:真实几何,最贵
性能:每像素 10-50 次纹理采样
适用:近距离观察的表面(地板、墙面)
```
---
## 常见 VFX 类型实现
### 战斗特效
| 特效类型 | 技术要点 | 性能注意 |
|----------|----------|----------|
| **刀剑轨迹** | Trail Renderer + 纹理动画 | 控制长度和分段数 |
| **击中火花** | 短生命周期粒子 burst | 限制同时存在数量 |
| **流血** | Decal 投影 + 粒子 | 限制 Decal 数量 |
| **护盾** | 半透明 Shader + Fresnel | Overdraw 控制 |
| **施法光环** | 环形 UV 动画 + 顶点偏移 | 简化几何 |
### 环境特效
| 特效类型 | 实现方式 | 优化策略 |
|----------|----------|----------|
| **雨** | GPU Particle + 碰撞平面 | 无单滴碰撞,整体平面 |
| **雪** | 粒子 + 风力扰动 | LOD:近处粒子远处贴图 |
| **雾** | 体积雾 / 高度雾 | 移动端用平面雾 |
| **火** | 粒子 + 扭曲 + 光照 | 限制光源数量 |
| **水** | 平面 + 法线动画 + 反射 | SSR 替代反射探针 |
### UI 特效
```
常见 UI VFX:
转场效果:
├── 淡入淡出(Alpha 插值)
├── 滑动(位置插值)
├── 缩放(Scale 弹性插值)
└── 翻转(3D 旋转)
反馈效果:
├── 按钮点击(缩放脉冲)
├── 获得物品(飞入动画 + 粒子)
├── 警告(红色闪烁 + 震动)
└── 加载(旋转 + 进度条填充)
风格化:
├── glitch 故障效果
├── 扫描线
├── 打字机文字
└── 粒子背景
```
---
## 三大引擎 VFX 工具对比
| 功能 | Unity | Unreal Engine | Godot |
|------|-------|---------------|-------|
| **粒子系统** | VFX Graph (GPU) + Particle System (CPU) | Niagara (GPU/CPU) | GPUParticles3D + CPUParticles |
| **可视化 Shader** | Shader Graph | Material Editor | VisualShader |
| **后处理** | URP/HDRP Volume | Post Process Volume | Environment + Camera Effects |
| **Decal** | Decal Projector | Deferred Decal | Decal 节点 |
| **Trail** | Trail Renderer | Ribbon Particle | Trail 节点 |
| **VFX 预设库** | 中等 | 丰富(UE 内容示例) | 较少 |
| **Shader 调试** | Frame Debugger | Shader Complexity View | 基础 |
| **性能分析** | Profiler GPU | GPU Visualizer | 基础 |
### Unity VFX Graph vs Unreal Niagara
| 特性 | Unity VFX Graph | Unreal Niagara |
|------|-----------------|----------------|
| **计算位置** | GPU(Compute Shader) | GPU/CPU 可选 |
| **节点类型** | 数据流图 | 模块化堆栈 |
| **事件系统** | 支持 Spawn Event | 强大 Event/Receiver |
| **与动画集成** | 通过 Timeline | 通过 AnimNotify |
| **蓝图/脚本** | C# 控制 | Blueprint + 自定义模块 |
| **学习曲线** | 中等 | 较陡 |
| **性能** | 极高(百万粒子) | 高 |
---
## VFX 性能优化
### 开销分布
```
VFX 性能热点:
Overdraw(过度绘制) ████████████████████ 最大问题
└── 半透明粒子层层叠加
└── 全屏后处理
Fill Rate(填充率) ████████████ 高分辨率更敏感
└── 大粒子覆盖很多像素
Draw Call ██████ 材质/纹理切换
Vertex Processing ████ 复杂网格动画
Memory Bandwidth ███ 大纹理采样
```
### 优化策略
| 问题 | 诊断 | 解决方案 |
|------|------|----------|
| **Overdraw** | 可视化 overdraw 热图 | 减少粒子数量、缩小大小、少用全屏特效 |
| **透明排序** | 粒子闪烁 | 正确设置排序模式、减少透明重叠 |
| **纹理带宽** | Profiler 显示 | 压缩纹理、降采样、图集合并 |
| **Shader 复杂** | GPU 时间高 | 简化 Shader、减少纹理采样 |
| **Fill Rate** | 高分辨率卡 | 动态分辨率、降低特效精度 |
### VFX LOD 方案
```
距离 LOD 策略:
0-10m:完整特效
├── 全部粒子效果
├── 完整光照响应
└── 后处理参与
10-30m:简化特效
├── 粒子数量减半
├── 关闭碰撞
└── 简化 Shader
30-100m:极简特效
├── 仅保留核心粒子
├── Billboard 替代 3D
└── 无动态光照
100m+:禁用或贴图
├── 完全关闭粒子
└── 用贴图/光影暗示存在
```
---
## 经典案例分析
### 《守望先锋》—— 可读性优先
```
设计原则:
- 每个英雄技能有独特视觉语言
- 友方/敌方颜色严格区分(蓝/红)
- 技能范围清晰可视化
- 关键技能有全局可见提示
示例:
- 半藏龙:巨大龙形,穿越墙壁可见
- 查莉娅重力喷涌:黑色球体+吸引特效
- 天使复活:金色光束,明确目标
```
### 《战神》(2018)—— 无缝打击感
| 技术 | 实现 | 效果 |
|------|------|------|
| **命中停顿** | 击中时 2-4 帧时间缩放 | 重量感 |
| **屏幕震动** | 基于打击力度的 Camera Shake | 冲击力 |
| **粒子爆发** | 方向性火花,沿打击方向 | 方向感 |
| **敌人闪烁** | 受击时白色闪烁 | 确认命中 |
| **血液轨迹** | 物理驱动的 Decal 和粒子 | 残酷感 |
### 《塞尔达传说:旷野之息》—— 风格化 VFX
```
美术方向:水彩/卡通风格
技术选择:
- 粒子风格化:手绘纹理,边缘柔和
- 魔法效果:几何图形 + 简单颜色
- 环境效果:大面积低细节,强调色彩
- 避免:写实烟雾、复杂火焰
Sheikah 科技特效:
- 统一的橙色/蓝色发光语言
- 几何图形(圆形、六边形)
- 扫描线 + 数字化元素
```
### 《毁灭战士:永恒》—— 信息密度
```
VFX 信息设计:
弱点系统:
- 敌人弱点发光(特定颜色)
- 命中弱点时独特特效 + 声音
- 处决可用时敌人闪烁
资源管理:
- 血包发光(绿色)
- 护甲碎片(蓝色)
- 弹药(对应武器颜色)
状态反馈:
- 低血量:屏幕边缘血红色
- Rampage 模式:全屏红色滤镜
- 击杀:经验值数字弹出
```
---
## 最佳实践清单
- [ ] **目的明确**:每个特效都有清晰的游戏设计目的
- [ ] **风格统一**:所有特效遵循同一美术方向
- [ ] **颜色编码**:用颜色传达信息(伤害类型、阵营、状态)
- [ ] **时机精确**:特效触发与游戏事件同步,无延迟
- [ ] **性能预算**:每个特效有明确的性能上限
- [ ] **距离 LOD**:远距离自动简化或禁用
- [ ] **池化管理**:所有特效使用对象池
- [ ] **可配置性**:参数外置,便于调优
- [ ] **可关闭**:提供选项关闭非必要特效
- [ ] **测试色盲**:确保颜色信息有其他方式传达
---
## 相关页面
- [渲染管线](rendering-pipeline.md) — 渲染技术基础
- [游戏 UI/UX](game-ui-ux.md) — UI 特效设计
- [性能优化](performance-optimization.md) — VFX 性能优化细节