mcpField
S
shadertoy

shadertoy

github.com/bfollington创意与媒体521.5k 次安装2 天前更新
代码仓库

关于 shadertoy

为 GLSL ES 与 Shadertoy 着色器创作提供指导,适用于生成式图形、视觉效果和 WebGL 片元着色器开发。内容包括常用数学模式、多通道渲染、调试与性能优化。

主要功能

  1. 01GLSL ES 语法与内置变量参考
  2. 02程序化图形和颜色模式
  3. 03光线步进与距离场技巧
  4. 04多通道渲染与反馈
  5. 05着色器调试及性能优化

适用场景

  1. 01编写或修改 .glsl 着色器
  2. 02制作生成艺术和程序化纹理
  3. 03实现光线步进 3D 场景
  4. 04排查着色器编译或数值问题

安装

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

$npx skills add https://github.com/bfollington/terma --skill shadertoy

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
common-patterns.md
example-compact-shader.glsl
glsl-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 内置输入

着色器中始终可用:

类型名称描述
vec3iResolution视口分辨率(x、y、宽高比)
floatiTime当前时间(秒)(主要动画驱动变量)
floatiTimeDelta渲染一帧所需的时间
intiFrame当前帧数
vec4iMouse鼠标:xy = 当前位置,zw = 点击位置
sampler2DiChannel0-iChannel3输入纹理/缓冲区
vec3iChannelResolution[4]每个输入通道的分辨率
vec4iDate年、月、日、时间(秒)(.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 关键规则

务必遵循以下规则,以避免编译错误:

  1. 不要使用 f 后缀:使用 1.0,不要用 1.0f
  2. 不要使用 saturate():改用 clamp(x, 0.0, 1.0)
  3. 保护 pow/sqrt:封装参数:pow(max(x, 0.0), p)、sqrt(abs(x))
  4. 避免除以零:检查分母或添加 epsilon
  5. 初始化变量:不要假设变量有默认值
  6. 避免名称冲突:不要将函数命名为与变量相同的名称
  7. 不要使用交互式命令:避免使用 find、grep,改用 Glob/Grep 工具

工作流指南

创建新着色器
  1. 设置坐标系 - 选择合适的 UV 归一化方式
  2. 定义核心效果 - 实现主要视觉算法
  3. 添加动画 - 使用 iTime 实现时间变化
  4. 应用调色板 - 使用余弦调色板或自定义方案
  5. 添加后期处理 - 暗角、抖动、伽马校正
  6. 优化 - 减少迭代次数、尽早退出、尽量减少分支
常见任务

可视化复数:

  • 使用 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);
  • 验证除法和开方运算

性能优化

  1. 固定迭代次数 - 避免动态循环
  2. 提前退出条件 - 达到阈值时跳出
  3. 调整步长乘数 - 平衡质量与速度(0.5 到 1.0)
  4. 尽量减少纹理读取 - 缓存重复查询结果
  5. 避免条件语句 - 使用 mix()、step()、smoothstep() 代替 if
  6. 降低精度 - 在适当情况下(移动设备)使用 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);
}

集合中常见的着色器类型

  1. 数学可视化 - 复数图、函数图
  2. 光线步进 3D - 距离场渲染、折叠几何体
  3. 程序化纹理 - 基于噪声的图案、有机效果
  4. 多通道效果 - 时间反馈、缓冲区合成
  5. 粒子系统 - 基于点的模拟
  6. 2D 图案 - 几何、万花筒、干涉效果

创意编码技巧

  • 从简单开始 - 先让基本结构运行起来,再逐步迭代
  • 巧用时间 - 使用 sin(iTime)、mod(iTime, period)、smoothstep() 进行过渡
  • 叠加效果 - 结合多种技巧,让效果更加丰富
  • 拥抱意外 - Bug 往往能带来有趣的视觉效果
  • 研究参考案例 - 从现有着色器中学习,理解其中的技巧
  • 稍后再优化 - 优先提升视觉质量,然后再关注性能

评论

支持 Markdown