Shader 学习笔记
项目中 Shader 实现的经验总结
方案 C:组合方案(当前实现)
通过分层组合的方式实现复杂的角色特效,每层负责不同的效果维度。
效果一:超级赛亚人气场(攻击时触发)
| 层级 | 组件 | 效果 | 文件 |
|---|---|---|---|
| 底层 | AuraEffect | 底部椭圆光晕 + 火焰舌 + 上升能量流 | aura_effect.gd |
| 中层 | Sprite + Shader | 角色描边发光 + 脉冲波动 | ssj_outline.gdshader |
| 顶层 | 粒子系统 | 向上飘散的能量粒子 | aura_effect.gd |
效果二:桑德维斯坦(冲刺时触发)
| 组件 | 效果 | 文件 |
|---|---|---|
| Sprite + Shader | 色差 + 边缘青色光晕 | sandevistan.gdshader |
| AfterimageSystem | 彩虹色残影拖尾 | afterimage_system.gd |
SubViewport 方案(计划中)
创建比角色大的"虚拟画布",把角色渲染到画布中心,然后对整个画布应用 shader。
┌─────────────────────────────────────┐
│ SubViewport │
│ (192×192 或 256×256) │
│ 特效可以延伸到这里 │
│ ┌─────────┐ │
│ │ 角色 │ │
│ │ (64×64) │ │
│ └─────────┘ │
│ 特效可以延伸到这里 │
└─────────────────────────────────────┘
优势
- 🔥 火焰可以真正"冲出"角色范围
- 🎨 所有效果基于真实轮廓
- 🖌️ 描边可以任意粗细
- ✨ 外发光自然扩散
Y-Sort 层级控制
问题:在 y_sort_enabled = true
的容器中,如何让特效在角色后面但在地图上面?
解决方案:把特效节点作为 YSort_Container 的直接子节点,通过 y 坐标偏移控制绘制顺序。
# 特效的 y 坐标 = 玩家 y 坐标 - 1
@export var y_offset: float = -1.0
func _process(delta):
global_position = follow_target.global_position + Vector2(0, y_offset)
排序结果
Y-Sort 排序:
[0] TileMapLayer: y=0.0 ← 地图,先绘制
[1] AuraEffect: y=599.0 ← 气场,后绘制(在地图上面)
[2] Player: y=600.0 ← 玩家,最后绘制(在气场上面)
Shader 控制 API
# 冲刺效果
func start_sandevistan()
func stop_sandevistan()
# 攻击效果
func start_ssj_outline(target_intensity: float = 1.0)
func stop_ssj_outline()
相关文件索引
Shader 文件
ssj_outline.gdshader- SSJ 描边发光sandevistan.gdshader- 桑德维斯坦色差
脚本文件
shader_controller.gd- Shader 效果控制器aura_effect.gd- 气场火焰节点afterimage_system.gd- 残影系统