关于 shadertoy
用于编写 Shadertoy 风格 GLSL 片段着色器的开发参考,面向制作程序化图形和视觉效果的艺术家与开发者,提供语法说明及光线步进、多通道渲染、调试和优化模式。
主要功能
- 01GLSL ES 语法与 Shadertoy 输入
- 02程序化图形和配色模式
- 03光线步进与距离场
- 04多通道渲染和反馈
- 05着色器调试与性能指导
- 06参考模式和示例着色器
适用场景
- 01创作动画程序化视觉效果
- 02构建光线步进 3D 场景
- 03开发带反馈的多通道效果
- 04调试或优化 GLSL 着色器
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ ckorhonen/ claude-skills --skill shadertoy安装后在 Claude Code 中输入/shadertoy确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/common-patterns.mdexample-compact-shader.glslglsl-reference.md详细介绍
Shadertoy 着色器开发
概述
Shadertoy 是一个用于创建和分享 GLSL 片段着色器的平台,这些着色器通过 WebGL 在浏览器中运行。本技能全面介绍了着色器编写指南,包括 GLSL ES 语法、常见模式、数学技巧,以及实时程序化图形的最佳实践。
何时使用此技能
在以下情况下启用此技能:
- 编写或编辑
.glsl着色器文件 - 创建程序化图形、生成艺术或视觉效果
- 使用 Shadertoy.com 项目或 WebGL 片段着色器
- 实现光线步进、距离场或程序化纹理
- 调试着色器代码或优化着色器性能
- 需要 GLSL ES 语法参考或 Shadertoy 输入变量信息
核心概念
着色器入口点
每个 Shadertoy 着色器都会实现 mainImage 函数:
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
// fragCoord: pixel coordinates (0 to iResolution.xy)
// fragColor: output color (RGBA, typically alpha = 1.0)
vec2 uv = fragCoord / iResolution.xy;
fragColor = vec4(uv, 0.0, 1.0);
}
Shadertoy 内置输入
着色器中始终可用:
| 类型 | 名称 | 描述 |
|---|---|---|
vec3 | iResolution | 视口分辨率(x、y、宽高比) |
float | iTime | 当前时间(秒)(主要动画驱动变量) |
float | iTimeDelta | 渲染一帧所需的时间 |
int | iFrame | 当前帧数 |
vec4 | iMouse | 鼠标:xy = 当前位置,zw = 点击位置 |
sampler2D | iChannel0-iChannel3 | 输入纹理/缓冲区 |
vec3 | iChannelResolution[4] | 每个输入通道的分辨率 |
vec4 | iDate | 年、月、日、时间(秒)(.xyzw) |
坐标系设置
坐标归一化的标准模式:
// Aspect-corrected UV centered at origin (-1 to 1, aspect-preserved)
vec2 uv = (fragCoord.xy - 0.5 * iResolution.xy) / min(iResolution.y, iResolution.x);
// Alternative compact form:
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / min(iResolution.x, iResolution.y);
// Simple normalized (0 to 1)
vec2 uv = fragCoord / iResolution.xy;
常见着色器模式
1. 程序化调色板
使用 Inigo Quilez 的余弦调色板实现平滑的颜色渐变:
vec3 palette(float t, vec3 a, vec3 b, vec3 c, vec3 d) {
return a + b * cos(6.28318 * (c * t + d));
}
// Example usage:
vec3 col = palette(
t,
vec3(0.5, 0.5, 0.5), // base
vec3(0.5, 0.5, 0.5), // amplitude
vec3(1.0, 1.0, 0.5), // frequency
vec3(0.8, 0.90, 0.30) // phase
);
2. 哈希函数(伪随机)
用于噪声和随机性的简单 2D 哈希:
float hash21(vec2 p) {
p = fract(p * vec2(234.34, 435.345));
p += dot(p, p + 34.23);
return fract(p.x * p.y);
}
3. 光线步进
通过球体追踪进行 3D 渲染的标准模式:
// Distance field function
float map(vec3 p) {
return length(p) - 1.0; // Sphere at origin, radius 1
}
// Normal calculation
vec3 calcNormal(vec3 p) {
vec2 e = vec2(0.001, 0.0);
return normalize(vec3(
map(p + e.xyy) - map(p - e.xyy),
map(p + e.yxy) - map(p - e.yxy),
map(p + e.yyx) - map(p - e.yyx)
));
}
// Ray marching loop
vec3 render(vec3 ro, vec3 rd) {
float t = 0.0;
for (int i = 0; i < 100; i++) {
vec3 p = ro + rd * t;
float d = map(p);
if (d < 0.001) {
// Hit - calculate lighting
vec3 n = calcNormal(p);
return n * 0.5 + 0.5; // Normal visualization
}
if (t > 10.0) break;
t += d * 0.5; // Step (0.5 factor for safety)
}
return vec3(0.0); // Miss
}
4. 旋转
2D 旋转:
mat2 rot2d(float a) {
float c = cos(a), s = sin(a);
return mat2(c, -s, s, c);
}
// Usage: p.xy *= rot2d(iTime);
3D 轴角旋转(原地修改):
void rot(inout vec3 p, vec3 axis, float angle) {
axis = normalize(axis);
float s = sin(angle), c = cos(angle), oc = 1.0 - c;
mat3 m = mat3(
oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s,
oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s,
oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c
);
p = m * p;
}
5. 域重复与折叠
创建类似分形的结构:
vec3 foldRotate(vec3 p, float timeOffset) {
for (int i = 0; i < 5; i++) {
p = abs(p); // Mirror fold
rot(p, vec3(0.707, 0.707, 0.0), 0.785);
p -= 0.5; // Translate
}
return p;
}
6. 后期处理
暗角:
float vignette(vec2 uv) {
uv *= 1.0 - uv.yx;
return pow(uv.x * uv.y * 15.0, 0.25);
}
胶片颗粒/抖动(减少色带):
float dither = hash21(fragCoord + iTime) * 0.001;
finalCol += dither;
伽马校正:
finalCol = pow(finalCol, vec3(0.45)); // ~1/2.2
多通道渲染
用于需要时间反馈或多个渲染阶段的复杂效果:
Buffer A(计算):
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// Generate or compute values
fragColor = vec4(computedColor, 1.0);
}
Buffer B(反馈/混合):
#define BUFFER_A iChannel0
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
vec4 current = texture(BUFFER_A, uv);
vec4 previous = texture(iChannel1, uv); // Self-reference
fragColor = mix(previous, current, 0.1); // Temporal blend
}
Main(最终输出):
#define BUFFER_B iChannel1
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
fragColor = texture(BUFFER_B, uv);
}
GLSL ES 关键规则
务必遵循以下规则,以避免编译错误:
- 不要使用
f后缀:使用1.0,不要用1.0f - 不要使用
saturate():改用clamp(x, 0.0, 1.0) - 保护 pow/sqrt:封装参数:
pow(max(x, 0.0), p)、sqrt(abs(x)) - 避免除以零:检查分母或添加 epsilon
- 初始化变量:不要假设变量有默认值
- 避免名称冲突:不要将函数命名为与变量相同的名称
- 不要使用交互式命令:避免使用
find、grep,改用 Glob/Grep 工具
工作流指南
创建新着色器
- 设置坐标系 - 选择合适的 UV 归一化方式
- 定义核心效果 - 实现主要视觉算法
- 添加动画 - 使用
iTime实现时间变化 - 应用调色板 - 使用余弦调色板或自定义方案
- 添加后期处理 - 暗角、抖动、伽马校正
- 优化 - 减少迭代次数、尽早退出、尽量减少分支
常见任务
可视化复数:
- 使用
references/common-patterns.md中的复数数学函数 - 使用
cx_log()、cx_pow()或多项式求值绘图 - 通过调色板将复数结果映射为颜色
对 3D 场景进行光线步进:
- 在
map()函数中定义距离场 - 设置摄像机(光线原点
ro、光线方向rd) - 使用标准循环模式进行步进
- 使用四面体法计算法线
- 应用光照和材质属性
创建噪声/有机效果:
- 使用
hash21()获取随机值 - 实现
fbm()(分形布朗运动)以产生自然变化 - 与
sin()/cos()结合,生成有序图案 - 应用域扭曲,实现有机变形
多层合成:
- 使用不同参数渲染多个通道
- 使用
mix()或自定义混合模式混合图层 - 比较图层差异,添加干涉图案
- 使用
smoothstep()实现平滑过渡
调试策略
可视化中间值:
fragColor = vec4(vec3(distanceField), 1.0); // Show distance
fragColor = vec4(normal * 0.5 + 0.5, 1.0); // Show normals
fragColor = vec4(fract(uv), 0.0, 1.0); // Show UV tiling
逐步简化:
- 注释掉后期处理
- 减少迭代次数
- 将复杂函数替换为简单占位函数
- 逐步检查坐标变换
检查 NaN/Inf:
- 添加保护:
if (isnan(value) || isinf(value)) return vec3(1.0, 0.0, 0.0); - 验证除法和开方运算
性能优化
- 固定迭代次数 - 避免动态循环
- 提前退出条件 - 达到阈值时跳出
- 调整步长乘数 - 平衡质量与速度(0.5 到 1.0)
- 尽量减少纹理读取 - 缓存重复查询结果
- 避免条件语句 - 使用
mix()、step()、smoothstep()代替if - 降低精度 - 在适当情况下(移动设备)使用
mediump或lowp
命名约定
根据创意作品中观察到的模式:
- 富有诗意/意境的名称 - “alien-water”、“heavenly-wisp”、“comprehension”
- 技术描述性名称 - “complex-plot”、“noise-circuits”、“ray-marching-demo”
- 复合短语 - “coming-apart-at-the-seams”、“form-without-form”
- 使用小写字母和连字符 -
my-shader-name.glsl
署名和分支
分支或改编着色器时:
// Fork of "Original Name" by AuthorName. https://shadertoy.com/view/XxXxXx
// Date: YYYY-MM-DD
// License: Creative Commons (CC BY-NC-SA 4.0) [or other]
资源
references/glsl-reference.md
完整的 GLSL ES 语法参考,包括:
- 内置函数(三角函数、数学函数、向量、矩阵、纹理)
- Shadertoy 输入变量规范
- 类型转换和分量重排
- 常见陷阱及修正方法
使用以下命令搜索完整语言参考:Read /references/glsl-reference.md。
references/common-patterns.md
全面的模式库,包括:
- 复数数学(cx_mul、cx_div、cx_sin、cx_cos、cx_log、cx_pow)
- 调色板函数(余弦调色板、多层调色板)
- 哈希函数(hash21、PCG 哈希)
- 光线步进模板(渲染循环、法线计算)
- 3D 变换(旋转、域折叠)
- 距离场(球体、立方体、八面体)
- 噪声函数(单纯形噪声、FBM)
- 后期处理(暗角、模糊、胶片颗粒、伽马)
- 混合模式(柔光、强光、亮光)
- 多通道渲染模式
使用以下命令搜索特定技巧:Grep "pattern" references/common-patterns.md。
references/example-compact-shader.glsl
参考实现,展示:
- 简洁、算法化的着色器编码风格
- 以精简代码高效实现光线步进
- 高级矩阵运算和变换
- 采用 Creative Commons 许可的示例
快速参考
#define PI 3.1415926535897932384626433832795
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
// 1. Normalize coordinates
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / min(iResolution.x, iResolution.y);
// 2. Compute effect
float d = length(uv) - 0.5; // Circle distance field
vec3 col = vec3(smoothstep(0.01, 0.0, d)); // Sharp edge
// 3. Animate with time
col *= 0.5 + 0.5 * sin(iTime + uv.xyx * 3.0);
// 4. Apply palette
col = palette(col.x, vec3(0.5), vec3(0.5), vec3(1.0), vec3(0.0));
// 5. Post-process
col = pow(col, vec3(0.45)); // Gamma
col *= vignette(fragCoord / iResolution.xy);
// 6. Output
fragColor = vec4(col, 1.0);
}
集合中常见的着色器类型
- 数学可视化 - 复数图、函数图
- 光线步进 3D - 距离场渲染、折叠几何体
- 程序化纹理 - 基于噪声的图案、有机效果
- 多通道效果 - 时间反馈、缓冲区合成
- 粒子系统 - 基于点的模拟
- 2D 图案 - 几何、万花筒、干涉效果
创意编码技巧
- 从简单开始 - 先让基本结构运行起来,再逐步迭代
- 巧用时间 - 使用
sin(iTime)、mod(iTime, period)、smoothstep()进行过渡 - 叠加效果 - 结合多种技巧,让效果更加丰富
- 拥抱意外 - Bug 往往能带来有趣的视觉效果
- 研究参考案例 - 从现有着色器中学习,理解其中的技巧
- 稍后再优化 - 优先提升视觉质量,然后再关注性能
评论
支持 Markdown