
Shadertoy
- 1.4k installs
- 52 repo stars
- Updated March 4, 2026
- bfollington/terma
shadertoy is an agent skill that this skill should be used when working with shadertoy shaders, glsl fragment shaders, or creating procedural graphics for the web. use when writing .glsl files, implementing visual effect
About
shadertoy is an agent skill from bfollington/terma that this skill should be used when working with shadertoy shaders, glsl fragment shaders, or creating procedural graphics for the web. use when writing .glsl files, implementing visual effects, creating g. # Shadertoy Shader Development ## Overview 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. ## Developers invoke shadertoy during operate/infra work for cloud & infrastructure tasks. The skill documents triggers, prerequisites, and step-by-step workflows grounded in SKILL.md. Compatible with Claude Code, Cursor, and Codex agent runtimes that load marketplace skills. Review the Security Audits panel on this listing before installing in production environments.
- Shadertoy Shader Development
- Writing or editing `.glsl` shader files
- Creating procedural graphics, generative art, or visual effects
- Working with Shadertoy.com projects or WebGL fragment shaders
- Implementing ray marching, distance fields, or procedural textures
Shadertoy by the numbers
- 1,424 all-time installs (skills.sh)
- +6 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #285 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Aug 4, 2026 (Skillselion catalog sync)
shadertoy capabilities & compatibility
- Capabilities
- shadertoy shader development · writing or editing `.glsl` shader files · creating procedural graphics, generative art, or · working with shadertoy.com projects or webgl fra · implementing ray marching, distance fields, or p
- Use cases
- orchestration
What shadertoy says it does
- Writing or editing `.glsl` shader files
- Creating procedural graphics, generative art, or visual effects
- Working with Shadertoy.com projects or WebGL fragment shaders
npx skills add https://github.com/bfollington/terma --skill shadertoyAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.4k |
|---|---|
| repo stars | ★ 52 |
| Security audit | 3 / 3 scanners passed |
| Last updated | March 4, 2026 |
| Repository | bfollington/terma ↗ |
What it does
This skill should be used when working with Shadertoy shaders, GLSL fragment shaders, or creating procedural graphics for the web. Use when writing .glsl files, implementing visual effects, creating g
Who is it for?
Developers working on cloud & infrastructure during operate tasks.
Skip if: Tasks outside Cloud & Infrastructure scope described in SKILL.md.
When should I use this skill?
This skill should be used when working with Shadertoy shaders, GLSL fragment shaders, or creating procedural graphics for the web. Use when writing .glsl files, implementing visual effects, creating g
What you get
Completed cloud & infrastructure workflow aligned with SKILL.md steps.
- GLSL shader snippets
- UV coordinate utilities
- effect pattern templates
Files
Shadertoy Shader Development
Overview
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.
When to Use This Skill
Activate this skill when:
- Writing or editing
.glslshader files - Creating procedural graphics, generative art, or visual effects
- Working with Shadertoy.com projects or WebGL fragment shaders
- Implementing ray marching, distance fields, or procedural textures
- Debugging shader code or optimizing shader performance
- Need GLSL ES syntax reference or Shadertoy input variables
Core Concepts
Shader Entry Point
Every 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);
}Shadertoy Built-in Inputs
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 | 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) |
Coordinate System Setup
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;Common Shader Patterns
1. Procedural Color Palettes
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
);2. Hash Functions (Pseudo-Random)
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);
}3. Ray Marching
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
}4. Rotations
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;
}5. Domain Repetition and Folding
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;
}6. Post-Processing
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.2Multi-Pass Rendering
For complex effects requiring temporal feedback or multiple rendering stages:
Buffer A (Computation):
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// Generate or compute values
fragColor = vec4(computedColor, 1.0);
}Buffer B (Feedback/Blending):
#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 (Final Output):
#define BUFFER_B iChannel1
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
fragColor = texture(BUFFER_B, uv);
}Critical GLSL ES Rules
ALWAYS follow these rules to avoid compilation errors:
1. NO `f` suffix: Use 1.0 NOT 1.0f 2. NO `saturate()`: Use clamp(x, 0.0, 1.0) instead 3. Protect pow/sqrt: Wrap arguments: pow(max(x, 0.0), p), sqrt(abs(x)) 4. Avoid division by zero: Check denominators or add epsilon 5. Initialize variables: Don't assume default values 6. Avoid name conflicts: Don't name functions like variables 7. NO interactive commands: Avoid find, grep - use Glob/Grep tools instead
Workflow Guide
Creating a New Shader
1. Set up coordinate system - Choose appropriate UV normalization 2. Define core effect - Implement main visual algorithm 3. Add animation - Use iTime for temporal variation 4. Apply color palette - Use cosine palette or custom scheme 5. Add post-processing - Vignette, dither, gamma correction 6. Optimize - Reduce iterations, use early exits, minimize branches
Common Tasks
Visualizing complex numbers:
- Use the complex math functions in
references/common-patterns.md - Plot with
cx_log(),cx_pow(), or polynomial evaluation - Map complex results to color via palette
Ray marching 3D scenes:
- Define distance field in
map()function - Set up camera (ray origin
ro, ray directionrd) - March using standard loop pattern
- Calculate normals with tetrahedron method
- Apply lighting and material properties
Creating noise/organic effects:
- Use
hash21()for random values - Implement
fbm()(fractional Brownian motion) for natural variation - Combine with
sin()/cos()for structured patterns - Apply domain warping for organic distortion
Multi-layer composition:
- Render multiple passes with different parameters
- Blend layers using
mix()or custom blend modes - Add interference patterns by comparing layer differences
- Use
smoothstep()for soft transitions
Debugging Strategies
Visualize 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 tilingSimplify progressively:
- Comment out post-processing
- Reduce iteration counts
- Replace complex functions with simple placeholders
- Check coordinate transformations step-by-step
Check for NaN/Inf:
- Add guards:
if (isnan(value) || isinf(value)) return vec3(1.0, 0.0, 0.0); - Validate divisions and roots
Performance Optimization
1. Fixed iteration counts - Avoid dynamic loops 2. Early exit conditions - Break when threshold met 3. Step multiplier tuning - Balance quality vs speed (0.5 to 1.0) 4. Minimize texture reads - Cache repeated lookups 5. Avoid conditionals - Use mix(), step(), smoothstep() instead of if 6. Reduce precision - Use mediump or lowp where appropriate (mobile)
Naming Conventions
Based on observed patterns in creative work:
- Poetic/evocative names - "alien-water", "heavenly-wisp", "comprehension"
- Technical descriptors - "complex-plot", "noise-circuits", "ray-marching-demo"
- Compound phrases - "coming-apart-at-the-seams", "form-without-form"
- Lowercase with hyphens -
my-shader-name.glsl
Attribution and Forking
When 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]Resources
references/glsl-reference.md
Complete GLSL ES syntax reference including:
- Built-in functions (trig, math, vectors, matrices, textures)
- Shadertoy input variables specification
- Type conversions and swizzling
- Common pitfalls and corrections
Search with: Read /references/glsl-reference.md for complete language reference.
references/common-patterns.md
Comprehensive pattern library including:
- Complex number mathematics (cx_mul, cx_div, cx_sin, cx_cos, cx_log, cx_pow)
- Color palette functions (cosine palette, multi-layer palettes)
- Hash functions (hash21, PCG hash)
- Ray marching templates (render loop, normal calculation)
- 3D transformations (rotations, domain folding)
- Distance fields (sphere, box, octahedron)
- Noise functions (simplex, FBM)
- Post-processing (vignette, blur, film grain, gamma)
- Blend modes (soft light, hard light, vivid light)
- Multi-pass rendering patterns
Search with: Grep "pattern" references/common-patterns.md for specific techniques.
references/example-compact-shader.glsl
Reference implementation showing:
- Compact, algorithmic shader coding style
- Efficient ray marching in minimal code
- Advanced matrix operations and transformations
- Creative Commons licensed example
Quick Reference
#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);
}Common Shader Types in Collection
1. Mathematical Visualizations - Complex number plots, function graphs 2. Ray Marched 3D - Distance field rendering, folded geometries 3. Procedural Textures - Noise-based patterns, organic effects 4. Multi-Pass Effects - Temporal feedback, buffer composition 5. Particle Systems - Point-based simulations 6. 2D Patterns - Geometric, kaleidoscopic, interference effects
Tips for Creative Coding
- Start simple - Get basic structure working, then iterate
- Use time creatively -
sin(iTime),mod(iTime, period),smoothstep()transitions - Layer effects - Combine multiple techniques for richness
- Embrace accidents - Bugs often lead to interesting visuals
- Study references - Learn from existing shaders, understand techniques
- Optimize later - Prioritize visual quality first, then performance
Common Shadertoy Patterns and Techniques
This document contains reusable patterns, techniques, and best practices extracted from real shader work.
Coordinate System Setup
Standard UV Normalization (Aspect-Corrected)
// Centers coordinates at (0,0) with aspect ratio correction
vec2 uv = (fragCoord.xy - 0.5 * iResolution.xy) / min(iResolution.y, iResolution.x);
// OR alternative form:
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / min(iResolution.x, iResolution.y);Simple Normalized UV (0 to 1)
vec2 uv = fragCoord / iResolution.xy;Centered UV for Effects
vec2 uv = fragCoord / iResolution.xy - vec2(1.0, 0.5);Complex Number Mathematics
Complex Number Operations
// Complex multiplication
#define cx_mul(a, b) vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x)
// Complex division
#define cx_div(a, b) vec2(((a.x*b.x + a.y*b.y)/(b.x*b.x + b.y*b.y)),((a.y*b.x - a.x*b.y)/(b.x*b.x + b.y*b.y)))
// Complex sine
#define cx_sin(a) vec2(sin(a.x) * cosh(a.y), cos(a.x) * sinh(a.y))
// Complex cosine
#define cx_cos(a) vec2(cos(a.x) * cosh(a.y), -sin(a.x) * sinh(a.y))
// Complex tangent
vec2 cx_tan(vec2 a) {
return cx_div(cx_sin(a), cx_cos(a));
}
// Complex logarithm
vec2 cx_log(vec2 a) {
float rpart = sqrt((a.x * a.x) + (a.y * a.y));
float ipart = atan(a.y, a.x);
if (ipart > PI) ipart = ipart - (2.0 * PI);
return vec2(log(rpart), ipart);
}
// Convert to polar coordinates
vec2 as_polar(vec2 z) {
return vec2(length(z), atan(z.y, z.x));
}
// Complex power
vec2 cx_pow(vec2 v, float p) {
vec2 z = as_polar(v);
return pow(z.x, p) * vec2(cos(z.y * p), sin(z.y * p));
}Color Palettes
Cosine Palette (IQ's Famous Technique)
vec3 palette(float t, vec3 a, vec3 b, vec3 c, vec3 d) {
return a + b * cos(2.0 * PI * (c * t + d));
}
// Example presets:
vec3 chrome(float t) {
return 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
);
}Multi-Layer Palettes with Noise
vec3 palette(float t, int layer) {
vec3[3] a = vec3[](
vec3(0.01, 0.012, 0.015),
vec3(0.012, 0.01, 0.015),
vec3(0.01, 0.013, 0.015)
);
vec3[3] b = vec3[](
vec3(0.03, 0.03, 0.04),
vec3(0.035, 0.025, 0.04),
vec3(0.025, 0.035, 0.04)
);
float noise = hash21(vec2(t, float(layer))) * 0.01;
return a[layer] + b[layer] * (0.5 + 0.5 * sin(t * PI * 2.0)) + noise;
}Hash Functions (Pseudo-Random)
Simple 2D Hash
float hash21(vec2 p) {
p = fract(p * vec2(234.34, 435.345));
p += dot(p, p + 34.23);
return fract(p.x * p.y);
}PCG Hash (High Quality)
uint pcg_hash(uint seed) {
uint state = seed * 747796405u + 2891336453u;
uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
return (word >> 22u) ^ word;
}Ray Marching
Basic Ray Marching Loop
vec3 render(vec3 ro, vec3 rd, float timeOffset) {
float t = 0.0;
float maxd = 10.0;
vec3 col = vec3(0.0);
for (int i = 0; i < 100; i++) {
vec3 p = ro + rd * t;
float d = map(p, timeOffset);
if (d < 0.001) {
// Hit surface - compute lighting
vec3 n = calcNormal(p, timeOffset);
// ... lighting calculations
break;
}
if (t > maxd) break;
t += d * 0.5; // Step multiplier (0.5 for safety)
}
return col;
}Normal Calculation (Tetrahedron Method)
vec3 calcNormal(vec3 p, float timeOffset) {
vec2 e = vec2(0.001, 0.0);
return normalize(vec3(
map(p + e.xyy, timeOffset) - map(p - e.xyy, timeOffset),
map(p + e.yxy, timeOffset) - map(p - e.yxy, timeOffset),
map(p + e.yyx, timeOffset) - map(p - e.yyx, timeOffset)
));
}3D Transformations
Axis-Angle Rotation
void rot(inout vec3 p, vec3 axis, float angle) {
axis = normalize(axis);
float s = sin(angle);
float c = cos(angle);
float 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;
}2D Rotation Matrix
mat2 rot2d(float a) {
float c = cos(a);
float s = sin(a);
return mat2(c, -s, s, c);
}
// Usage:
// p.xy *= rot2d(angle);Domain Folding (Fractal-like Repetition)
vec3 foldRotate(vec3 p, float timeOffset) {
float t = iTime * 0.2 + timeOffset;
rot(p, vec3(sin(t), cos(t), 0.5), t * 0.3);
for (int i = 0; i < 5; i++) {
p = abs(p); // Fold space
rot(p, vec3(0.707, 0.707, 0.0), 0.785);
p -= 0.5 * smoothstep(-1.0, 1.0, sin(iTime * 0.1 + timeOffset));
}
return p;
}Distance Fields (SDFs)
Octahedron
float sdOctahedron(vec3 p, float s) {
p = abs(p);
float m = p.x + p.y + p.z - s;
return m * 0.57735027;
}Sphere
float sdSphere(vec3 p, float r) {
return length(p) - r;
}Box
float sdBox(vec3 p, vec3 b) {
vec3 q = abs(p) - b;
return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
}Noise Functions
Simplex Noise 3D
// (Full implementation in glsl-reference.md or use texture-based noise)
float snoise(vec3 v) {
// ... simplex noise implementation
}FBM (Fractional Brownian Motion)
float fbm(vec3 p) {
float value = 0.0;
float amplitude = 0.5;
float frequency = 1.0;
for (int i = 0; i < 5; i++) {
value += amplitude * snoise(p * frequency);
frequency *= 2.0;
amplitude *= 0.5;
}
return value;
}Post-Processing Effects
Vignette
float vignette(vec2 uv) {
uv *= 1.0 - uv.yx;
float vig = uv.x * uv.y * 15.0;
return pow(vig, 0.25);
}Film Grain / Dithering
// Add subtle noise to reduce banding
float dither = hash21(fragCoord + iTime) * 0.001;
finalCol += dither;Gamma Correction
// Apply gamma correction for proper color output
finalCol = pow(finalCol, vec3(0.45)); // ~1/2.2Blur (9-tap Gaussian)
vec3 blur9(vec2 p, vec2 resolution, vec2 direction) {
vec3 color = vec3(0.0);
vec2 off1 = vec2(1.3846153846) * direction;
vec2 off2 = vec2(3.2307692308) * direction;
color += pixel(p) * 0.2270270270;
color += pixel(p + (off1 / resolution)) * 0.3162162162;
color += pixel(p - (off1 / resolution)) * 0.3162162162;
color += pixel(p + (off2 / resolution)) * 0.0702702703;
color += pixel(p - (off2 / resolution)) * 0.0702702703;
return color;
}Blend Modes
Soft Light
float softLight(float s, float d) {
return (s < 0.5) ? d - (1.0 - 2.0 * s) * d * (1.0 - d)
: (d < 0.25) ? d + (2.0 * s - 1.0) * d * ((16.0 * d - 12.0) * d + 3.0)
: d + (2.0 * s - 1.0) * (sqrt(d) - d);
}
vec3 softLight(vec3 s, vec3 d) {
return vec3(softLight(s.x, d.x), softLight(s.y, d.y), softLight(s.z, d.z));
}Hard Light
float hardLight(float s, float d) {
return (s < 0.5) ? 2.0 * s * d : 1.0 - 2.0 * (1.0 - s) * (1.0 - d);
}Multi-Pass Rendering
Buffer Setup Pattern
// Buffer A (a.glsl) - Computation/generation
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// ... compute values, store in fragColor
}
// Buffer B (b.glsl) - Temporal blending/feedback
#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-feedback
fragColor = mix(previous, current, 0.1); // Blend factor
}
// Main (main.glsl) - Final output
#define BUFFER_B iChannel1
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
fragColor = texture(BUFFER_B, uv);
}Time-Based Animation
Smooth Periodic Motion
float t = iTime * 0.2; // Scale time
float wave = sin(t) * 0.5 + 0.5; // 0 to 1
float smooth_wave = smoothstep(0.0, 1.0, wave);Camera Orbit
vec3 ro = vec3(0.0, 0.0, -4.0);
vec3 rd = normalize(vec3(uv, 2.0));
rot(ro, vec3(1.0, 1.0, 0.0), iTime * 0.12);
rot(rd, vec3(1.0, 1.0, 0.0), iTime * 0.12);Performance Tips
1. Loop Unrolling: Use fixed iteration counts, not dynamic 2. Early Exit: Check distance thresholds to break ray marching early 3. Step Multiplier: Use t += d * 0.5 instead of t += d for safety vs speed tradeoff 4. Minimize Texture Reads: Cache texture lookups when used multiple times 5. Avoid Branches: Use mix() and step() instead of if statements when possible 6. Dithering: Add small noise to reduce banding artifacts from limited precision
Common Constants
#define PI 3.1415926535897932384626433832795
#define TAU 6.283185307179586
#define PHI 1.618033988749895 // Golden ratioDebugging Techniques
Visualize Distance Field
fragColor = vec4(vec3(map(p)), 1.0); // Bright = far, dark = nearVisualize Normals
vec3 n = calcNormal(p);
fragColor = vec4(n * 0.5 + 0.5, 1.0); // Map -1..1 to 0..1Visualize UV Space
fragColor = vec4(fract(uv), 0.0, 1.0); // Shows UV tiling/*================================
= Liquid Tech =
= Author: Jaenam =
================================*/
// Date: 2025-10-19
// License: Creative Commons (CC BY-NC-SA 4.0)
void mainImage( out vec4 O, vec2 I )
{
float i,d,s;
vec3 p, r = iResolution;
mat2 R = mat2(cos(iTime/2.+vec4(0,33,11,0)));
for(O*=i; i++<1e2; O+=max(1.3*sin(vec4(3,2,1,1)+i*.3)/s,-length(p*p)))
p = vec3((I+I - r.xy)/r.y*d*R, d-8.), p.xz*=R,
d+=s=.012+.08*abs(max(sin(dot(p.yzx,p)/.7),length(p)-4.)-i/1e2);
O=tanh(O*O/8e5);
}
/* Twigl version
https://x.com/Jaenam97/status/1979924313215033855
*/
This help only covers the parts of GLSL ES that are relevant for Shadertoy. For the complete specification please have a look at GLSL ES specification
Language:
Version: WebGL 2.0 Arithmetic: ( ) + - ! * / % Logical/Relatonal: ~ < > <= >= == != && || Bit Operators: & ^ | << >> Comments: // /* */ Types: void bool int uint float vec2 vec3 vec4 bvec2 bvec3 bvec4 ivec2 ivec3 ivec4 uvec2 uvec3 uvec4 mat2 mat3 mat4 mat?x? sampler2D, sampler3D samplerCube Format: float a = 1.0; int b = 1; uint i = 1U; int i = 0x1; Function Parameter Qualifiers: [none] in out inout Global Variable Qualifiers: const Vector Components: .xyzw .rgba .stpq Flow Control: if else for return break continue switch/case Output: vec4 fragColor Input: vec2 fragCoord Preprocessor: # #define #undef #if #ifdef #ifndef #else #elif #endif #error #pragma #line
Built-in Functions:
| function | description |
|---|---|
type `radians` (type degrees) | degrees to radians |
type `degrees` (type radians) | radians to degrees |
type `sin` (type angle) | |
type `cos` (type angle) | |
type `tan` (type angle) | |
type `asin` (type x) | |
type `acos` (type x) | |
type `atan` (type y, type x) | |
type `atan` (type y_over_x) | |
type `sinh` (type x) | |
type `cosh` (type x) | |
type `tanh` (type x) | |
type `asinh` (type x) | |
type `acosh` (type x) | |
type `atanh` (type x) | |
type `pow` (type x, type y) | |
type `exp` (type x) | |
type `log` (type x) | |
type `exp2` (type x) | |
type `log2` (type x) | |
type `sqrt` (type x) | |
type `inversesqrt` (type x) | |
type `abs` (type x) | |
type `sign` (type x) | |
type `floor` (type x) | |
type `ceil` (type x) | |
type `trunc` (type x) | |
type `fract` (type x) | the fractional part of x. Same as x - floor(x). |
type `mod` (type x, float y) | modulo |
type `modf` (type x, out type i) | |
type `min` (type x, type y) | |
type `max` (type x, type y) | |
type `clamp` (type x, type minV, type maxV) | |
type `mix` (type x, type y, type a) | |
type `step` (type edge, type x) | |
type `smoothstep` (type a, type b, type x) | |
float `length` (type x) | |
float `distance` (type p0, type p1) | |
float `dot` (type x, type y) | |
vec3 `cross` (vec3 x, vec3 y) | |
type `normalize` (type x) | |
type `faceforward` (type N, type I, type Nref) | |
type `reflect` (type I, type N) | |
type `refract` (type I, type N,float eta) | |
float `determinant` (mat? m) | |
mat?x? `outerProduct` (vec? c, vec? r) | |
type `matrixCompMult` (type x, type y) | |
type `inverse` (type inverse) | |
type `transpose` (type inverse) | |
vec4 `texture` ( sampler? , vec? coord [, float bias]) | |
vec4 `textureLod` ( sampler, vec? coord, float lod) | |
vec4 `textureLodOffset` ( sampler? sampler, vec? coord, float lod, ivec? offset) | |
vec4 `textureGrad` ( sampler? , vec? coord, vec2 dPdx, vec2 dPdy) | |
vec4 textureGradOffset sampler? , vec? coord, vec? dPdx, vec? dPdy, vec? offset) | |
vec4 `textureProj` ( sampler? , vec? coord [, float bias]) | |
vec4 `textureProjLod` ( sampler? , vec? coord, float lod) | |
vec4 `textureProjLodOffset` ( sampler? , vec? coord, float lod, vec? offset) | |
vec4 `textureProjGrad` ( sampler? , vec? coord, vec2 dPdx, vec2 dPdy) | |
vec4 `texelFetch` ( sampler? , ivec? coord, int lod) | |
vec4 `texelFetchOffset` ( sampler?, ivec? coord, int lod, ivec? offset ) | |
ivec? `textureSize` ( sampler? , int lod) | |
type `dFdx` (type x) | |
type `dFdy` (type x) | |
type `fwidth` (type p) | the sum of the absolute value of derivatives in x and y |
type `isnan` (type x) | |
type `isinf` (type x) | |
float `intBitsToFloat` (int v) | |
uint `uintBitsToFloat` (uint v) | |
int `floatBitsToInt` (float v) | |
uint `floatBitsToUint` (float v) | |
uint `packSnorm2x16` (vec2 v) | |
uint `packUnorm2x16` (vec2 v) | |
vec2 `unpackSnorm2x16` (uint p) | |
vec2 `unpackUnorm2x16` (uint p) | |
bvec `lessThan` (type x, type y) | |
bvec `lessThanEqual` (type x, type y) | |
bvec `greaterThan` (type x, type y) | |
bvec `greaterThanEqual` (type x, type y) | |
bvec `equal` (type x, type y) | |
bvec `notEqual` (type x, type y) | |
bool `any` (bvec x) | |
bool `all` (bvec x) | |
bvec `not` (bvec x) |
Conversions
- Int to Float:
int(uv.x * 3.0)
How-to
Use structs: struct myDataType { float occlusion; vec3 color; }; myDataType myData = myDataType(0.7, vec3(1.0, 2.0, 3.0)); Initialize arrays: float[] x = float[] (0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6); Do conversions: int a = 3; float b = float(a); Do component swizzling: vec4 a = vec4(1.0,2.0,3.0,4.0); vec4 b = a.zyyw; Access matrix components: mat4 m; m[1] = vec4(2.0); m[0][0] = 1.0; m[2][3] = 2.0;
Be careful!
the f suffix for floating point numbers: 1.0f is illegal in GLSL. You must use 1.0 saturate(): saturate(x) doesn't exist in GLSL. Use clamp(x,0.0,1.0) instead pow/sqrt: please don't feed sqrt() and pow() with negative numbers. Add an abs() or max(0.0, x) to the argument mod: please don't do mod(x,0.0). This is undefined in some platforms variables: initialize your variables! Don't assume they'll be set to zero by default functions: don't name your functions the same as some of your variables
Shadertoy Inputs
| type | name | description |
|---|---|---|
vec3 | iResolution | image/buffer The viewport resolution (z is pixel aspect ratio, usually 1.0) |
float | iTime | image/sound/buffer Current time in seconds |
float | iTimeDelta | image/buffer Time it takes to render a frame, in seconds |
int | iFrame | image/buffer Current frame |
float | iFrameRate | image/buffer Number of frames rendered per second |
float | iChannelTime[4] | image/buffer Time for channel (if video or sound), in seconds |
vec3 | iChannelResolution[4] | image/buffer/sound Input texture resolution for each channel |
vec4 | iMouse | image/buffer xy = current pixel coords (if LMB is down). zw = click pixel |
sampler2D | iChannel{i} | image/buffer/sound Sampler for input textures i |
vec4 | iDate | image/buffer/sound Year, month, day, time in seconds in .xyzw |
float | iSampleRate | image/buffer/sound The sound sample rate (typically 44100) |
Shadertoy Outputs
Image shaders:
fragColor is used as output channel. It is not, for now, mandatory but recommended to leave the alpha channel to 1.0.
Sound shaders:
the mainSound() function returns a vec2 containing the left and right (stereo) sound channel wave data.
Related skills
How it compares
Pick shadertoy over generic graphics skills when the task is GLSL fragment-shader math and Shadertoy conventions, not 3D engine scene graphs.
FAQ
What does shadertoy do?
This skill should be used when working with Shadertoy shaders, GLSL fragment shaders, or creating procedural graphics for the web. Use when writing .glsl files, implementing visual effects, creating g
When should I use shadertoy?
During operate infra work for cloud & infrastructure.
Is shadertoy safe to install?
Review the Security Audits panel on this listing before production use.