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 - 残影系统