GLSL / WGSL Guide
๐ Select your role above to see customized content
External Resource Library
41 hand-picked resources โ tutorials, tools, communities
The Book of Shaders
Step-by-step guide to fragment shaders โ the most referenced GLSL learning resource. Open source.
Inigo Quilez โ Articles & Tutorials
SDFs, ray marching, soft shadows, color palettes โ the bible of advanced GLSL techniques by Shadertoy's co-creator.
An Introduction to Shader Art Coding โ kishimisu
The most-watched beginner tutorial for shader art on Shadertoy. Hundreds of thousands of views.
Level
Domain
41 resource(s)
Step-by-step guide to fragment shaders โ the most referenced GLSL learning resource. Open source.
BeginnerSDFs, ray marching, soft shadows, color palettes โ the bible of advanced GLSL techniques by Shadertoy's co-creator.
AdvancedThe most-watched beginner tutorial for shader art on Shadertoy. Hundreds of thousands of views.
BeginnerFriendly GLSL tutorials: ray marching, fractals, game effects โ excellent for beginners.
BeginnerVectors, interpolation, Bezier curves, signed distances โ beautifully animated math for shaders.
BeginnerDeep dive into value noise, fbm and domain warping in GLSL.
IntermediateLive coding sessions and explanations of advanced ray marching, SDF operations and rendering.
AdvancedBrowser-level WebGL: buffers, shaders, textures โ useful for understanding the pipeline.
IntermediateOfficial Shadertoy shader tutorials โ uniforms, ray marching, noise, directly runnable.
BeginnerLive GLSL editor in the browser โ instant feedback, huge public shader gallery.
BeginnerThe premier online GLSL editor and community. Thousands of shared shaders with source code.
BeginnerExhaustive written guide to raw WebGL โ vertices, textures, transforms, lighting.
Beginner๐ Shader Templates
Jump-start your shader with a ready-to-run template. Click "Use" to open it in the editor.
Simple color gradient from red to blue
Pulsing circle with time animation
Rotating geometric pattern
Animated wave pattern
Fractal visualization
Water ripple animation
Animated starfield effect
Basic WGSL entry-point โ runs natively on WebGPU. Requires Chrome 113+ / Edge 113+.
Simple animated rainbow in WGSL โ an easy starting point.
โ๏ธ GLSL Fill-in-the-Blank Exercises
Fill in the blanks to test your GLSL understanding. Answers are validated live with WebGL.
Discord Commands Reference
๐ Quick Start
Paste your GLSL code directly into /shader. The bot compiles and returns an animated GIF within seconds. 17 slash commands available โ shaders, AI, audio, collab, marketplace and more.
๐ผ๏ธ Shaders
/shaderMainCompiles and displays a custom GLSL/WGSL shader.
code: Your GLSL code (required)resolution: 480x270 / 960x540 / 1920x1080 (default: 480x270)duration: 0.5โ5.0s (default: 2s)format: gif / webp / png-sequenceview: 2d / 3d (render on 3D mesh)mesh: sphere / cube / torus / plane (when view=3d)texture0โ3: Image URL for iChannel0โ3/shader-presetRuns one of 1,200+ pre-built presets (nebula, matrix, particles, neoncityโฆ). Autocomplete available.
preset: Preset name (autocomplete)resolution / duration / format / view / mesh: Same options as /shader/shader-generateAIGenerates a shader via guided visual parameters. Autocomplete on every option.
shape: Shape (circle, wave, fractalโฆ)color / animation / speed / pattern / background / effect / complexity: Visual options (all optional)resolution / duration / view / mesh: Same options as /shader/shader-promptAIGenerates a full shader from a natural language description (e.g. "purple nebula with twinkling stars").
description: What you want to see (required)resolution / duration / view / mesh: Same options as /shader/shader-codeDisplays the GLSL source code of a preset. Autocomplete available.
name: Preset name (autocomplete)/shader-minecraftMinecraftMinecraft shaders โ OptiFine, Iris and Vibrant Visuals. 50+ dedicated presets.
loader: optifine / iris / vibrantcode / preset: Custom shader or Minecraft preset (optional)/shader-helpSends a link to this guide and the web dashboard.
๐ค AI & Assistant
/aiRAGRAG-powered GLSL assistant. Sub-commands:
/ai ask โ General GLSL / ShaderBot question/ai preset โ Detailed info about a preset/ai suggest โ Suggestions based on your code/ai debug โ Debug a shader/ai analyze โ Deep code analysis/ai image / screenshot / match โ Visual analysis (VLM)/agentAutonomous shader generation agent.
/agent status โ Show status and recent stats/agent generate โ Trigger a generation cycle (admin)๐ต Audio & Media
/audioAudio-reactive shaders from a Discord voice channel.
/audio join โ Bot joins the voice channel/audio leave โ Bot leaves the voice channel/audio shader โ Renders an audio-reactive shader (audio_bars, audio_pulse, audio_spectrum)/musicAudioCraftAI music generation via AudioCraft (Meta). Returns a .wav file.
/music generate โ Generates a clip from a prompt, style and duration๐ Data & Visualisation
/datavizRenders charts (bar, line, pie, scatter, heatmapโฆ) as animated shader GIFs.
/dataviz-liveWebSocketLive data visualisation via WebSocket.
/dataviz-live connect โ [url] [jsonpath] [min] [max]๐ค Collaboration & Streaming
/collabReal-time collaborative shader editing.
/collab start โ [preset] โ create a session/collab join / leave / snapshot โ Join, leave or snapshot/sceneOBSOBS scenes โ create browser sources pointing to your shaders.
/scene create โ [preset] โ returns an OBS Browser Source URL/scene list / delete โ List or delete your scenes/streamTwitchTwitch overlay โ connect a shader stream to your broadcast.
/stream connect โ [username] [preset]/stream shader / disconnect โ Change shader or disconnect๐ Marketplace
/marketplaceBuy, sell and manage shaders on the community marketplace.
/marketplace list / buy / sell / my-shaders โ Browse, purchase, sell, view your shaders๐ฆ Variables Available in your Shader
iTimefloat โ Time in secondsiResolutionvec3 โ Canvas size (x, y, ratio)iMousevec4 โ Mouse positionfragCoordvec2 โ Current pixel coordsiChannel0โ3sampler2D โ Optional texturesfragColorvec4 out โ Output colorโ Minimal Example โ Ready to Paste in /shader
Ready-to-use plasma shader. Copy this code into /shader code: to try it.
// Plasma colorรฉ animรฉ โ copiez et lancez avec /shader
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
vec2 p = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
float t = iTime;
float v1 = sin(p.x * 4.0 + t);
float v2 = sin(p.y * 4.0 + t * 1.3);
float v3 = sin((p.x + p.y) * 4.0 + t * 0.7);
float v = (v1 + v2 + v3) / 3.0;
vec3 col = vec3(
sin(v * 3.14159) * 0.5 + 0.5,
sin(v * 3.14159 + 2.094) * 0.5 + 0.5,
sin(v * 3.14159 + 4.189) * 0.5 + 0.5
);
fragColor = vec4(col, 1.0);
}๐ท With #define โ Compact Syntax
#define macros work normally โ t, r, PI, and other shorthands are all supported.
// Les macros #define sont supportรฉes
#define t iTime
#define r iResolution.xy
#define PI 3.14159265
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / r;
vec2 p = uv - 0.5;
float wave = sin(length(p) * 20.0 - t * 3.0);
float ring = smoothstep(0.02, 0.0, abs(wave * 0.05));
vec3 col = mix(
vec3(0.05, 0.05, 0.2),
vec3(0.2, 0.8, 1.0),
ring + sin(t + uv.x * PI) * 0.1
);
fragColor = vec4(col, 1.0);
}Introduction to GLSL and WGSL
GLSL (OpenGL Shading Language)
- Shader language for OpenGL/WebGL
- C-like familiar syntax
- Native support for vector types (vec2, vec3, vec4)
- Many built-in mathematical functions
- Used by most graphics editors and engines
WGSL (WebGPU Shading Language)
- Shader language for WebGPU (WebGL successor)
- More modern Rust-like syntax
- Better performance and parallelism
- Improved memory safety
- Standard for modern WebGPU applications
Shader Types
- Vertex Shader: Transforms vertex positions in 3D space
- Fragment Shader: Calculates the color of each pixel (what we mainly use)
- Compute Shader: General GPU computations (available in WGSL)
This bot supports GLSL and WGSL Fragment Shaders. Fragment Shaders calculate the color of each pixel on the screen, allowing you to create complex and performant visual effects.
Shader Fundamentals
Standard GLSL Structure
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
// Normaliser les coordonnรฉes UV (0.0 ร 1.0)
vec2 uv = fragCoord / iResolution.xy;
// Calculer la couleur du pixel
vec3 color = vec3(uv.x, uv.y, 0.5);
// Sortie finale
fragColor = vec4(color, 1.0);
}Data Types
float - Decimal number (32-bit)int - Integerbool - Booleanvec2 - 2D vector (x, y)vec3 - 3D vector (x, y, z) or RGBvec4 - 4D vector (x, y, z, w) or RGBAmat2, mat3, mat4 - 2x2, 3x3, 4x4 matricessampler2D - 2D textureAvailable Global Variables
iTime - Elapsed time in seconds (float)iTimeDelta - Duration of previous frame in seconds (float)iFrame - Frame counter (int) โ 0, 1, 2 โฆiResolution - Viewport size in pixels (vec3: .x = width, .y = height, .z = 1.0)iMouse - Mouse position (vec4: .xy = current pos, .zw = click pos)iDate - Calendar date (vec4: .x year, .y month, .z day, .w seconds since midnight)iSampleRate - Audio sample rate, 44100 default (float)iChannel0-3 - Optional textures (sampler2D)fragCoord - Current pixel coordinates (vec2)Vector Manipulation
vec2 uv = vec2(0.5, 0.5);
vec3 color = vec3(1.0, 0.0, 0.0); // Rouge
// Accรจs aux composants
float x = uv.x; // ou uv.r, uv.s
float y = uv.y; // ou uv.g, uv.t
vec2 xy = uv.xy; // Swizzling
vec2 yx = uv.yx; // Inversion
// Opรฉrations vectorielles
vec3 a = vec3(1.0, 2.0, 3.0);
vec3 b = vec3(4.0, 5.0, 6.0);
vec3 sum = a + b; // Addition
vec3 prod = a * b; // Multiplication composante par composante
float dot = dot(a, b); // Produit scalaire
vec3 cross = cross(a, b); // Produit vectoriel (3D)Gradients and Colors
Linear Gradients
Different types of linear gradients
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// Gradient horizontal
float gradH = uv.x;
// Gradient vertical
float gradV = uv.y;
// Gradient diagonal
float gradD = (uv.x + uv.y) * 0.5;
// Gradient radial
vec2 center = vec2(0.5);
float gradR = length(uv - center);
// Gradient angulaire
vec2 p = uv - center;
float gradA = atan(p.y, p.x) / 6.28318 + 0.5;
fragColor = vec4(vec3(gradA), 1.0);
}Color Spaces
Conversion between RGB and HSV color spaces
// Conversion RGB vers HSV
vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
// Conversion HSV vers RGB
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
float time = iTime;
// Gradient HSV animรฉ
vec3 hsv = vec3(uv.x + time * 0.1, 1.0, 1.0);
vec3 rgb = hsv2rgb(hsv);
fragColor = vec4(rgb, 1.0);
}Color Palettes
Creating and using color palettes
// Palette de couleurs prรฉdรฉfinie
vec3 palette(float t) {
vec3 a = vec3(0.5, 0.5, 0.5);
vec3 b = vec3(0.5, 0.5, 0.5);
vec3 c = vec3(1.0, 1.0, 1.0);
vec3 d = vec3(0.263, 0.416, 0.557);
return a + b * cos(6.28318 * (c * t + d));
}
// Palette chaud/froid
vec3 warmCool(float t) {
return mix(
vec3(1.0, 0.5, 0.0), // Orange chaud
vec3(0.0, 0.5, 1.0), // Bleu froid
t
);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
float time = iTime;
float value = sin(uv.x * 10.0 + time) * 0.5 + 0.5;
vec3 color = palette(value);
fragColor = vec4(color, 1.0);
}Professional Tips
โก Performance & Optimization
- Avoid if/else branches: Use smoothstep(), step(), mix() and clamp() โ branchless operations that run in parallel on the GPU.
- Minimize texture reads: Each texture() call is expensive. Reuse values and batch your reads.
- Constant folding: Pre-compute constant expressions outside the main loop.
- Bounded loops: In GLSL ES, for loops must have constant bounds known at compile time.
- Avoid pow(x, 2.0): Prefer x*x โ faster than pow() for small exponents.
- Reduce raymarching iterations: Start with 64 steps, increase only if needed. Use early exit when d < 0.001.
๐ Shader Debugging
In GLSL, you cannot use console.log. Use color as debug output.
Color debug techniques
Techniques to visualize internal values in your shaders
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// DEBUG: Inspecter une valeur float (0.0 -> noir, 1.0 -> blanc)
float myValue = sin(iTime); // Valeur ร dรฉboguer
fragColor = vec4(vec3(myValue), 1.0); // Affiche en niveaux de gris
// DEBUG: Inspecter un vec2 (x=rouge, y=vert)
vec2 myVec = uv;
fragColor = vec4(myVec, 0.0, 1.0);
// DEBUG: Inspecter un vec3 directement
vec3 myNormal = vec3(0.5, 0.8, 1.0);
fragColor = vec4(myNormal * 0.5 + 0.5, 1.0); // Remapper [-1,1] -> [0,1]
// DEBUG: Valeur nรฉgative / positive (rouge=nรฉgatif, vert=positif)
float signedVal = sin(iTime * 2.0);
fragColor = vec4(
max(-signedVal, 0.0), // Rouge si nรฉgatif
max(signedVal, 0.0), // Vert si positif
0.0, 1.0
);
// DEBUG: Isoler une zone de l'รฉcran (split-screen)
float debug = step(0.5, uv.x);
vec3 left = vec3(uv, 0.0); // Debug ร gauche
vec3 right = vec3(sin(iTime), 0.0, cos(iTime)); // Normal ร droite
fragColor = vec4(mix(left, right, debug), 1.0);
}โ ๏ธ Common Pitfalls
- Integer vs float: GLSL is strict. Use 1.0 instead of 1, and 0.5 not 0.5f. A bare "1" where a float is expected causes an error.
- division par zรฉro : Protect your divisions: length(v) can be 0.0. Use max(length(v), 0.0001) or normalize() with a guard.
- precision mediump : On mobile/SwiftShader, mediump has limited precision (~3 decimals). Use highp for sensitive calculations.
- Integer division:
3/2= 1 (integer), not 1.5. Use3.0/2.0 - iResolution is a vec3: iResolution.xy (vec2) for screen size, iResolution.z for pixel ratio.
- #define macros : #define macros work fine: #define t iTime or #define r iResolution.xy are supported.
Useful Patterns โ Toolbox
Ready-to-use utility functions for your shaders.
// === NORMALISATION DES UV ===
vec2 uv = fragCoord / iResolution.xy; // [0,1] x [0,1]
vec2 uvc = (fragCoord - iResolution.xy * 0.5) // [-0.5,0.5] centrรฉ
/ iResolution.y; // aspect-ratio correct
vec2 uvn = (fragCoord * 2.0 - iResolution.xy) // [-1,1] x [-1,1]
/ iResolution.y; // le plus courant en 3D
// === COLORISATION ===
vec3 palette(float t, vec3 a, vec3 b, vec3 c, vec3 d) {
return a + b * cos(6.28318 * (c * t + d));
}
// Utilisation : palette(t, vec3(0.5), vec3(0.5), vec3(1.), vec3(0.,0.33,0.67))
// === BRUIT SIMPLE ===
float hash(float n) { return fract(sin(n) * 43758.5453); }
float hash(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }
float noise(vec2 p) {
vec2 i = floor(p), f = fract(p);
f = f*f*(3.-2.*f);
return mix(mix(hash(i),hash(i+vec2(1,0)),f.x),
mix(hash(i+vec2(0,1)),hash(i+vec2(1,1)),f.x),f.y);
}
// === SMOOTHSTEP TRICKS ===
float remap(float v, float lo, float hi) { return (v-lo)/(hi-lo); }
float remap01(float v, float lo, float hi) { return clamp(remap(v,lo,hi),0.,1.); }
// === ROTATION 2D ===
vec2 rot2D(vec2 p, float a) {
float s = sin(a), c = cos(a);
return vec2(c*p.x - s*p.y, s*p.x + c*p.y);
}
// === SDF RAPIDES ===
float sdCircle(vec2 p, float r) { return length(p) - r; }
float sdBox(vec2 p, vec2 b) { vec2 d=abs(p)-b; return length(max(d,0.))+min(max(d.x,d.y),0.); }
float sdSegment(vec2 p, vec2 a, vec2 b) { vec2 pa=p-a,ab=b-a; float t=clamp(dot(pa,ab)/dot(ab,ab),0.,1.); return length(pa-ab*t); }Color Theory โ HSL, Palettes
HSL/RGB conversion, cosine palettes (Inigo Quilez technique).
// HSL -> RGB (trรจs utile pour faire des arcs-en-ciel)
vec3 hsl2rgb(vec3 c) {
vec3 rgb = clamp(abs(mod(c.x*6.+vec3(0.,4.,2.),6.)-3.)-1., 0., 1.);
return c.z + c.y * (rgb - 0.5) * (1. - abs(2.*c.z - 1.));
}
// RGB -> HSL
vec3 rgb2hsl(vec3 c) {
float mx = max(max(c.r,c.g),c.b), mn = min(min(c.r,c.g),c.b);
float l = (mx+mn)/2.;
float s = mx == mn ? 0. : (mx-mn)/(1.-abs(2.*l-1.));
float h = mx == mn ? 0. :
mx == c.r ? mod((c.g-c.b)/(mx-mn), 6.) :
mx == c.g ? (c.b-c.r)/(mx-mn)+2. :
(c.r-c.g)/(mx-mn)+4.;
return vec3(h/6., s, l);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// Arc-en-ciel animรฉ
vec3 rainbow = hsl2rgb(vec3(uv.x + iTime * 0.1, 1.0, 0.5));
// Palette cosinus (Inigo Quilez)
float t = uv.x + iTime * 0.2;
vec3 a = vec3(0.5), b = vec3(0.5);
vec3 c = vec3(1.0), d = vec3(0.0, 0.33, 0.67);
vec3 palette = a + b*cos(6.28318*(c*t+d));
fragColor = vec4(palette, 1.0);
}Advanced 2D Techniques
Geometric Shapes
Creating geometric shapes with SDF (Signed Distance Fields)
// Cercle
float circle(vec2 uv, vec2 center, float radius) {
return length(uv - center) - radius;
}
// Rectangle
float box(vec2 uv, vec2 center, vec2 size) {
vec2 d = abs(uv - center) - size;
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
}
// Polygone rรฉgulier
float polygon(vec2 uv, vec2 center, float radius, int sides) {
vec2 p = uv - center;
float angle = atan(p.y, p.x);
float slice = 6.28318 / float(sides);
return length(p) - radius * cos(floor(0.5 + angle / slice) * slice - angle);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
uv -= 0.5;
float d = circle(uv, vec2(0.0), 0.3);
float shape = smoothstep(0.0, 0.01, -d);
fragColor = vec4(vec3(shape), 1.0);
}Repeating Patterns
Creating repeating patterns with fract() and floor()
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// Rรฉpรฉtition avec fract()
vec2 id = floor(uv * 10.0);
vec2 gv = fract(uv * 10.0) - 0.5;
// Distance au centre de chaque cellule
float dist = length(gv);
// Cercle dans chaque cellule
float circle = smoothstep(0.3, 0.29, dist);
// Alternance de couleurs
vec3 color = mix(
vec3(0.2, 0.4, 0.8),
vec3(0.8, 0.4, 0.2),
mod(id.x + id.y, 2.0)
);
fragColor = vec4(color * circle, 1.0);
}Distortions and Warping
Distortion and warping techniques for visual effects
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
float time = iTime;
// Distorsion sinusoรฏdale
vec2 distorted = uv;
distorted.x += sin(uv.y * 10.0 + time) * 0.05;
distorted.y += cos(uv.x * 10.0 + time) * 0.05;
// Spirale
vec2 center = vec2(0.5);
vec2 p = distorted - center;
float angle = atan(p.y, p.x);
float radius = length(p);
// Rotation basรฉe sur le rayon
angle += radius * 5.0 + time;
p = vec2(cos(angle), sin(angle)) * radius;
// Pattern
float pattern = sin(p.x * 10.0) * sin(p.y * 10.0);
fragColor = vec4(vec3(pattern * 0.5 + 0.5), 1.0);
}Voronoi and Cellular Noise
Generating Voronoi patterns for organic textures
// Hash function
vec2 hash(vec2 p) {
p = vec2(dot(p, vec2(127.1, 311.7)),
dot(p, vec2(269.5, 183.3)));
return fract(sin(p) * 43758.5453);
}
// Voronoi
float voronoi(vec2 uv) {
vec2 i = floor(uv);
vec2 f = fract(uv);
float minDist = 1.0;
// Vรฉrifier les 9 cellules voisines
for(int y = -1; y <= 1; y++) {
for(int x = -1; x <= 1; x++) {
vec2 neighbor = vec2(float(x), float(y));
vec2 point = hash(i + neighbor);
point = 0.5 + 0.5 * sin(iTime + 6.2831 * point);
vec2 diff = neighbor + point - f;
float dist = length(diff);
minDist = min(minDist, dist);
}
}
return minDist;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
float v = voronoi(uv * 10.0);
fragColor = vec4(vec3(v), 1.0);
}Textures and Sampling
Complete guide on using, manipulating, and optimizing textures in GLSL/WGSL
Introduction to Textures
Textures allow you to apply images or data to your shaders. In ShaderBot, you have access to 4 texture channels (iChannel0-3) via 2D samplers.
sampler2D - Type for sampling 2D texturestexture(sampler, uv) - Function to read a texture at UV coordinatesiChannel0, iChannel1, iChannel2, iChannel3 - 4 available texture channels1. Basic Texture Sampling
Fundamentals: direct sampling, vertical flip, tiling and offset. Replace sampleTex(uv) with texture(iChannel0, uv) for your own texture.
// sampleTex simule iChannel0 โ remplace par texture(iChannel0, uv)
vec4 sampleTex(vec2 uv) {
uv = fract(uv);
float check = mod(floor(uv.x * 8.0) + floor(uv.y * 8.0), 2.0);
vec3 col = mix(vec3(0.9, 0.5, 0.1), vec3(0.1, 0.4, 0.9), check);
col *= 0.5 + 0.5 * sin(uv.x * 6.28318);
return vec4(col, 1.0);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// Sampling direct
vec4 direct = sampleTex(uv);
// Coordonnรฉes inversรฉes (flip vertical)
vec4 flipped = sampleTex(vec2(uv.x, 1.0 - uv.y));
// Rรฉpรฉtition ร2 (tiling)
vec4 tiled = sampleTex(fract(uv * 2.0));
// Dรฉcalage (offset)
vec4 offset = sampleTex(uv + vec2(0.1, 0.05));
// Affichage en 4 quadrants
vec2 q = step(vec2(0.5), uv);
float quad = q.x + q.y * 2.0;
if (quad < 0.5) fragColor = direct;
else if (quad < 1.5) fragColor = flipped;
else if (quad < 2.5) fragColor = tiled;
else fragColor = offset;
}2. Wrapping Modes (Tiling)
Repeat, clamp, mirror: 3 wrapping modes side by side. Avoid edge artifacts with clamp mode.
// Texture de rรฉfรฉrence โ remplace par texture(iChannel0, uv_in)
vec4 sampleTex(vec2 uv) {
uv = fract(uv);
float pat = smoothstep(0.0, 0.5,
abs(sin(uv.x * 6.28318) * sin(uv.y * 6.28318)));
return vec4(0.2 + 0.8 * pat, 0.5 * pat, 1.0 - pat, 1.0);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// REPEAT โ rรฉpรฉtition infinie (fract = modulo 1)
vec2 uvRepeat = fract(uv * 3.0);
vec4 repeat = sampleTex(uvRepeat);
// CLAMP โ pince les bords hors [0,1]
vec2 uvClamp = clamp(uv * 3.0 - 1.0, 0.0, 1.0);
vec4 clamped = sampleTex(uvClamp);
// MIRROR โ rรฉpรฉtition en miroir
vec2 uvMirror = abs(fract(uv * 1.5) * 2.0 - 1.0);
vec4 mirrored = sampleTex(uvMirror);
// Affichage en 3 bandes verticales
float band = floor(uv.x * 3.0);
if (band < 0.5) fragColor = repeat;
else if (band < 1.5) fragColor = clamped;
else fragColor = mirrored;
}3. Filtering: Linear vs Nearest
Linear (bilinear) vs Nearest: linear smooths pixels, nearest keeps hard edges โ ideal for pixel art.
// Grille haute frรฉquence pour rendre le filtrage visible
vec4 sampleTex(vec2 uv) {
uv = fract(uv);
float px = mod(floor(uv.x * 16.0) + floor(uv.y * 16.0), 2.0);
return vec4(vec3(0.1 + 0.9 * px), 1.0);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// LINEAR (bilinรฉaire) : sampleTex interpole naturellement
vec4 linear = sampleTex(uv);
// NEAREST : arrondir les UV ร la grille texel (pixel art)
float texRes = 16.0;
vec2 nearestUV = floor(uv * texRes) / texRes;
vec4 nearest = sampleTex(nearestUV);
// Gauche = Nearest (crรฉnelรฉ), Droite = Linear (lissรฉ)
fragColor = uv.x < 0.5 ? nearest : linear;
// Ligne de sรฉparation
if (abs(uv.x - 0.5) < 0.002)
fragColor = vec4(1.0, 1.0, 0.0, 1.0);
}4. Texture Blending (Blend Modes)
Six blend modes on a 3ร2 grid: Normal, Multiply, Screen, Difference, Additive, Lighten.
// Deux textures procรฉdurales diffรฉrentes
vec4 sampleTex0(vec2 uv) {
uv = fract(uv);
float r = length(uv - 0.5) * 2.0;
return vec4(1.0 - r * 0.8, 0.3, 0.6 * r, 1.0);
}
vec4 sampleTex1(vec2 uv) {
uv = fract(uv);
float n = fract(sin(dot(floor(uv * 8.0),
vec2(127.1, 311.7))) * 43758.5453);
return vec4(n, n * 0.5, 1.0 - n, 1.0);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
vec4 t0 = sampleTex0(uv);
vec4 t1 = sampleTex1(uv);
float col = floor(uv.x * 3.0);
float row = floor(uv.y * 2.0);
vec4 result;
if (row < 0.5) {
// Ligne haute : Normal, Multiply, Screen
if (col < 0.5) result = mix(t0, t1, 0.5);
else if (col < 1.5) result = t0 * t1;
else result = 1.0 - (1.0 - t0) * (1.0 - t1);
} else {
// Ligne basse : Difference, Additive, Lighten
if (col < 0.5) result = abs(t0 - t1);
else if (col < 1.5) result = clamp(t0 + t1, 0.0, 1.0);
else result = max(t0, t1);
}
fragColor = vec4(result.rgb, 1.0);
}5. Texture Distortion
Sine waves, vortex and displacement mapping: three techniques to dynamically warp UV coordinates.
// Texture ร distordre โ remplace par texture(iChannel0, uv)
vec4 sampleTex(vec2 uv) {
uv = fract(uv);
float ch = mod(floor(uv.x * 10.0) + floor(uv.y * 10.0), 2.0);
return vec4(mix(vec3(0.15, 0.3, 0.8),
vec3(0.9, 0.7, 0.1), ch), 1.0);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// Distorsion sinusoรฏdale (ondes)
vec2 wave = vec2(
sin(uv.y * 10.0 + iTime * 2.0) * 0.04,
cos(uv.x * 10.0 + iTime * 2.0) * 0.04
);
// Vortex (tourbillon radial)
vec2 p = uv - 0.5;
float a = atan(p.y, p.x) + length(p) * 6.0 - iTime;
vec2 vortex = 0.5 + length(p) * vec2(cos(a), sin(a));
// Displacement mapping : la texture dรฉcale elle-mรชme les UV
float disp = sampleTex(uv * 0.5).r;
vec2 displaced = uv + (disp - 0.5) * 0.15;
// Affichage en 3 bandes
float band = floor(uv.x * 3.0);
if (band < 0.5) fragColor = sampleTex(uv + wave);
else if (band < 1.5) fragColor = sampleTex(vortex);
else fragColor = sampleTex(displaced);
}6. Normal Mapping and Bump Mapping
Bump mapping: compute surface normal from heightmap gradient, then full Phong lighting with animated diffuse + specular.
// Heightmap procรฉdurale (remplace texture(iChannel1, uv).r)
float heightmap(vec2 uv) {
return 0.5 + 0.5 * sin(uv.x * 12.0) * sin(uv.y * 9.0 + 0.5);
}
// Texture diffuse (remplace texture(iChannel0, uv).rgb)
vec3 diffuseTex(vec2 uv) {
float t = fract(uv.x * 4.0) * fract(uv.y * 4.0);
return mix(vec3(0.6, 0.3, 0.1), vec3(0.9, 0.8, 0.5), t);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// Gradient de la heightmap โ normale de surface
float eps = 0.003;
float h = heightmap(uv);
float hx = heightmap(uv + vec2(eps, 0.0));
float hy = heightmap(uv + vec2(0.0, eps));
vec3 normal = normalize(vec3(h - hx, h - hy, 0.02));
// รclairage directionnel animรฉ
vec3 lightDir = normalize(vec3(
cos(iTime * 0.8), sin(iTime * 0.6), 1.0));
float diff = max(dot(normal, lightDir), 0.0);
// Spรฉculaire simple
vec3 refl = reflect(-lightDir, normal);
float spec = pow(max(refl.z, 0.0), 16.0) * 0.5;
vec3 color = diffuseTex(uv) * (0.25 + 0.75 * diff) + spec;
fragColor = vec4(color, 1.0);
}7. Parallax Mapping
Simple (left) vs steep parallax with fixed-iteration for loop (right). Creates 3D depth illusion without geometry.
// Heightmap et texture diffuse procรฉdurales
float heightmap(vec2 uv) {
return 0.5 + 0.5 * sin(uv.x * 16.0 + 1.0) * cos(uv.y * 12.0);
}
vec3 diffuseTex(vec2 uv) {
float ch = mod(floor(uv.x * 8.0) + floor(uv.y * 8.0), 2.0);
return mix(vec3(0.2, 0.5, 0.8), vec3(0.8, 0.7, 0.2), ch);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
vec2 viewDir = normalize(vec2(cos(iTime * 0.4), sin(iTime * 0.3)));
// Parallax simple (1 couche)
float h0 = heightmap(uv);
vec2 parallaxUV = uv - viewDir * h0 * 0.05;
// Steep parallax โ boucle ร nombre FIXE d'itรฉrations (pas de while)
const int LAYERS = 8;
float layerDepth = 1.0 / float(LAYERS);
float curDepth = 0.0;
vec2 deltaUV = viewDir * 0.05 / float(LAYERS);
vec2 curUV = uv;
float curH = heightmap(curUV);
for (int i = 0; i < LAYERS; i++) {
if (curDepth >= curH) break;
curUV -= deltaUV;
curH = heightmap(curUV);
curDepth += layerDepth;
}
// Gauche = parallax simple, Droite = steep parallax
vec2 finalUV = uv.x < 0.5 ? parallaxUV : curUV;
vec3 color = diffuseTex(finalUV);
float ao = smoothstep(0.0, 0.2, heightmap(finalUV));
fragColor = vec4(color * (0.4 + 0.6 * ao), 1.0);
}8. Procedural Texture Generation
Wood, marble and brick 100% procedurally via noise + FBM. No image needed โ all calculated mathematically.
float hash(vec2 p) {
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
}
float noise(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
f = f * f * (3.0 - 2.0 * f);
return mix(mix(hash(i), hash(i + vec2(1,0)), f.x),
mix(hash(i + vec2(0,1)), hash(i + vec2(1,1)), f.x), f.y);
}
float fbm(vec2 p) {
float v = 0.0, a = 0.5;
for (int i = 0; i < 4; i++) { v += a * noise(p); p *= 2.0; a *= 0.5; }
return v;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// BOIS
float woodN = fbm(uv * vec2(10.0, 2.0));
float wood = sin(woodN * 20.0 + uv.y * 10.0) * 0.5 + 0.5;
vec3 woodC = mix(vec3(0.4,0.2,0.1), vec3(0.6,0.4,0.2), wood);
// MARBRE
float marbN = fbm(uv * 5.0);
float marb = sin(marbN * 10.0 + uv.x * 5.0) * 0.5 + 0.5;
vec3 marbC = mix(vec3(0.9,0.9,0.95), vec3(0.7,0.7,0.8), marb);
// BRIQUE
vec2 brickUV = fract(uv * vec2(4.0, 8.0));
float brick = step(0.9, brickUV.x) + step(0.9, brickUV.y);
vec3 brickC = mix(vec3(0.6,0.2,0.1), vec3(0.4,0.15,0.1), brick);
// Affichage en 3 bandes
float band = floor(uv.x * 3.0);
if (band < 0.5) fragColor = vec4(woodC, 1.0);
else if (band < 1.5) fragColor = vec4(marbC, 1.0);
else fragColor = vec4(brickC, 1.0);
}9. Texture Atlas and UV Mapping
4ร4 atlas with animated tile selection. The comment shows how to compute atlasUV for texture(iChannel0, atlasUV) with a real image.
// Simule un atlas 4ร4 avec une couleur unique par tile
// En production : return texture(iChannel0, atlasUV)
vec4 getAtlasTile(vec2 localUV, vec2 tilePos, float gridSize) {
vec2 tileSize = vec2(1.0 / gridSize);
// calcul atlasUV (pour une vraie texture) :
// vec2 atlasUV = tilePos * tileSize + fract(localUV) * tileSize;
// return texture(iChannel0, atlasUV);
vec3 tileColor = 0.5 + 0.5 * cos(vec3(
tilePos.x * 1.7 + 0.5,
tilePos.y * 2.1 + 1.0,
(tilePos.x + tilePos.y) * 0.9 + 2.5));
float pat = 0.5 + 0.5 *
sin(fract(localUV).x * 6.28 * 3.0) *
sin(fract(localUV).y * 6.28 * 3.0);
return vec4(tileColor * pat, 1.0);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
float gridSize = 4.0;
vec2 tilePos = floor(uv * gridSize);
fragColor = getAtlasTile(uv * gridSize, tilePos, gridSize);
// Tile sรฉlectionnรฉe animรฉe
float frame = floor(mod(iTime * 6.0, gridSize * gridSize));
vec2 selTile = vec2(mod(frame, gridSize), floor(frame / gridSize));
vec2 dist = abs(uv * gridSize - selTile - 0.5);
float border = step(0.48, max(dist.x, dist.y));
fragColor.rgb = mix(fragColor.rgb, vec3(1.0, 0.9, 0.0), border * 0.8);
}10. Optimizations and Best Practices
Visual comparison: original, 5-tap box blur, and unsharp mask. Shows the pre-calc โ clamp โ filter โ sharpen pipeline.
// Texture procรฉdurale โ en production : texture(iChannel0, uv)
vec4 sampleTex(vec2 uv) {
vec2 p = fract(uv);
float pat = 0.5 + 0.5 * sin(p.x * 12.566) * cos(p.y * 9.425 + 0.3);
return vec4(pat, pat * 0.6, 1.0 - pat * 0.5, 1.0);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// โ
Prรฉ-calculer la taille du texel (ex. texture 256ร256)
vec2 texelSize = vec2(1.0 / 256.0);
// โ
Clamper les UV avant sampling
vec2 safeUV = clamp(uv, texelSize, 1.0 - texelSize);
vec4 raw = sampleTex(safeUV);
// โ
Flou 5-tap box blur
vec4 blurred = (
sampleTex(safeUV) +
sampleTex(safeUV + vec2( texelSize.x, 0.0)) +
sampleTex(safeUV + vec2(-texelSize.x, 0.0)) +
sampleTex(safeUV + vec2(0.0, texelSize.y)) +
sampleTex(safeUV + vec2(0.0, -texelSize.y))
) * 0.2;
// โ
Sharpen (unsharp mask)
vec4 sharp = clamp(raw * 2.0 - blurred, 0.0, 1.0);
// Comparaison : Original | Flou | Nettetรฉ
float sec = floor(uv.x * 3.0);
if (sec < 0.5) fragColor = raw;
else if (sec < 1.5) fragColor = blurred;
else fragColor = sharp;
}11. Mipmap / LOD Simulation
4 detail levels side by side (LOD 0โ3), WebGL1 compatible without textureSize or textureLod. Shows resolution decrease with LOD.
// Simule un niveau de dรฉtail (LOD) sans textureSize/textureLod
// (WebGL1 compatible). En production : textureLod(iChannel0, uv, lod)
vec4 sampleAtLOD(vec2 uv, float lod) {
float scale = pow(2.0, floor(lod));
vec2 lowUV = floor(uv * 32.0 / scale) * (scale / 32.0);
// Hash โ couleur unique par cellule
float a = fract(sin(dot(lowUV * 32.0,
vec2(127.1, 311.7))) * 43758.5453);
float b = fract(sin(dot(lowUV * 32.0 + vec2(1.0, 0.0),
vec2(127.1, 311.7))) * 43758.5453);
float val = mix(a, b, fract(uv.x * 32.0 / scale));
return vec4(0.5 + 0.5 * cos(vec3(0.0, 1.0, 2.0) + val * 6.28), 1.0);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
// 4 bandes : LOD 0 (dรฉtail max) โ LOD 3 (trรจs flou)
float band = floor(uv.x * 4.0);
fragColor = sampleAtLOD(uv, band);
// Sรฉparateurs
if (fract(uv.x * 4.0) < 0.015)
fragColor = vec4(1.0);
}12. Masks and Alpha Blending
Cutout (step), soft edges (smoothstep) and premultiplied alpha on checkerboard โ 3 alpha mask approaches side by side.
// Texture de base (remplace texture(iChannel0, uv))
vec3 baseTex(vec2 uv) {
uv = fract(uv);
float t = 0.5 + 0.5 *
sin(uv.x * 6.28318 * 3.0 + iTime) *
cos(uv.y * 6.28318 * 2.0);
return mix(vec3(0.1, 0.4, 0.9), vec3(0.9, 0.2, 0.5), t);
}
// Masque (remplace texture(iChannel1, uv).r)
float alphaMask(vec2 uv) {
uv = fract(uv);
return 0.5 + 0.5 * cos(length(uv - 0.5) * 16.0 - iTime * 2.0);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
vec3 col = baseTex(uv);
float mask = alphaMask(uv);
// Fond damier pour visualiser la transparence
float bg = mod(floor(uv.x * 16.0) + floor(uv.y * 16.0), 2.0);
vec3 bgColor = mix(vec3(0.3), vec3(0.5), bg);
// Cutout (seuil dur)
float cutout = step(0.5, mask);
// Bords doux (smoothstep)
float soft = smoothstep(0.3, 0.7, mask);
// Prรฉmultiplication alpha
vec3 premul = col * soft;
// Affichage en 3 bandes
float band = floor(uv.x * 3.0);
vec3 result;
if (band < 0.5) result = mix(bgColor, col, cutout);
else if (band < 1.5) result = mix(bgColor, col, soft);
else result = mix(bgColor, premul, soft);
fragColor = vec4(result, 1.0);
}Advanced Animations
Easing and Interpolation
Easing functions for smooth animations
// Easing functions
float easeInOut(float t) {
return t * t * (3.0 - 2.0 * t);
}
float easeIn(float t) {
return t * t;
}
float easeOut(float t) {
return 1.0 - (1.0 - t) * (1.0 - t);
}
float bounce(float t) {
if(t < 0.5) {
return 4.0 * t * t;
} else {
return 1.0 - pow(-2.0 * t + 2.0, 2.0) / 2.0;
}
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
float time = iTime;
// Animation avec easing
float t = mod(time, 2.0) / 2.0;
float eased = easeInOut(t);
float circle = length(uv - vec2(0.5 + eased * 0.3, 0.5)) - 0.1;
float shape = smoothstep(0.0, 0.01, -circle);
fragColor = vec4(vec3(shape), 1.0);
}Multiple Animations
Combining multiple simultaneous animations
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
float time = iTime;
// Rotation
vec2 center = vec2(0.5);
vec2 p = uv - center;
float angle = atan(p.y, p.x) + time;
float radius = length(p);
p = vec2(cos(angle), sin(angle)) * radius;
// Scale pulsation
float scale = 1.0 + sin(time * 2.0) * 0.2;
p *= scale;
// Translation
p += vec2(sin(time), cos(time)) * 0.1;
// Pattern animรฉ
float pattern = sin(p.x * 10.0 + time) * sin(p.y * 10.0 + time);
// Couleur animรฉe
vec3 color = vec3(
sin(time),
sin(time + 2.094),
sin(time + 4.189)
) * 0.5 + 0.5;
fragColor = vec4(color * (pattern * 0.5 + 0.5), 1.0);
}Particles and Systems
Particle systems with hash and animations
// Hash pour gรฉnรฉrer des positions de particules
vec2 hash(vec2 p) {
p = vec2(dot(p, vec2(127.1, 311.7)),
dot(p, vec2(269.5, 183.3)));
return fract(sin(p) * 43758.5453);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
float time = iTime;
vec2 grid = floor(uv * 10.0);
vec2 cellUV = fract(uv * 10.0);
// Position de particule dans la cellule
vec2 particlePos = hash(grid);
// Animation de la particule
particlePos += vec2(
sin(time + particlePos.x * 6.283),
cos(time + particlePos.y * 6.283)
) * 0.3;
// Distance ร la particule
float dist = length(cellUV - particlePos);
// Rendu de la particule (smoothstep: 1 quand dist=0, 0 quand dist=0.05)
float particle = 1.0 - smoothstep(0.0, 0.05, dist);
// Traรฎnรฉe (glow exponentiel)
float trailDist = length(cellUV - particlePos);
float trailGlow = exp(-trailDist * 8.0) * (1.0 - smoothstep(0.0, 0.3, trailDist));
vec3 color = vec3(0.2, 0.6, 1.0) * (particle + trailGlow * 0.5);
fragColor = vec4(color, 1.0);
}Advanced 3D Techniques
๐บ Video Tutorial โ Ray Marching
Basic Raymarching
Raymarching to create 3D scenes with SDF
// SDF pour une sphรจre
float sdSphere(vec3 p, float radius) {
return length(p) - radius;
}
// SDF pour un cube
float sdBox(vec3 p, vec3 size) {
vec3 d = abs(p) - size;
return length(max(d, 0.0)) + min(max(d.x, max(d.y, d.z)), 0.0);
}
// Raymarching
float raymarch(vec3 ro, vec3 rd) {
float t = 0.0;
for(int i = 0; i < 100; i++) {
vec3 p = ro + rd * t;
float d = sdSphere(p, 1.0);
if(d < 0.001) break;
t += d;
if(t > 100.0) break;
}
return t;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
vec3 ro = vec3(0.0, 0.0, -3.0);
vec3 rd = normalize(vec3(uv, 1.0));
float t = raymarch(ro, rd);
vec3 col = vec3(1.0) / (1.0 + t * 0.1);
fragColor = vec4(col, 1.0);
}3D Lighting
Normal calculation and Phong lighting for realistic 3D rendering
float sdSphere(vec3 p, float r) {
return length(p) - r;
}
vec3 calcNormal(vec3 p) {
float eps = 0.001;
float r = 1.0;
return normalize(vec3(
sdSphere(p + vec3(eps, 0, 0), r) - sdSphere(p - vec3(eps, 0, 0), r),
sdSphere(p + vec3(0, eps, 0), r) - sdSphere(p - vec3(0, eps, 0), r),
sdSphere(p + vec3(0, 0, eps), r) - sdSphere(p - vec3(0, 0, eps), r)
));
}
float raymarch(vec3 ro, vec3 rd) {
float t = 0.0;
for(int i = 0; i < 100; i++) {
vec3 p = ro + rd * t;
float d = sdSphere(p, 1.0);
if(d < 0.001) return t;
t += d;
if(t > 100.0) return -1.0;
}
return -1.0;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
vec3 ro = vec3(0.0, 0.0, -3.0);
vec3 rd = normalize(vec3(uv, 1.0));
float t = raymarch(ro, rd);
if(t < 0.0) {
fragColor = vec4(0.0);
return;
}
vec3 p = ro + rd * t;
vec3 n = calcNormal(p);
vec3 light = normalize(vec3(2.0, 3.0, -2.0));
float diff = max(dot(n, light), 0.0);
vec3 col = vec3(0.2, 0.4, 0.8) * (0.2 + 0.8 * diff);
fragColor = vec4(col, 1.0);
}CSG Operations
CSG operations to combine 3D shapes
float sdSphere(vec3 p, float r) {
return length(p) - r;
}
float sdBox(vec3 p, vec3 s) {
vec3 d = abs(p) - s;
return length(max(d, 0.0)) + min(max(d.x, max(d.y, d.z)), 0.0);
}
// Union (combine)
float opUnion(float d1, float d2) {
return min(d1, d2);
}
// Intersection
float opIntersection(float d1, float d2) {
return max(d1, d2);
}
// Soustraction
float opSubtraction(float d1, float d2) {
return max(-d1, d2);
}
// Smooth union
float opSmoothUnion(float d1, float d2, float k) {
float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
return mix(d2, d1, h) - k * h * (1.0 - h);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
vec3 ro = vec3(0.0, 0.0, -3.0);
vec3 rd = normalize(vec3(uv, 1.0));
float t = 0.0;
for(int i = 0; i < 100; i++) {
vec3 p = ro + rd * t;
float d1 = sdSphere(p, 1.0);
float d2 = sdBox(p - vec3(0.5, 0.0, 0.0), vec3(0.5));
float d = opSmoothUnion(d1, d2, 0.3);
if(d < 0.001) break;
t += d;
if(t > 100.0) break;
}
vec3 col = vec3(1.0) / (1.0 + t * 0.1);
fragColor = vec4(col, 1.0);
}3D Rotations and Transformations
Rotation matrices and 3D transformations
// Rotation autour de l'axe X
mat3 rotX(float angle) {
float c = cos(angle);
float s = sin(angle);
return mat3(
1.0, 0.0, 0.0,
0.0, c, -s,
0.0, s, c
);
}
// Rotation autour de l'axe Y
mat3 rotY(float angle) {
float c = cos(angle);
float s = sin(angle);
return mat3(
c, 0.0, s,
0.0, 1.0, 0.0,
-s, 0.0, c
);
}
// Rotation autour de l'axe Z
mat3 rotZ(float angle) {
float c = cos(angle);
float s = sin(angle);
return mat3(
c, -s, 0.0,
s, c, 0.0,
0.0, 0.0, 1.0
);
}
float sdBox(vec3 p, vec3 s) {
vec3 d = abs(p) - s;
return length(max(d, 0.0)) + min(max(d.x, max(d.y, d.z)), 0.0);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
vec3 ro = vec3(0.0, 0.0, -3.0);
vec3 rd = normalize(vec3(uv, 1.0));
float t = 0.0;
for(int i = 0; i < 100; i++) {
vec3 p = ro + rd * t;
// Rotation animรฉe
p = rotY(iTime) * rotX(iTime * 0.5) * p;
float d = sdBox(p, vec3(0.5));
if(d < 0.001) break;
t += d;
if(t > 100.0) break;
}
vec3 col = vec3(1.0) / (1.0 + t * 0.1);
fragColor = vec4(col, 1.0);
}Advanced Techniques
Complex Fractals
Mandelbrot set with enhanced coloring
// Mandelbrot Set
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
uv *= 2.0;
uv -= vec2(0.5, 0.0);
vec2 c = uv;
vec2 z = vec2(0.0);
float iterations = 0.0;
int maxIter = 100;
for(int i = 0; i < maxIter; i++) {
if(length(z) > 2.0) break;
z = vec2(z.x*z.x - z.y*z.y, 2.0*z.x*z.y) + c;
iterations++;
}
float color = iterations / maxIter;
// Coloration amรฉliorรฉe
color = sqrt(color);
vec3 col = vec3(
sin(color * 3.14159),
sin(color * 3.14159 + 2.094),
sin(color * 3.14159 + 4.189)
) * 0.5 + 0.5;
fragColor = vec4(col, 1.0);
}Advanced Raymarching with Shadows
Raymarching with soft shadows and lighting
float sdSphere(vec3 p, float r) {
return length(p) - r;
}
float scene(vec3 p) {
return sdSphere(p, 1.0);
}
float raymarch(vec3 ro, vec3 rd) {
float t = 0.0;
for(int i = 0; i < 100; i++) {
float d = scene(ro + rd * t);
if(d < 0.001) return t;
t += d;
if(t > 100.0) return -1.0;
}
return -1.0;
}
float softShadow(vec3 ro, vec3 rd, float k) {
float res = 1.0;
float t = 0.01;
for(int i = 0; i < 50; i++) {
float h = scene(ro + rd * t);
res = min(res, k * h / t);
t += clamp(h, 0.01, 0.5);
if(res < 0.001) break;
}
return clamp(res, 0.0, 1.0);
}
vec3 calcNormal(vec3 p) {
float eps = 0.001;
return normalize(vec3(
scene(p + vec3(eps, 0, 0)) - scene(p - vec3(eps, 0, 0)),
scene(p + vec3(0, eps, 0)) - scene(p - vec3(0, eps, 0)),
scene(p + vec3(0, 0, eps)) - scene(p - vec3(0, 0, eps))
));
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
vec3 ro = vec3(0.0, 0.0, -3.0);
vec3 rd = normalize(vec3(uv, 1.0));
float t = raymarch(ro, rd);
if(t < 0.0) {
fragColor = vec4(0.0);
return;
}
vec3 p = ro + rd * t;
vec3 n = calcNormal(p);
vec3 light = normalize(vec3(2.0, 3.0, -2.0));
float diff = max(dot(n, light), 0.0);
float shadow = softShadow(p + n * 0.01, light, 16.0);
vec3 col = vec3(0.2, 0.4, 0.8) * (0.2 + 0.8 * diff * shadow);
fragColor = vec4(col, 1.0);
}Post-Processing Effects
Post-processing effects (bloom, vignette)
uniform sampler2D iChannel0;
// Bloom effect
vec3 bloom(sampler2D tex, vec2 uv, float intensity) {
vec3 color = texture(tex, uv).rgb;
vec3 bloomColor = vec3(0.0);
for(int i = -2; i <= 2; i++) {
for(int j = -2; j <= 2; j++) {
vec2 offset = vec2(float(i), float(j)) / iResolution.xy * 5.0;
bloomColor += texture(tex, uv + offset).rgb;
}
}
bloomColor /= 25.0;
float brightness = dot(bloomColor, vec3(0.299, 0.587, 0.114));
bloomColor *= smoothstep(0.7, 1.0, brightness) * intensity;
return color + bloomColor;
}
// Vignette
vec3 vignette(vec3 color, vec2 uv, float intensity) {
vec2 center = vec2(0.5);
float dist = length(uv - center);
float vig = 1.0 - smoothstep(0.3, 1.0, dist) * intensity;
return color * vig;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
vec3 color = texture(iChannel0, uv).rgb;
color = bloom(iChannel0, uv, 0.3);
color = vignette(color, uv, 0.5);
fragColor = vec4(color, 1.0);
}Domain Warping
Domain warping: deform coordinates with FBM to create organic smoke, cloud, fire effects. Inigo Quilez technique.
// FBM = Fractal Brownian Motion (bruit multi-octave)
float hash(vec2 p) {
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
}
float noise(vec2 p) {
vec2 i = floor(p), f = fract(p);
f = f*f*(3.0-2.0*f);
return mix(mix(hash(i),hash(i+vec2(1,0)),f.x),
mix(hash(i+vec2(0,1)),hash(i+vec2(1,1)),f.x),f.y);
}
float fbm(vec2 p) {
float v=0.0, a=0.5;
for(int i=0; i<5; i++) { v+=a*noise(p); p=p*2.0+vec2(1.7,9.2); a*=0.5; }
return v;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 p = fragCoord / iResolution.y;
// Premiรจre couche de dรฉformation
vec2 q = vec2(fbm(p + vec2(0.0, 0.0)),
fbm(p + vec2(5.2, 1.3)));
// Deuxiรจme couche (dรฉformรฉe par q)
vec2 r = vec2(fbm(p + 4.0*q + vec2(1.7,9.2) + 0.15*iTime),
fbm(p + 4.0*q + vec2(8.3,2.8) + 0.126*iTime));
float f = fbm(p + 4.0*r);
// Coloration
vec3 col = mix(vec3(0.1,0.2,0.4), vec3(0.9,0.6,0.1), clamp(f*f*4.0,0.,1.));
col = mix(col, vec3(0.0,0.0,0.16), clamp(length(q),0.,1.));
col = mix(col, vec3(0.9,0.9,0.9), clamp(r.x*r.x, 0.,1.));
fragColor = vec4(col, 1.0);
}PBR โ Physically Based Rendering
Physically Based Rendering (PBR): GGX NDF, Smith geometry, Fresnel-Schlick, ACES tone mapping. Produces photorealistic metallic sphere.
// GGX NDF (distribution des microfacettes)
float ggxD(float NdotH, float roughness) {
float a = roughness*roughness;
float a2 = a*a;
float d = NdotH*NdotH*(a2-1.0)+1.0;
return a2 / (3.14159*d*d);
}
// Smith geometry term
float smithG(float NdotV, float NdotL, float rough) {
float k = (rough+1.0)*(rough+1.0)/8.0;
float g1 = NdotV/(NdotV*(1.-k)+k);
float g2 = NdotL/(NdotL*(1.-k)+k);
return g1*g2;
}
// Fresnel-Schlick
float fresnel(float HdotV, float F0) {
return F0+(1.-F0)*pow(1.-HdotV, 5.0);
}
float sdSphere(vec3 p, float r) { return length(p)-r; }
vec3 calcNormal(vec3 p) {
vec2 e = vec2(0.001,0.0);
return normalize(vec3(sdSphere(p+e.xyy,1.)-sdSphere(p-e.xyy,1.),
sdSphere(p+e.yxy,1.)-sdSphere(p-e.yxy,1.),
sdSphere(p+e.yyx,1.)-sdSphere(p-e.yyx,1.)));
}
float raymarch(vec3 ro, vec3 rd) {
float t=0.0;
for(int i=0;i<64;i++){float d=sdSphere(ro+rd*t,1.);if(d<0.001)return t;t+=d;if(t>20.)return -1.;}
return -1.;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord*2.-iResolution.xy)/iResolution.y;
// Camรฉra animรฉe
float a = iTime*0.3;
vec3 ro = vec3(cos(a)*3., 1.5, sin(a)*3.);
vec3 rd = normalize(vec3(uv, 1.5) - vec3(0., 0.5, 0.));
rd = normalize(vec3(rd.x*cos(-a)+rd.z*sin(-a), rd.y, -rd.x*sin(-a)+rd.z*cos(-a)));
float t = raymarch(ro, rd);
if(t < 0.0) { fragColor = vec4(0.05,0.05,0.1,1.); return; }
vec3 p = ro+rd*t;
vec3 N = calcNormal(p);
vec3 V = normalize(-rd);
vec3 L = normalize(vec3(2.,3.,-1.));
vec3 H = normalize(V+L);
// Matรฉriaux PBR (mรฉtal dorรฉ)
float roughness = 0.25;
float metalness = 0.95;
vec3 albedo = vec3(1.0, 0.71, 0.29); // Or
float NdotV = max(dot(N,V),0.001);
float NdotL = max(dot(N,L),0.0);
float NdotH = max(dot(N,H),0.0);
float HdotV = max(dot(H,V),0.0);
float D = ggxD(NdotH, roughness);
float G = smithG(NdotV, NdotL, roughness);
float F = fresnel(HdotV, mix(0.04, 1.0, metalness));
float spec = (D*G*F)/max(4.*NdotV*NdotL,0.001);
vec3 diff = (1.-F)*(1.-metalness)*albedo/3.14159;
vec3 col = (diff + vec3(spec)) * NdotL * 2.0 + albedo*0.05;
// ACES tone mapping
col = col*(col+0.0245786)/(col*(0.983729*col+0.432951)+0.238081);
fragColor = vec4(col, 1.0);
}Ambient Occlusion + Orbital Camera
Ambient Occlusion via normal ray marching, orbital camera with proper view matrix. AO adds depth and realism by darkening crevices.
float sdBox(vec3 p, vec3 s) {
vec3 d=abs(p)-s; return length(max(d,0.))+min(max(d.x,max(d.y,d.z)),0.);
}
float sdPlane(vec3 p){ return p.y+1.0; }
float scene(vec3 p) {
float t = iTime*0.5;
float d = sdPlane(p);
d = min(d, length(p-vec3(sin(t)*0.6,0.,0.))-0.5); // Sphรจre oscillante
d = min(d, sdBox(p-vec3(-1.0,-0.4,0.0),vec3(0.3,0.6,0.3))); // Boรฎte
return d;
}
vec3 calcNormal(vec3 p) {
vec2 e=vec2(0.001,0.);
return normalize(vec3(scene(p+e.xyy)-scene(p-e.xyy),
scene(p+e.yxy)-scene(p-e.yxy),
scene(p+e.yyx)-scene(p-e.yyx)));
}
float ambientOcclusion(vec3 p, vec3 n) {
float occ=0., w=1.;
for(int i=1;i<=5;i++){
float d=float(i)*0.12;
occ+=w*(d-scene(p+n*d));
w*=0.5;
}
return clamp(1.-occ*3., 0., 1.);
}
float raymarch(vec3 ro, vec3 rd) {
float t=0.;
for(int i=0;i<80;i++){float d=scene(ro+rd*t);if(d<0.001)return t;t+=d;if(t>30.)return -1.;}
return -1.;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord*2.-iResolution.xy)/iResolution.y;
// Camรฉra orbitale
float ca=cos(iTime*0.3), sa=sin(iTime*0.3);
vec3 ro = vec3(3.*sa,1.5,3.*ca);
vec3 ww = normalize(-ro+vec3(0.,0.,0.));
vec3 uu = normalize(cross(ww,vec3(0.,1.,0.)));
vec3 vv = cross(uu,ww);
vec3 rd = normalize(uv.x*uu + uv.y*vv + 1.5*ww);
float t = raymarch(ro,rd);
if(t<0.){ fragColor=vec4(0.4,0.6,0.9,1.); return; }
vec3 p = ro+rd*t;
vec3 n = calcNormal(p);
vec3 L = normalize(vec3(1.,2.,1.5));
float diff = max(dot(n,L),0.);
float ao = ambientOcclusion(p,n);
vec3 col = vec3(0.9,0.85,0.8)*(diff*0.8+0.2)*ao;
col = pow(clamp(col,0.,1.), vec3(0.4545)); // Gamma
fragColor = vec4(col, 1.0);
}Animated Metaballs
Metaballs via potential field ISO-surface: 3 spheres blend organically. The isosurface is found by sphere marching (SDF is approximate โ clamp prevents overshooting).
// Potentiel d'une metaball = rยฒ/dยฒ
float metaball(vec3 p, vec3 center, float radius) {
float d = length(p - center);
return (radius*radius) / (d*d + 0.0001);
}
float scene(vec3 p) {
float t = iTime;
// Somme des potentiels โ surface = champ > threshold (1.0 / sum > 0.4)
float m1 = metaball(p, vec3(sin(t)*0.8, cos(t*0.7)*0.5, 0.0), 0.70);
float m2 = metaball(p, vec3(cos(t*1.3)*0.6, sin(t*1.1)*0.7, 0.3), 0.60);
float m3 = metaball(p, vec3(sin(t*0.9+1.5)*0.5, 0.0, cos(t*1.2)*0.6), 0.65);
return 1.0/(m1+m2+m3) - 0.4; // Zรฉro = surface
}
vec3 calcNormal(vec3 p) {
vec2 e=vec2(0.01,0.);
return normalize(vec3(scene(p+e.xyy)-scene(p-e.xyy),
scene(p+e.yxy)-scene(p-e.yxy),
scene(p+e.yyx)-scene(p-e.yyx)));
}
float raymarch(vec3 ro, vec3 rd) {
float t=0.1;
for(int i=0;i<80;i++){
float d=scene(ro+rd*t);
if(d<0.001) return t;
t+=clamp(d,0.01,0.3);
if(t>10.) return -1.;
}
return -1.;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord*2.-iResolution.xy)/iResolution.y;
vec3 ro=vec3(0.,0.,-3.5);
vec3 rd=normalize(vec3(uv,1.5));
float t=raymarch(ro,rd);
if(t<0.){ fragColor=vec4(0.05,0.02,0.1,1.); return; }
vec3 p=ro+rd*t;
vec3 n=calcNormal(p);
vec3 L=normalize(vec3(1.5,2.,-1.));
float diff=max(dot(n,L),0.);
float spec=pow(max(dot(reflect(-L,n),-rd),0.),32.);
// Couleur arc-en-ciel basรฉe sur la position
vec3 col=0.5+0.5*cos(p.xzy*2.+vec3(0.,2.1,4.2));
col*=diff*0.8+0.3;
col+=vec3(0.5)*spec;
fragColor=vec4(col,1.);
}Complete GLSL/WGSL Functions
mix(x, y, a)Linear interpolation between x and y
vec3 color = mix(vec3(1,0,0), vec3(0,0,1), 0.5);
smoothstep(edge0, edge1, x)Smooth transition between edge0 and edge1
float edge = smoothstep(0.3, 0.7, uv.x);
step(edge, x)Returns 0.0 if x < edge, else 1.0
float mask = step(0.5, uv.x);
fract(x)Fractional part (x - floor(x))
float pattern = fract(uv.x * 5.0);
floor(x)Round down
int cell = int(floor(uv.x * 10.0));
ceil(x)Round up
int cell = int(ceil(uv.x * 10.0));
mod(x, y)Modulo (remainder)
float tiled = mod(uv.x, 0.1);
clamp(x, min, max)Clamp x between min and max
float safe = clamp(uv.x, 0.0, 1.0);
length(v)Vector length (distance)
float dist = length(uv - vec2(0.5));
distance(p0, p1)Distance between two points
float d = distance(uv, vec2(0.5));
dot(a, b)Dot product
float dp = dot(vec2(1,0), vec2(0,1)); // 0.0
cross(a, b)Cross product (3D only)
vec3 normal = cross(vec3(1,0,0), vec3(0,1,0));
normalize(v)Normalize vector (length = 1)
vec2 dir = normalize(vec2(1,1));
reflect(I, N)Reflect vector I on normal N
vec3 reflected = reflect(lightDir, normal);
refract(I, N, eta)Refraction with index eta
vec3 refracted = refract(rayDir, normal, 0.9);
texture(sampler, uv)Sample a texture
vec4 color = texture(iChannel0, uv);
textureLod(sampler, uv, lod)Sample with level of detail
vec4 color = textureLod(iChannel0, uv, 0.0);
sin(x), cos(x), tan(x)Trigonometric functions
float wave = sin(uv.x * 10.0);
asin(x), acos(x), atan(x)Inverse trigonometric functions
float angle = atan(uv.y, uv.x);
pow(x, y)x raised to power y
float curve = pow(uv.x, 2.0);
exp(x)Exponential (e^x)
float decay = exp(-dist * 10.0);
log(x)Natural logarithm
float value = log(uv.x + 1.0);
sqrt(x)Square root
float dist = sqrt(dx*dx + dy*dy);
abs(x)Absolute value
float dist = abs(uv.x - 0.5);
sign(x)Sign (-1, 0, or 1)
float dir = sign(uv.x - 0.5);
min(a, b), max(a, b)Minimum and maximum
float d = min(d1, d2);
WGSL Specifics
Key Differences from GLSL
- Rust-like syntax instead of C-like
- Explicit types required (f32, i32, u32)
- No function overloading
- Improved memory safety
- Structures and modules supported
Basic WGSL Structure
Basic WGSL fragment shader structure โ click to see the live GLSL equivalent
// WGSL โ syntaxe WebGPU (pour rรฉfรฉrence)
@fragment
fn main(@location(0) fragCoord: vec2<f32>) -> @location(0) vec4<f32> {
let uv = fragCoord / uniforms.resolution;
let color = vec3<f32>(uv.x, uv.y, 0.5);
return vec4<f32>(color, 1.0);
}
// โ รquivalent GLSL (compilable ci-dessous)
// void mainImage(out vec4 fragColor, in vec2 fragCoord) {
// vec2 uv = fragCoord / iResolution.xy;
// vec3 color = vec3(uv.x, uv.y, 0.5);
// fragColor = vec4(color, 1.0);
// }WGSL Types vs GLSL
WGSL โ GLSL type mapping โ exact equivalents
// WGSL // GLSL รฉquivalent let f: f32 = 1.0; // float f = 1.0; let i: i32 = 42; // int i = 42; let u: u32 = 100u; // uint u = 100u; let v2: vec2<f32> = vec2<f32>(1.0, 2.0); // vec2 v2 = vec2(1.0, 2.0); let v3: vec3<f32> = vec3<f32>(1.0, 2.0, 3.0); // vec3 v3 = ... let v4: vec4<f32> = vec4<f32>(1.0, 2.0, 3.0, 4.0); // Matrices WGSL let m2: mat2x2<f32> = mat2x2<f32>(1.0, 0.0, 0.0, 1.0); // mat2 m2 let m4: mat4x4<f32> = mat4x4<f32>(/* ... */); // mat4 m4 // Texture WGSL var tex: texture_2d<f32>; // GLSL: uniform sampler2D tex; var smp: sampler;
WGSL Uniforms vs GLSL Uniforms
WGSL uses bound structs โ GLSL exposes iTime/iResolution/iMouse as globals
// WGSL โ uniforms via struct + bindings
struct Uniforms {
time: f32,
resolution: vec2<f32>,
mouse: vec4<f32>,
};
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
@fragment
fn main(@builtin(position) fragCoord: vec4<f32>) -> @location(0) vec4<f32> {
let uv = fragCoord.xy / uniforms.resolution;
let t = uniforms.time;
let r = length(uv - vec2<f32>(0.5));
return vec4<f32>(uv, 0.5 + 0.5 * sin(t), 1.0);
}
// GLSL โ uniforms globaux (iTime, iResolution, iMouse)
// void mainImage(out vec4 fragColor, in vec2 fragCoord) {
// vec2 uv = fragCoord / iResolution.xy; <- uniforms.resolution
// float t = iTime; <- uniforms.time
// fragColor = vec4(uv, 0.5+0.5*sin(t), 1.0);
// }GLSL โ WGSL Converter
โ ๏ธ Automatic conversion โ may require manual adjustments. Always verify the converted code.
Discord Commands
Quick reference /shader & uniforms
ยท 3 minDiscord Commands Reference
๐ Quick Start
Paste your GLSL code directly into /shader. The bot compiles and returns an animated GIF within seconds. 17 slash commands available โ shaders, AI, audio, collab, marketplace and more.
๐ผ๏ธ Shaders
/shaderMainCompiles and displays a custom GLSL/WGSL shader.
code: Your GLSL code (required)resolution: 480x270 / 960x540 / 1920x1080 (default: 480x270)duration: 0.5โ5.0s (default: 2s)format: gif / webp / png-sequenceview: 2d / 3d (render on 3D mesh)mesh: sphere / cube / torus / plane (when view=3d)texture0โ3: Image URL for iChannel0โ3/shader-presetRuns one of 1,200+ pre-built presets (nebula, matrix, particles, neoncityโฆ). Autocomplete available.
preset: Preset name (autocomplete)resolution / duration / format / view / mesh: Same options as /shader/shader-generateAIGenerates a shader via guided visual parameters. Autocomplete on every option.
shape: Shape (circle, wave, fractalโฆ)color / animation / speed / pattern / background / effect / complexity: Visual options (all optional)resolution / duration / view / mesh: Same options as /shader/shader-promptAIGenerates a full shader from a natural language description (e.g. "purple nebula with twinkling stars").
description: What you want to see (required)resolution / duration / view / mesh: Same options as /shader/shader-codeDisplays the GLSL source code of a preset. Autocomplete available.
name: Preset name (autocomplete)/shader-minecraftMinecraftMinecraft shaders โ OptiFine, Iris and Vibrant Visuals. 50+ dedicated presets.
loader: optifine / iris / vibrantcode / preset: Custom shader or Minecraft preset (optional)/shader-helpSends a link to this guide and the web dashboard.
๐ค AI & Assistant
/aiRAGRAG-powered GLSL assistant. Sub-commands:
/ai ask โ General GLSL / ShaderBot question/ai preset โ Detailed info about a preset/ai suggest โ Suggestions based on your code/ai debug โ Debug a shader/ai analyze โ Deep code analysis/ai image / screenshot / match โ Visual analysis (VLM)/agentAutonomous shader generation agent.
/agent status โ Show status and recent stats/agent generate โ Trigger a generation cycle (admin)๐ต Audio & Media
/audioAudio-reactive shaders from a Discord voice channel.
/audio join โ Bot joins the voice channel/audio leave โ Bot leaves the voice channel/audio shader โ Renders an audio-reactive shader (audio_bars, audio_pulse, audio_spectrum)/musicAudioCraftAI music generation via AudioCraft (Meta). Returns a .wav file.
/music generate โ Generates a clip from a prompt, style and duration๐ Data & Visualisation
/datavizRenders charts (bar, line, pie, scatter, heatmapโฆ) as animated shader GIFs.
/dataviz-liveWebSocketLive data visualisation via WebSocket.
/dataviz-live connect โ [url] [jsonpath] [min] [max]๐ค Collaboration & Streaming
/collabReal-time collaborative shader editing.
/collab start โ [preset] โ create a session/collab join / leave / snapshot โ Join, leave or snapshot/sceneOBSOBS scenes โ create browser sources pointing to your shaders.
/scene create โ [preset] โ returns an OBS Browser Source URL/scene list / delete โ List or delete your scenes/streamTwitchTwitch overlay โ connect a shader stream to your broadcast.
/stream connect โ [username] [preset]/stream shader / disconnect โ Change shader or disconnect๐ Marketplace
/marketplaceBuy, sell and manage shaders on the community marketplace.
/marketplace list / buy / sell / my-shaders โ Browse, purchase, sell, view your shaders๐ฆ Variables Available in your Shader
iTimefloat โ Time in secondsiResolutionvec3 โ Canvas size (x, y, ratio)iMousevec4 โ Mouse positionfragCoordvec2 โ Current pixel coordsiChannel0โ3sampler2D โ Optional texturesfragColorvec4 out โ Output colorโ Minimal Example โ Ready to Paste in /shader
Ready-to-use plasma shader. Copy this code into /shader code: to try it.
// Plasma colorรฉ animรฉ โ copiez et lancez avec /shader
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
vec2 p = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
float t = iTime;
float v1 = sin(p.x * 4.0 + t);
float v2 = sin(p.y * 4.0 + t * 1.3);
float v3 = sin((p.x + p.y) * 4.0 + t * 0.7);
float v = (v1 + v2 + v3) / 3.0;
vec3 col = vec3(
sin(v * 3.14159) * 0.5 + 0.5,
sin(v * 3.14159 + 2.094) * 0.5 + 0.5,
sin(v * 3.14159 + 4.189) * 0.5 + 0.5
);
fragColor = vec4(col, 1.0);
}๐ท With #define โ Compact Syntax
#define macros work normally โ t, r, PI, and other shorthands are all supported.
// Les macros #define sont supportรฉes
#define t iTime
#define r iResolution.xy
#define PI 3.14159265
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / r;
vec2 p = uv - 0.5;
float wave = sin(length(p) * 20.0 - t * 3.0);
float ring = smoothstep(0.02, 0.0, abs(wave * 0.05));
vec3 col = mix(
vec3(0.05, 0.05, 0.2),
vec3(0.2, 0.8, 1.0),
ring + sin(t + uv.x * PI) * 0.1
);
fragColor = vec4(col, 1.0);
}