Skip to content
Back to skills

Glsl

ASecurity

GLSL shader programming for JARVIS holographic effects

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 27, 2026
data-aitypescriptgobashtestingsecurityperformance

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned May 27, 2026

npx -y skills add anvilfilbert/Auto-Crypto-Tradingjournal --skill glsl --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Glsl?

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

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

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
description: GLSL shader programming for JARVIS holographic effects
model: sonnet
risk_level: LOW
version: 1.1.0
---

# GLSL Shader Programming Skill

> **File Organization**: This skill uses split structure. See `references/` for advanced shader patterns.

## 1. Overview

This skill provides GLSL shader expertise for creating holographic visual effects in the JARVIS AI Assistant HUD. It focuses on efficient GPU programming for real-time rendering.

**Risk Level**: LOW - GPU-side code with limited attack surface, but can cause performance issues

**Primary Use Cases**:
- Holographic panel effects with scanlines
- Animated energy fields and particle systems
- Data visualization with custom rendering
- Post-processing effects (bloom, glitch, chromatic aberration)

## 2. Core Responsibilities

### 2.1 Fundamental Principles

1. **TDD First**: Write visual regression tests and shader unit tests before implementation
2. **Performance Aware**: Profile GPU performance, optimize for 60 FPS target
3. **Precision Matters**: Use appropriate precision qualifiers for performance
4. **Avoid Branching**: Minimize conditionals in shaders for GPU efficiency
5. **Optimize Math**: Use built-in functions, avoid expensive operations
6. **Uniform Safety**: Validate uniform inputs before sending to GPU
7. **Loop Bounds**: Always use constant loop bounds to prevent GPU hangs
8. **Memory Access**: Optimize texture lookups and varying interpolation

## 3. Implementation Workflow (TDD)

### 3.1 Step 1: Write Failing Test First

```typescript
// tests/shaders/holographic-panel.test.ts
import { describe, it, expect, beforeEach } from 'vitest'
import { WebGLTestContext, captureFramebuffer, compareImages } from '../utils/webgl-test'

describe('HolographicPanelShader', () => {
  let ctx: WebGLTestContext

  beforeEach(() => {
    ctx = new WebGLTestContext(256, 256)
  })

  // Unit test: Shader compiles
  it('should compile without errors', () => {
    const shader = ctx.compileShader(holoFragSource, ctx.gl.FRAGMENT_SHADER)
    expect(shader).not.toBeNull()
    expect(ctx.getShaderErrors()).toEqual([])
  })

  // Unit test: Uniforms are accessible
  it('should have required uniforms', () => {
    const program = ctx.createProgram(vertSource, holoFragSource)
    expect(ctx.getUniformLocation(program, 'uTime')).not.toBeNull()
    expect(ctx.getUniformLocation(program, 'uColor')).not.toBeNull()
    expect(ctx.getUniformLocation(program, 'uOpacity')).not.toBeNull()
  })

  // Visual regression test
  it('should render scanlines correctly', async () => {
    ctx.renderShader(holoFragSource, { uTime: 0, uColor: [0, 0.5, 1], uOpacity: 1 })
    const result = captureFramebuffer(ctx)
    const baseline = await loadBaseline('holographic-scanlines.png')
    expect(compareImages(result, baseline, { threshold: 0.01 })).toBeLessThan(0.01)
  })

  // Edge case test
  it('should handle extreme UV values', () => {
    const testCases = [
      { uv: [0, 0], expected: 'no crash' },
      { uv: [1, 1], expected: 'no crash' },
      { uv: [0.5, 0.5], expected: 'no crash' }
    ]
    testCases.forEach(({ uv }) => {
      expect(() => ctx.renderAtUV(holoFragSource, uv)).not.toThrow()
    })
  })
})
```

### 3.2 Step 2: Implement Minimum to Pass

```glsl
// Start with minimal shader that passes tests
#version 300 es
precision highp float;

uniform float uTime;
uniform vec3 uColor;
uniform float uOpacity;

in vec2 vUv;
out vec4 fragColor;

void main() {
  // Minimal implementation to pass compilation test
  fragColor = vec4(uColor, uOpacity);
}
```

### 3.3 Step 3: Refactor with Full Implementation

```glsl
// Expand to full implementation after tests pass
void main() {
  vec2 uv = vUv;
  float scanline = sin(uv.y * 100.0) * 0.1 + 0.9;
  float pulse = sin(uTime * 2.0) * 0.1 + 0.9;
  vec3 color = uColor * scanline * pulse;
  fragColor = vec4(color, uOpacity);
}
```

### 3.4 Step 4: Run Full Verification

```bash
# Run all shader tests
npm run test:shaders

# Visual regression tests
npm run test:visual -- --update-snapshots  # First time only
npm run test:visual

# Performance benchmark
npm run bench:shaders

# Cross-browser compilation check
npm run test:webgl-compat
```

## 4. Technology Stack & Versions

### 4.1 GLSL Versions

| Version | Context | Features |
|---------|---------|----------|
| GLSL ES 3.00 | WebGL 2.0 | Modern features, better precision |
| GLSL ES 1.00 | WebGL 1.0 | Legacy support |

### 4.2 Shader Setup

```glsl
#version 300 es
precision highp float;
precision highp int;

// WebGL 2.0 shader header
```

## 5. Performance Patterns

### 5.1 Avoid Branching - Use Mix/Step

```glsl
// ❌ BAD - GPU branch divergence
vec3 getColor(float value) {
  if (value < 0.3) {
    return vec3(1.0, 0.0, 0.0);  // Red
  } else if (value < 0.7) {
    return vec3(1.0, 1.0, 0.0);  // Yellow
  } else {
    return vec3(0.0, 1.0, 0.0);  // Green
  }
}

// ✅ GOOD - Branchless with mix/step
vec3 getColor(float value) {
  vec3 red = vec3(1.0, 0.0, 0.0);
  vec3 yellow = vec3(1.0, 1.0, 0.0);
  vec3 green = vec3(0.0, 1.0, 0.0);

  vec3 color = mix(red, yellow, smoothstep(0.3, 0.31, value));
  color = mix(color, green, smoothstep(0.7, 0.71, value));
  return color;
}
```

### 5.2 Texture Atlases - Reduce Draw Calls

```glsl
// ❌ BAD - Multiple texture bindings
uniform sampler2D uIcon1;
uniform sampler2D uIcon2;
uniform sampler2D uIcon3;

vec4 getIcon(int id) {
  if (id == 0) return texture(uIcon1, vUv);
  if (id == 1) return texture(uIcon2, vUv);
  return texture(uIcon3, vUv);
}

// ✅ GOOD - Single atlas texture
uniform sampler2D uIconAtlas;
uniform vec4 uAtlasOffsets[3];  // [x, y, width, height] for each icon

vec4 getIcon(int id) {
  vec4 offset = uAtlasOffsets[id];
  vec2 atlasUV = offset.xy + vUv * offset.zw;
  return texture(uIconAtlas, atlasUV);
}
```

### 5.3 Level of Detail (LOD) - Distance-Based Quality

```glsl
// ❌ BAD - Same quality regardless of distance
const int NOISE_OCTAVES = 8;

float noise(vec3 p) {
  float result = 0.0;
  for (int i = 0; i < NOISE_OCTAVES; i++) {
    result += snoise(p * pow(2.0, float(i)));
  }
  return result;
}

// ✅ GOOD - Reduce octaves based on distance
uniform float uCameraDistance;

float noise(vec3 p) {
  // Fewer octaves when far away (detail not visible)
  int octaves = int(mix(2.0, 8.0, 1.0 - smoothstep(10.0, 100.0, uCameraDistance)));
  float result = 0.0;
  for (int i = 0; i < 8; i++) {
    if (i >= octaves) break;
    result += snoise(p * pow(2.0, float(i)));
  }
  return result;
}
```

### 5.4 Uniform Batching - Minimize CPU-GPU Transfers

```glsl
// ❌ BAD - Many individual uniforms
uniform float uPosX;
uniform float uPosY;
uniform float uPosZ;
uniform float uRotX;
uniform float uRotY;
uniform float uRotZ;
uniform float uScaleX;
uniform float uScaleY;
uniform float uScaleZ;

// ✅ GOOD - Packed into vectors/matrices
uniform vec3 uPosition;
uniform vec3 uRotation;
uniform vec3 uScale;
// Or even better:
uniform mat4 uTransform;
```

### 5.5 Precision Optimization - Use Appropriate Precision

```glsl
// ❌ BAD - Everything highp (wastes GPU cycles)
precision highp float;

highp vec3 color;
highp float alpha;
highp vec2 uv;

// ✅ GOOD - Match precision to data needs
precision highp float;  // Default for calculations

mediump vec3 color;     // 0-1 range, mediump sufficient
mediump float alpha;    // 0-1 range
highp vec2 uv;          // Need precision for texture coords
lowp int flags;         // Boolean-like values
```

### 5.6 Cache Texture Lookups

```glsl
// ❌ BAD - Redundant texture fetches
void main() {
  vec3 diffuse = texture(uTexture, vUv).rgb;
  // ... some code ...
  float alpha = texture(uTexture, vUv).a;  // Same lookup!
  // ... more code ...
  vec3 doubled = texture(uTexture, vUv).rgb * 2.0;  // Again!
}

// ✅ GOOD - Cache the result
void main() {
  vec4 texSample = texture(uTexture, vUv);
  vec3 diffuse = texSample.rgb;
  float alpha = texSample.a;
  vec3 doubled = texSample.rgb * 2.0;
}
```

## 6. Implementation Patterns

### 6.1 Holographic Panel Shader

```glsl
// shaders/holographic-panel.frag
#version 300 es
precision highp float;

uniform float uTime;
uniform vec3 uColor;
uniform float uOpacity;
uniform vec2 uResolution;

in vec2 vUv;
out vec4 fragColor;

const int SCANLINE_COUNT = 50;

void main() {
  vec2 uv = vUv;

  // Scanline effect
  float scanline = 0.0;
  for (int i = 0; i < SCANLINE_COUNT; i++) {
    float y = float(i) / float(SCANLINE_COUNT);
    scanline += smoothstep(0.0, 0.002, abs(uv.y - y));
  }
  scanline = 1.0 - scanline * 0.3;

  // Edge glow
  float edge = 1.0 - smoothstep(0.0, 0.05, min(
    min(uv.x, 1.0 - uv.x),
    min(uv.y, 1.0 - uv.y)
  ));

  // Animated pulse
  float pulse = sin(uTime * 2.0) * 0.1 + 0.9;

  vec3 color = uColor * scanline * pulse;
  color += vec3(0.0, 0.5, 1.0) * edge * 0.5;

  fragColor = vec4(color, uOpacity);
}
```

### 6.2 Energy Field Shader

```glsl
// shaders/energy-field.frag
#version 300 es
precision highp float;

uniform float uTime;
uniform vec3 uColor;

in vec2 vUv;
in vec3 vNormal;
in vec3 vViewPosition;
out vec4 fragColor;

float snoise(vec3 v) {
  return fract(sin(dot(v, vec3(12.9898, 78.233, 45.543))) * 43758.5453);
}

void main() {
  vec3 viewDir = normalize(-vViewPosition);
  float fresnel = pow(1.0 - abs(dot(viewDir, vNormal)), 3.0);
  float noise = snoise(vec3(vUv * 5.0, uTime * 0.5));

  vec3 color = uColor * fresnel;
  color += uColor * noise * 0.2;
  float alpha = fresnel * 0.8 + noise * 0.1;

  fragColor = vec4(color, alpha);
}
```

### 6.3 Data Visualization Shader

```glsl
// shaders/data-bar.frag
#version 300 es
precision highp float;

uniform float uValue;
uniform float uThreshold;
uniform vec3 uColorLow;
uniform vec3 uColorHigh;
uniform vec3 uColorWarning;

in vec2 vUv;
out vec4 fragColor;

void main() {
  float fill = step(vUv.x, uValue);
  vec3 color = mix(uColorLow, uColorHigh, uValue);
  color = mix(color, uColorWarning, step(uThreshold, uValue));
  float gradient = vUv.y * 0.3 + 0.7;
  fragColor = vec4(color * gradient * fill, fill);
}
```

## 7. Security & Performance Standards

### 7.1 GPU Safety

| Risk | Mitigation |
|------|------------|
| Infinite loops | Always use constant loop bounds |
| GPU hangs | Test shaders with small datasets first |
| Memory exhaustion | Limit texture sizes |

### 7.2 Loop Safety Pattern

```glsl
// ❌ BAD - Dynamic loop bound
for (int i = 0; i < int(uCount); i++) { }

// ✅ GOOD - Constant loop bound
const int MAX_ITERATIONS = 100;
for (int i = 0; i < MAX_ITERATIONS; i++) {
  if (i >= int(uCount)) break;
}
```

## 8. Common Mistakes & Anti-Patterns

### 8.1 Never: Use Dynamic Loop Bounds

```glsl
// ❌ DANGEROUS - May cause GPU hang
for (int i = 0; i < uniformValue; i++) { }

// ✅ SAFE - Constant bound with early exit
const int MAX = 100;
for (int i = 0; i < MAX; i++) {
  if (i >= uniformValue) break;
}
```

### 8.2 Never: Divide Without Checking Zero

```glsl
// ❌ DANGEROUS - Division by zero
float result = value / divisor;

// ✅ SAFE - Guard against zero
float result = value / max(divisor, 0.0001);
```

## 9. Pre-Implementation Checklist

### Phase 1: Before Writing Code

- [ ] Write shader compilation test
- [ ] Write uniform accessibility test
- [ ] Create baseline images for visual regression tests
- [ ] Define performance targets (FPS, draw calls)
- [ ] Review existing shaders for reusable patterns

### Phase 2: During Implementation

- [ ] All loops have constant bounds
- [ ] No division by zero possible
- [ ] Using branchless patterns (mix/step)
- [ ] Appropriate precision qualifiers
- [ ] Texture lookups cached
- [ ] Uniforms batched into vectors/matrices

### Phase 3: Before Committing

- [ ] All shader tests pass: `npm run test:shaders`
- [ ] Visual regression tests pass: `npm run test:visual`
- [ ] Performance benchmark meets targets: `npm run bench:shaders`
- [ ] Cross-browser compatibility verified
- [ ] No artifacts at edge cases (UV 0,0 and 1,1)
- [ ] Smooth animation timing verified

## 10. Summary

GLSL shaders power the visual effects in JARVIS HUD:

1. **TDD First**: Write tests before shaders - compilation, uniforms, visual regression
2. **Performance**: Use branchless patterns, texture atlases, LOD, precision optimization
3. **Safety**: Constant loop bounds, guard divisions
4. **Testing**: Verify across target browsers, benchmark GPU performance

**Remember**: Shaders run on GPU - a single bad shader can freeze the entire system.

---

**References**:
- `references/advanced-patterns.md` - Complex shader techniques

Files in this skill

  • SKILL.md12.2 KB
  • references/advanced-patterns.md2.9 KB

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…