mcpField
S
shader-programming

shader-programming

github.com/gamedev-skills开发5.4k7.6k 次安装1 天前更新
代码仓库

关于 shader-programming

面向学习或编写 GPU 顶点与片段着色器的开发者,提供跨引擎着色器编程指导。内容以 GLSL 通用基础为主,并提供 HLSL 对照,涵盖常见视觉效果与着色器易错点。

主要功能

  1. 01顶点与片段着色器基础
  2. 02GLSL 与 HLSL 概念对照
  3. 03UV 与坐标空间指引
  4. 04常见效果模式
  5. 05性能与平台注意事项

适用场景

  1. 01编写滚动纹理着色器
  2. 02制作溶解或边缘光效果
  3. 03在不同引擎间转换着色器概念

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill shader-programming

安装后在 Claude Code 中输入/shader-programming确认已加载。

附带文件references/effects.md

详细介绍

着色器编程(跨引擎)

着色器是在 GPU 上逐顶点和逐像素运行的小型程序。 其中的概念——渲染管线、坐标空间、UV,以及常见效果的构建方式——都能跨引擎通用;只有语言方言和内置变量名称会有所变化。本技能使用 GLSL 讲解这些可移植的基础知识,并提供 HLSL 对应写法;如需了解确切的引擎语法和内置变量,请使用 godot-shaders(或 Unity/Unreal 材质文档)。

适用场景

  • 用于理解或编写顶点/片段着色器,并分析 UV、坐标空间和 GPU 渲染管线。
  • 用于构建常见效果:着色/重着色、纹理滚动、溶解、轮廓、菲涅耳/边缘光、晕影、颜色分级。
  • 用于在 GLSL 和 HLSL 之间,或在不同引擎之间转换着色器概念。

不适用场景: 如需了解某个引擎的确切着色器语言和内置变量,请使用 godot-shaders(Godot 着色语言)或该引擎的材质文档。对于完整的粒子 VFX 系统,请参阅 unreal-niagara。对于后处理堆栈,请参考引擎的渲染器设置。

核心工作流

  1. 明确当前所处的阶段。 顶点着色器会将每个顶点变换到裁剪空间,并传递数据(UV、法线);片段/像素着色器会对每个光栅化像素运行并输出颜色。大多数游戏效果都在片段阶段实现。
  2. 跟踪坐标空间。 位置在模型 → 世界 → 视图 → 裁剪空间之间变换;法线属于世界空间或视图空间。混用坐标空间是最常见的错误。
  3. 用 UV 和时间驱动效果。 UV 是 0..1 范围内的纹理坐标;对其进行偏移、缩放或扭曲,并使用 time uniform 制作动画。
  4. 逐像素处理,尽量少用分支。 尽可能使用 mix、step、smoothstep 和 clamp 代替 if;GPU 会锁步运行像素,不适合处理分歧分支。
  5. 通过 uniforms(每次绘制固定不变)和 varyings(在顶点→片段间插值)传递数据。尽量减少纹理采样次数;它们是主要开销。
  6. 如果工具已可用,先验证源代码,再进行视觉测试。 对于 GLSL,使用匹配的阶段后缀运行 glslangValidator path/to/shader.frag;对于 WGSL,运行 naga path/to/shader.wgsl。Godot .gdshader 文件需要在 Godot 中打开项目进行检查,因为 Godot 没有独立的验证器。
  7. 在目标硬件上进行视觉验证。 在桌面设备上看起来正常的着色器,在移动设备上可能会出问题(精度、缺失的功能)。请在实际发布的平台上测试。

模式

GLSL 风格的片段代码(接近 Godot 的 canvas_item/spatial 着色器和 OpenGL)。HLSL 对应写法以及完整的轮廓/菲涅耳/晕影着色器,请参阅 references/effects.md。

1. 片段着色器基础:采样、着色与合成
// Per-pixel: read the texture at this UV, multiply by a color (tint), keep alpha.
uniform sampler2D tex;
uniform vec4 tint;          // e.g. (1,0,0,1) reddens; multiply is non-destructive
in vec2 uv;                 // interpolated 0..1 texture coordinate (a "varying")
out vec4 frag;
void main() {
    vec4 c = texture(tex, uv);   // HLSL: tex.Sample(samp, uv)
    frag = c * tint;             // component-wise multiply tints without clipping
}
2. UV 滚动(动画纹理)——与帧率无关
// Add time * speed to the UV to scroll. fract() wraps it into 0..1 so it tiles.
uniform sampler2D tex;
uniform float time;          // seconds, supplied by the engine
uniform vec2 scroll_speed;   // UV units per second, e.g. (0.1, 0.0)
in vec2 uv;
out vec4 frag;
void main() {
    vec2 scrolled = fract(uv + scroll_speed * time);  // HLSL: frac(...)
    frag = texture(tex, scrolled);
}
// Drive with a real time uniform, not a per-frame accumulator, so speed is stable.
3. 溶解(对噪声贴图进行阈值处理,为边缘添加辉光)
// Hide pixels where noise < threshold; tint a thin band at the boundary.
uniform sampler2D tex;
uniform sampler2D noise_tex;     // grayscale noise, 0..1
uniform float amount;            // 0 = fully visible, 1 = fully dissolved
uniform float edge = 0.05;       // width of the glowing edge band
uniform vec4 edge_color;
in vec2 uv;
out vec4 frag;
void main() {
    vec4 c = texture(tex, uv);
    float n = texture(noise_tex, uv).r;
    if (n < amount) discard;                 // cut away dissolved pixels
    float e = smoothstep(amount, amount + edge, n);  // 0 at the edge -> 1 inside
    frag = mix(edge_color, c, e);            // HLSL: lerp(edge_color, c, e)
}
4. 菲涅耳边缘光(3D)——增强掠射角处的亮度
// Rim = 1 where the surface faces away from the camera (silhouette glow).
in vec3 world_normal;        // normalized, world space (from the vertex stage)
in vec3 view_dir;            // normalized, surface -> camera, world space
uniform float power = 3.0;
uniform vec3 rim_color;
out vec4 frag;
void main() {
    float f = pow(1.0 - clamp(dot(world_normal, view_dir), 0.0, 1.0), power);
    frag = vec4(rim_color * f, 1.0);   // add to lighting; f peaks at the silhouette
}
// Correctness: normal and view_dir MUST be in the same space and normalized.

常见陷阱

  • 混用坐标空间(用视图空间中的光照计算世界空间法线)会导致细微的着色错误。选定一个空间,并将所有内容转换到该空间。
  • 忘记归一化插值后的法线/方向:插值会缩短向量,因此 dot() 的结果会产生偏差。请在片元阶段调用 normalize()。
  • 跨引擎的 UV 假设。 有些引擎会翻转 V(原点位于左上角还是左下角);纹理可能会显示为上下颠倒。请了解所用引擎的约定。
  • 繁重的分支/动态循环会让 GPU 停滞。优先使用 step/smoothstep/mix;只有在确实能以低成本提前退出时才使用 if/discard。
  • discard 会破坏 early-Z,并可能影响采用分块渲染的移动 GPU 的性能;条件允许时,优先使用 Alpha 混合。
  • 移动设备上的精度:highp 与 mediump 的区别很重要;低精度下,较大的 UV 值或时间值会产生闪烁。坐标和时间应使用足够的精度。
  • 不要假设 GLSL 等同于 HLSL。 mix↔lerp、fract↔frac、texture()↔.Sample()、vec2↔float2、矩阵的列主序与行主序。请参阅参考映射表。

参考资料

  • references/effects.md — 完整大纲(2D 精灵 + 3D)、渐晕和色彩分级着色器;GLSL↔HLSL 函数/类型映射表;各引擎说明(Godot canvas_item/spatial、Unity ShaderLab/HLSL、Unreal 材质节点)。

相关技能

  • godot-shaders — Godot 着色语言语法、内置功能和屏幕读取。
  • unreal-niagara — GPU 粒子 VFX(着色器的另一种用途)。
  • procedural-gen — 驱动溶解和程序化纹理的噪声。

评论

支持 Markdown