Skip to content
Back to skills

Glsl Shader

ASecurity

Create audio-reactive GLSL visualizers for Bice-Box. Provides templates, audio uniforms (iRMSOutput, iRMSInput, iAudioTexture), coordinate patterns, and common shader functions.

  • 666 stars
  • 0 votes
  • 0 copies
  • 5 views
  • Added February 8, 2026
developmentgoreactrailsdebuggingperformance

Works with

  • cli
  • mcp

Security analysis

A100/100

Scanned February 10, 2026

npx -y skills add majiayu000/claude-skill-registry --skill glsl-shader --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Glsl Shader?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Glsl Shader
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-glsl-shader/badge)](https://www.skillsdirectory.com/skills/majiayu000-glsl-shader)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: glsl-shader
description: Create audio-reactive GLSL visualizers for Bice-Box. Provides templates, audio uniforms (iRMSOutput, iRMSInput, iAudioTexture), coordinate patterns, and common shader functions.
---

# GLSL Shader Development

Create audio-reactive GLSL visualizers for Bice-Box.

## Essential Structure

- **GLSL ES 3.00** only
- **DO NOT DECLARE** `#version 300 es` or `precision` directives (system adds these automatically)
- **Main function**: `void mainImage(out vec4 fragColor, in vec2 fragCoord)`
- **File types**:
  - Single-pass: `name.glsl`
  - Multi-pass: `name_bufferA.glsl`, `name_image.glsl`

## Standard Uniforms (DO NOT redeclare)

```glsl
uniform vec3  iResolution;    // Screen resolution (width, height, aspect)
uniform float iTime;          // Shader time (seconds)
uniform vec4  iMouse;         // Mouse coordinates (xy = current, zw = click)
uniform sampler2D iChannel0;  // Buffer A output (in image pass)
uniform sampler2D iChannel1;  // Buffer B output (in image pass)
```

## Audio Uniforms

```glsl
uniform float iRMSInput;      // Real-time input audio (0.0-1.0+) - USE FOR REACTIVITY
uniform float iRMSOutput;     // Real-time output audio (0.0-1.0+) - USE FOR REACTIVITY
uniform float iRMSTime;       // Cumulative time - NOT for reactivity, grows with audio
uniform sampler2D iAudioTexture; // FFT/waveform data
```

### Audio Reactivity - Important Notes

**Use iRMSOutput/iRMSInput for real-time reactivity:**
```glsl
float intensity = 0.3 + 0.7 * iRMSOutput;  // Pulse with audio
float scale = 1.0 + iRMSOutput * 0.5;       // Scale with audio
```

**Do NOT use iRMSTime for reactivity** - it's cumulative time that grows infinitely with audio input.

## Audio Texture Sampling

The `iAudioTexture` provides two rows of data:

```glsl
// FFT (frequency spectrum) - Row 0
// u = 0.0 (bass) to 1.0 (treble), y = 0.25
float bass = texture(iAudioTexture, vec2(0.1, 0.25)).x;
float mid = texture(iAudioTexture, vec2(0.5, 0.25)).x;
float treble = texture(iAudioTexture, vec2(0.9, 0.25)).x;

// Waveform (time domain) - Row 1
// u = time position (0.0 to 1.0), y = 0.75
float waveVal = texture(iAudioTexture, vec2(0.5, 0.75)).x;
float waveValSigned = (waveVal * 2.0) - 1.0; // Convert 0-1 to -1,1

// Loop over frequencies
for(float i = 0.0; i < 1.0; i += 0.01) {
    float fftMag = texture(iAudioTexture, vec2(i, 0.25)).x;
    // Use fftMag for frequency-based visualization
}
```

## Common Coordinate Patterns

```glsl
// Normalized coordinates (0-1)
vec2 uv = fragCoord.xy / iResolution.xy;

// Centered coordinates (-0.5 to 0.5)
vec2 uv_centered = (fragCoord.xy - 0.5 * iResolution.xy) / iResolution.xy;

// Aspect-corrected coordinates (for perfect circles)
vec2 uv_centered = fragCoord.xy - 0.5 * iResolution.xy;
vec2 uv_aspect = uv_centered / iResolution.y;

// Polar coordinates
vec2 centered = fragCoord.xy - 0.5 * iResolution.xy;
float r = length(centered) / iResolution.y;
float theta = atan(centered.y, centered.x);
```

## Single-Pass Template

```glsl
// Optional resolution scaling (0.5 = half res for performance)
// resolution: 0.5

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    // Normalized coordinates
    vec2 uv = fragCoord.xy / iResolution.xy;

    // Audio reactivity
    float audioLevel = iRMSOutput;

    // Sample audio texture
    float bass = texture(iAudioTexture, vec2(0.1, 0.25)).x;

    // Your visualization here
    vec3 col = vec3(uv.x, uv.y, audioLevel);

    // Output
    fragColor = vec4(col, 1.0);
}
```

## Multi-Pass Template

**Buffer A** (`effect_name_bufferA.glsl`) - Feedback/persistence:
```glsl
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = fragCoord.xy / iResolution.xy;

    // Read previous frame from iChannel0 (self-reference)
    vec4 prev = texture(iChannel0, uv);

    // Fade previous frame
    prev *= 0.95;

    // Add new content
    float audioLevel = iRMSOutput;
    vec3 newContent = vec3(0.0);

    // ... your drawing code ...

    // Combine
    vec3 col = prev.rgb + newContent;

    fragColor = vec4(col, 1.0);
}
```

**Image Pass** (`effect_name_image.glsl`) - Final output:
```glsl
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = fragCoord.xy / iResolution.xy;

    // Read from Buffer A via iChannel0
    vec4 bufferA = texture(iChannel0, uv);

    // Apply post-processing
    vec3 col = bufferA.rgb;
    col = pow(col, vec3(1.0/2.2)); // Gamma correction

    fragColor = vec4(col, 1.0);
}
```

**JSON Configuration** (`effect_name.json`):
```json
{
    "shader": "shaders/effect_name"
}
```

## Multi-Pass Setup Notes

- **Buffer A** self-references via `iChannel0` (previous frame)
- **Image pass** reads buffers via `iChannel0` (Buffer A), `iChannel1` (Buffer B), etc.
- Use for: trails, feedback, persistence, fluid simulation
- JSON uses base name without `_bufferA` or `_image` suffix

## Audio-Reactive Patterns

### Pulsing/Scaling
```glsl
float pulse = 0.5 + 0.5 * iRMSOutput;
float scale = 1.0 + iRMSOutput * 0.3;
```

### Color Modulation
```glsl
vec3 col = vec3(0.5) + 0.5 * vec3(
    sin(iTime + iRMSOutput * 2.0),
    sin(iTime + iRMSOutput * 3.0 + 2.0),
    sin(iTime + iRMSOutput * 4.0 + 4.0)
);
```

### Frequency-Based Visualization
```glsl
// Spectrum analyzer style
for(float i = 0.0; i < 1.0; i += 0.02) {
    float fft = texture(iAudioTexture, vec2(i, 0.25)).x;
    if(abs(uv.x - i) < 0.01 && uv.y < fft) {
        col = vec3(1.0, 0.5, 0.0);
    }
}
```

### Waveform Visualization
```glsl
float wave = texture(iAudioTexture, vec2(uv.x, 0.75)).x;
wave = (wave * 2.0) - 1.0; // Convert to -1,1
float dist = abs(uv.y - 0.5 - wave * 0.3);
if(dist < 0.01) {
    col = vec3(0.0, 1.0, 0.5);
}
```

## MCP Workflow

**Workflow for creating/updating shaders:**

1. **Create shader file(s)** in `shaders/` directory
   - Single-pass: `shaders/my_shader.glsl`
   - Multi-pass: `shaders/my_shader_bufferA.glsl`, `shaders/my_shader_image.glsl`
   - Use Write tool to create files directly

2. **Activate visualizer**
   ```
   mcp__bice-box__set_visualizer(visualizerName: "my_shader")
   ```

3. **Link to audio effect** - Add shader comment in `.sc` file
   ```supercollider
   // shader: my_shader
   (
       var defName = \my_effect;
       // ... rest of effect code
   )
   ```
   This auto-loads the shader when the effect activates.

4. **List available visualizers**
   ```
   mcp__bice-box__list_visualizers()
   ```
   Returns p5.js sketches and GLSL shaders

5. **Iterate** - Edit and save, hot-reload handles the rest
   - Changes auto-reload when files are saved
   - No need to manually reload

## Common Shader Functions

```glsl
// Smooth minimum (blend shapes)
float smin(float a, float b, float k) {
    float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
    return mix(b, a, h) - k * h * (1.0 - h);
}

// Rotate 2D
vec2 rotate(vec2 v, float angle) {
    float c = cos(angle);
    float s = sin(angle);
    return vec2(v.x * c - v.y * s, v.x * s + v.y * c);
}

// Hash function (pseudo-random)
float hash(vec2 p) {
    return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
}

// Smooth step
float smoothstep(float edge0, float edge1, float x) {
    float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
    return t * t * (3.0 - 2.0 * t);
}
```

## Performance Tips

- **Use resolution scaling** for complex shaders:
  ```glsl
  // resolution: 0.5  // Half resolution
  ```

- **Minimize texture lookups** - Cache results when possible
  ```glsl
  vec4 prev = texture(iChannel0, uv);  // Once per fragment
  ```

- **Avoid loops when possible** - Unroll or use noise functions

- **Use built-in functions** - `smoothstep`, `mix`, `clamp` are optimized

- **Test on target hardware** - Raspberry Pi has different performance characteristics

## Common Gotchas

- **Don't declare `#version 300 es`** - System adds it automatically
- **Don't declare `precision`** - System handles this
- **iRMSTime is NOT for reactivity** - Use iRMSOutput/iRMSInput instead
- **Audio texture Y coordinates** - FFT at 0.25, waveform at 0.75 (not 0.0 and 1.0)
- **Multi-pass naming** - Must use `_bufferA`, `_image` suffixes exactly
- **Aspect ratio** - Divide by `iResolution.y` for circular shapes, not `iResolution.x`

## Debugging

- **Check shader compilation** - Look for errors in console logs
  ```
  mcp__bice-box__read_logs(lines: 100, filter: "shader")
  ```

- **Test with simple output** - Start with solid colors to verify structure
  ```glsl
  fragColor = vec4(1.0, 0.0, 0.0, 1.0);  // Red
  ```

- **Visualize UVs** - Debug coordinates
  ```glsl
  fragColor = vec4(uv, 0.0, 1.0);
  ```

- **Check audio uniforms** - Verify audio is flowing
  ```glsl
  fragColor = vec4(vec3(iRMSOutput), 1.0);  // Should pulse with audio
  ```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.