shadertoy by bfollington/terma
npx skills add https://github.com/bfollington/terma --skill shadertoyShadertoy 是一个用于创建和分享 GLSL 片段着色器的平台,这些着色器使用 WebGL 在浏览器中运行。本技能为编写着色器提供了全面的指导,包括 GLSL ES 语法、常见模式、数学技巧以及实时程序化图形特有的最佳实践。
在以下情况下激活此技能:
.glsl 着色器文件每个 Shadertoy 着色器都实现 mainImage 函数:
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
// fragCoord: 像素坐标 (0 到 iResolution.xy)
// fragColor: 输出颜色 (RGBA, 通常 alpha = 1.0)
vec2 uv = fragCoord / iResolution.xy;
fragColor = vec4(uv, 0.0, 1.0);
}
着色器中始终可用:
| 类型 | 名称 |
|---|
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 描述 |
|---|
vec3 | iResolution | 视口分辨率 (x, y, 宽高比) |
float | iTime | 当前时间(秒)(主要动画驱动) |
float | iTimeDelta | 渲染一帧的时间 |
int | iFrame | 当前帧号 |
vec4 | iMouse | 鼠标:xy = 当前位置,zw = 点击位置 |
sampler2D | iChannel0-iChannel3 | 输入纹理/缓冲区 |
vec3 | iChannelResolution[4] | 每个输入通道的分辨率 |
vec4 | iDate | 年、月、日、时间(秒)(.xyzw) |
归一化坐标的标准模式:
// 以原点为中心且保持宽高比的 UV (-1 到 1)
vec2 uv = (fragCoord.xy - 0.5 * iResolution.xy) / min(iResolution.y, iResolution.x);
// 替代的紧凑形式:
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / min(iResolution.x, iResolution.y);
// 简单的归一化 (0 到 1)
vec2 uv = fragCoord / iResolution.xy;
使用 Inigo Quilez 的余弦调色板实现平滑的颜色渐变:
vec3 palette(float t, vec3 a, vec3 b, vec3 c, vec3 d) {
return a + b * cos(6.28318 * (c * t + d));
}
// 示例用法:
vec3 col = palette(
t,
vec3(0.5, 0.5, 0.5), // 基础色
vec3(0.5, 0.5, 0.5), // 振幅
vec3(1.0, 1.0, 0.5), // 频率
vec3(0.8, 0.90, 0.30) // 相位
);
用于噪声和随机性的简单 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);
}
通过球体追踪进行 3D 渲染的标准模式:
// 距离场函数
float map(vec3 p) {
return length(p) - 1.0; // 原点处的球体,半径 1
}
// 法线计算
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)
));
}
// 光线步进循环
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) {
// 命中 - 计算光照
vec3 n = calcNormal(p);
return n * 0.5 + 0.5; // 法线可视化
}
if (t > 10.0) break;
t += d * 0.5; // 步进 (0.5 因子用于安全)
}
return vec3(0.0); // 未命中
}
2D 旋转:
mat2 rot2d(float a) {
float c = cos(a), s = sin(a);
return mat2(c, -s, s, c);
}
// 用法: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;
}
创建分形结构:
vec3 foldRotate(vec3 p, float timeOffset) {
for (int i = 0; i < 5; i++) {
p = abs(p); // 镜像折叠
rot(p, vec3(0.707, 0.707, 0.0), 0.785);
p -= 0.5; // 平移
}
return p;
}
暗角:
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
对于需要时间反馈或多个渲染阶段的复杂效果:
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// 生成或计算值
fragColor = vec4(computedColor, 1.0);
}
#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); // 自引用
fragColor = mix(previous, current, 0.1); // 时间混合
}
#define BUFFER_B iChannel1
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
fragColor = texture(BUFFER_B, uv);
}
务必遵循这些规则以避免编译错误:
f 后缀:使用 1.0,而不是 1.0fsaturate():使用 clamp(x, 0.0, 1.0) 代替pow(max(x, 0.0), p),sqrt(abs(x))find、grep - 改用 Glob/Grep 工具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); // 显示距离
fragColor = vec4(normal * 0.5 + 0.5, 1.0); // 显示法线
fragColor = vec4(fract(uv), 0.0, 1.0); // 显示 UV 平铺
逐步简化:
检查 NaN/Inf:
if (isnan(value) || isinf(value)) return vec3(1.0, 0.0, 0.0);mix()、step()、smoothstep() 代替 ifmediump 或 lowp(移动设备)基于创意工作中观察到的模式:
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) [或其他]
完整的 GLSL ES 语法参考,包括:
搜索:Read /references/glsl-reference.md 获取完整的语言参考。
全面的模式库,包括:
搜索:Grep "pattern" references/common-patterns.md 获取特定技术。
参考实现,展示:
#define PI 3.1415926535897932384626433832795
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
// 1. 归一化坐标
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / min(iResolution.x, iResolution.y);
// 2. 计算效果
float d = length(uv) - 0.5; // 圆形距离场
vec3 col = vec3(smoothstep(0.01, 0.0, d)); // 锐利边缘
// 3. 随时间动画
col *= 0.5 + 0.5 * sin(iTime + uv.xyx * 3.0);
// 4. 应用调色板
col = palette(col.x, vec3(0.5), vec3(0.5), vec3(1.0), vec3(0.0));
// 5. 后期处理
col = pow(col, vec3(0.45)); // 伽马
col *= vignette(fragCoord / iResolution.xy);
// 6. 输出
fragColor = vec4(col, 1.0);
}
sin(iTime)、mod(iTime, period)、smoothstep() 过渡每周安装量
1.2K
仓库
GitHub 星标数
39
首次出现
2026年1月24日
安全审计
安装于
opencode1.0K
gemini-cli1.0K
codex1.0K
github-copilot1.0K
kimi-cli1.0K
amp1.0K
Shadertoy is a platform for creating and sharing GLSL fragment shaders that run in the browser using WebGL. This skill provides comprehensive guidance for writing shaders including GLSL ES syntax, common patterns, mathematical techniques, and best practices specific to real-time procedural graphics.
Activate this skill when:
.glsl shader filesEvery Shadertoy shader implements the mainImage function:
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);
}
Always available in shaders:
| Type | Name | Description |
|---|---|---|
vec3 | iResolution | Viewport resolution (x, y, aspect ratio) |
float | iTime | Current time in seconds (primary animation driver) |
float | iTimeDelta | Time to render one frame |
int |
Standard patterns for normalizing coordinates:
// 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;
Use Inigo Quilez's cosine palette for smooth color gradients:
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
);
Simple 2D hash for noise and randomness:
float hash21(vec2 p) {
p = fract(p * vec2(234.34, 435.345));
p += dot(p, p + 34.23);
return fract(p.x * p.y);
}
Standard pattern for 3D rendering via sphere tracing:
// 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
}
2D rotation:
mat2 rot2d(float a) {
float c = cos(a), s = sin(a);
return mat2(c, -s, s, c);
}
// Usage: p.xy *= rot2d(iTime);
3D axis-angle rotation (modifies in-place):
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;
}
Create fractal-like structures:
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;
}
Vignette:
float vignette(vec2 uv) {
uv *= 1.0 - uv.yx;
return pow(uv.x * uv.y * 15.0, 0.25);
}
Film grain/dithering (reduces banding):
float dither = hash21(fragCoord + iTime) * 0.001;
finalCol += dither;
Gamma correction:
finalCol = pow(finalCol, vec3(0.45)); // ~1/2.2
For complex effects requiring temporal feedback or multiple rendering stages:
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// Generate or compute values
fragColor = vec4(computedColor, 1.0);
}
#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
}
#define BUFFER_B iChannel1
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
fragColor = texture(BUFFER_B, uv);
}
ALWAYS follow these rules to avoid compilation errors:
f suffix: Use 1.0 NOT 1.0fsaturate(): Use clamp(x, 0.0, 1.0) insteadpow(max(x, 0.0), p), sqrt(abs(x))find, - use Glob/Grep tools insteadiTime for temporal variationVisualizing complex numbers:
references/common-patterns.mdcx_log(), cx_pow(), or polynomial evaluationRay marching 3D scenes:
map() functionro, ray direction rd)Creating noise/organic effects:
hash21() for random valuesfbm() (fractional Brownian motion) for natural variationsin()/cos() for structured patternsMulti-layer composition:
mix() or custom blend modessmoothstep() for soft transitionsVisualize intermediate values:
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
Simplify progressively:
Check for NaN/Inf:
if (isnan(value) || isinf(value)) return vec3(1.0, 0.0, 0.0);mix(), step(), smoothstep() instead of ifmediump or lowp where appropriate (mobile)Based on observed patterns in creative work:
my-shader-name.glslWhen forking or remixing shaders:
// 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]
Complete GLSL ES syntax reference including:
Search with: Read /references/glsl-reference.md for complete language reference.
Comprehensive pattern library including:
Search with: Grep "pattern" references/common-patterns.md for specific techniques.
Reference implementation showing:
#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);
}
sin(iTime), mod(iTime, period), smoothstep() transitionsWeekly Installs
1.2K
Repository
GitHub Stars
39
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode1.0K
gemini-cli1.0K
codex1.0K
github-copilot1.0K
kimi-cli1.0K
amp1.0K
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装
iFrame |
| Current frame number |
vec4 | iMouse | Mouse: xy = current position, zw = click position |
sampler2D | iChannel0-iChannel3 | Input textures/buffers |
vec3 | iChannelResolution[4] | Resolution of each input channel |
vec4 | iDate | Year, month, day, time in seconds (.xyzw) |
grep