关于 shader-programming
面向学习或编写 GPU 顶点与片段着色器的开发者,提供跨引擎着色器编程指导。内容以 GLSL 通用基础为主,并提供 HLSL 对照,涵盖常见视觉效果与着色器易错点。
主要功能
- 01顶点与片段着色器基础
- 02GLSL 与 HLSL 概念对照
- 03UV 与坐标空间指引
- 04常见效果模式
- 05性能与平台注意事项
适用场景
- 01编写滚动纹理着色器
- 02制作溶解或边缘光效果
- 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。对于后处理堆栈,请参考引擎的渲染器设置。
核心工作流
- 明确当前所处的阶段。 顶点着色器会将每个顶点变换到裁剪空间,并传递数据(UV、法线);片段/像素着色器会对每个光栅化像素运行并输出颜色。大多数游戏效果都在片段阶段实现。
- 跟踪坐标空间。 位置在模型 → 世界 → 视图 → 裁剪空间之间变换;法线属于世界空间或视图空间。混用坐标空间是最常见的错误。
- 用 UV 和时间驱动效果。 UV 是
0..1范围内的纹理坐标;对其进行偏移、缩放或扭曲,并使用timeuniform 制作动画。 - 逐像素处理,尽量少用分支。 尽可能使用
mix、step、smoothstep和clamp代替if;GPU 会锁步运行像素,不适合处理分歧分支。 - 通过 uniforms(每次绘制固定不变)和 varyings(在顶点→片段间插值)传递数据。尽量减少纹理采样次数;它们是主要开销。
- 如果工具已可用,先验证源代码,再进行视觉测试。 对于 GLSL,使用匹配的阶段后缀运行
glslangValidator path/to/shader.frag;对于 WGSL,运行naga path/to/shader.wgsl。Godot.gdshader文件需要在 Godot 中打开项目进行检查,因为 Godot 没有独立的验证器。 - 在目标硬件上进行视觉验证。 在桌面设备上看起来正常的着色器,在移动设备上可能会出问题(精度、缺失的功能)。请在实际发布的平台上测试。
模式
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 函数/类型映射表;各引擎说明(Godotcanvas_item/spatial、Unity ShaderLab/HLSL、Unreal 材质节点)。
相关技能
godot-shaders— Godot 着色语言语法、内置功能和屏幕读取。unreal-niagara— GPU 粒子 VFX(着色器的另一种用途)。procedural-gen— 驱动溶解和程序化纹理的噪声。
评论
支持 Markdown