LobeHub
WE

webgl

3
1.0.0

Summary

This WebGL Development Skill provides a secure, performance-focused toolkit for building GPU-accelerated shaders and visual effects for the JARVIS 3D HUD. It targets WebGL 2.0-capable browsers and emphasizes TDD-first workflows, shader validation, and strict performance budgets (draw calls, triangles, texture/buffer caps). Key features include reusable shader patterns, post-processing (bloom, glitch), particle systems with compute shader approaches, and real-time data visualization. Core responsibilities cover context loss handling, memory management, resource limits and timeout mechanisms to mitigate driver or resource exhaustion risks. The skill also prescribes fallbacks for non-WebGL environments and security-aware setup (failIfMajorPerformanceCaveat, capability checks). Use it to build high-performance holographic effects, robust particle systems, and production-grade visualization while minimizing GPU safety and security exposure.

SKILL.md

WebGL Development Skill

File Organization: This skill uses split structure. See references/ for advanced patterns and security examples.

1. Overview

This skill provides WebGL expertise for creating custom shaders and visual effects in the JARVIS AI Assistant HUD. It focuses on GPU-accelerated rendering with security considerations.

Risk Level: MEDIUM - Direct GPU access, potential for resource exhaustion, driver vulnerabilities

Primary Use Cases:

  • Custom shaders for holographic effects
  • Post-processing effects (bloom, glitch)
  • Particle systems with compute shaders
  • Real-time data visualization

2. Core Responsibilities

2.1 Fundamental Principles

  1. TDD First: Write tests before implementation - test shaders, contexts, and resources
  2. Performance Aware: Optimize GPU usage - batch draws, reuse buffers, compress textures
  3. GPU Safety: Implement timeout mechanisms and resource limits
  4. Shader Validation: Validate all shader inputs before compilation
  5. Context Management: Handle context loss gracefully
  6. Performance Budgets: Set strict limits on draw calls and triangles
  7. Fallback Strategy: Provide non-WebGL fallbacks
  8. Memory Management: Track and limit texture/buffer usage

3. Technology Stack & Versions

3.1 Browser Support

BrowserWebGL 2.0Notes
Chrome56+Full support
Firefox51+Full support
Safari15+WebGL 2.0 support
Edge79+Chromium-based

3.2 Security Considerations

*.ts
TypeScript
// Check WebGL support and capabilities
function getWebGLContext(canvas: HTMLCanvasElement): WebGL2RenderingContext | null {
  const gl = canvas.getContext('webgl2', {
    alpha: true,
    antialias: true,
    powerPreference: 'high-performance',
    failIfMajorPerformanceCaveat: true  // Fail if software rendering
  })

  if (!gl) {
    console.warn('WebGL 2.0 not supported')
    return null
  }

  return gl
}

4. Implementation Patterns

4.1 Safe Shader Compilation

*.ts
TypeScript
// utils/shaderUtils.ts

// ✅ Safe shader compilation with error handling
export function compileShader(
  gl: WebGL2RenderingContext,
  source: string,
  type: number
): WebGLShader | null {
  const shader = gl.createShader(type)
  if (!shader) return null

  gl.shaderSource(shader, source)
  gl.compileShader(shader)

  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    const error = gl.getShaderInfoLog(shader)
    console.error('Shader compilation error:', error)
    gl.deleteShader(shader)
    return null
  }

  return shader
}

// ✅ Safe program linking
export function createProgram(
  gl: WebGL2RenderingContext,
  vertexShader: WebGLShader,
  fragmentShader: WebGLShader
): WebGLProgram | null {
  const program = gl.createProgram()
  if (!program) return null

  gl.attachShader(program, vertexShader)
  gl.attachShader(program, fragmentShader)
  gl.linkProgram(program)

  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    const error = gl.getProgramInfoLog(program)
    console.error('Program linking error:', error)
    gl.deleteProgram(program)
    return null
  }

  return program
}

4.2 Context Loss Handling

*.ts
TypeScript
// composables/useWebGL.ts
export function useWebGL(canvas: Ref<HTMLCanvasElement | null>) {
  const gl = ref<WebGL2RenderingContext | null>(null)
  const contextLost = ref(false)

  onMounted(() => {
    if (!canvas.value) return

    // ✅ Handle context loss
    canvas.value.addEventListener('webglcontextlost', (e) => {
      e.preventDefault()
      contextLost.value = true
      console.warn('WebGL context lost')
    })

    canvas.value.addEventListener('webglcontextrestored', () => {
      contextLost.value = false
      initializeGL()
      console.info('WebGL context restored')
    })

    initializeGL()
  })

  function initializeGL() {
    gl.value = getWebGLContext(canvas.value!)
    // Reinitialize all resources
  }

  return { gl, contextLost }
}

4.3 Holographic Shader

*.glsl
GLSL
// shaders/holographic.frag
#version 300 es
precision highp float;

uniform float uTime;
uniform vec3 uColor;
uniform float uScanlineIntensity;

in vec2 vUv;
out vec4 fragColor;

void main() {
  // Scanline effect
  float scanline = sin(vUv.y * 200.0 + uTime * 2.0) * 0.5 + 0.5;
  scanline = mix(1.0, scanline, uScanlineIntensity);

  // Edge glow
  float edge = smoothstep(0.0, 0.1, vUv.x) *
               smoothstep(1.0, 0.9, vUv.x) *
               smoothstep(0.0, 0.1, vUv.y) *
               smoothstep(1.0, 0.9, vUv.y);

  vec3 color = uColor * scanline * edge;
  float alpha = edge * 0.8;

  fragColor = vec4(color, alpha);
}

4.4 Resource Management

*.ts
TypeScript
// utils/resourceManager.ts
export class WebGLResourceManager {
  private textures: Set<WebGLTexture> = new Set()
  private buffers: Set<WebGLBuffer> = new Set()
  private programs: Set<WebGLProgram> = new Set()

  private textureMemory = 0
  private readonly MAX_TEXTURE_MEMORY = 256 * 1024 * 1024  // 256MB

  constructor(private gl: WebGL2RenderingContext) {}

  createTexture(width: number, height: number): WebGLTexture | null {
    const size = width * height * 4  // RGBA

    // ✅ Enforce memory limits
    if (this.textureMemory + size > this.MAX_TEXTURE_MEMORY) {
      console.error('Texture memory limit exceeded')
      return null
    }

    const texture = this.gl.createTexture()
    if (texture) {
      this.textures.add(texture)
      this.textureMemory += size
    }
    return texture
  }

  dispose(): void {
    this.textures.forEach(t => this.gl.deleteTexture(t))
    this.buffers.forEach(b => this.gl.deleteBuffer(b))
    this.programs.forEach(p => this.gl.deleteProgram(p))
    this.textureMemory = 0
  }
}

4.5 Uniform Validation

*.ts
TypeScript
// ✅ Type-safe uniform setting
export function setUniforms(
  gl: WebGL2RenderingContext,
  program: WebGLProgram,
  uniforms: Record<string, number | number[] | Float32Array>
): void {
  for (const [name, value] of Object.entries(uniforms)) {
    const location = gl.getUniformLocation(program, name)
    if (!location) {
      console.warn(`Uniform '${name}' not found`)
      continue
    }

    if (typeof value === 'number') {
      gl.uniform1f(location, value)
    } else if (Array.isArray(value)) {
      switch (value.length) {
        case 2: gl.uniform2fv(location, value); break
        case 3: gl.uniform3fv(location, value); break
        case 4: gl.uniform4fv(location, value); break
        case 16: gl.uniformMatrix4fv(location, false, value); break
      }
    }
  }
}

5. Implementation Workflow (TDD)

5.1 Step-by-Step Process

  1. Write failing test -> 2. Implement minimum -> 3. Refactor -> 4. Verify
*.ts
TypeScript
// Step 1: tests/webgl/shaderCompilation.test.ts
import { describe, it, expect, beforeEach } from 'vitest'
import { compileShader } from '@/utils/shaderUtils'

describe('WebGL Shader Compilation', () => {
  let gl: WebGL2RenderingContext

  beforeEach(() => {
    gl = document.createElement('canvas').getContext('webgl2')!
  })

  it('should compile valid shader', () => {
    const source = `#version 300 es
      in vec4 aPosition;
      void main() { gl_Position = aPosition; }`
    expect(compileShader(gl, source, gl.VERTEX_SHADER)).not.toBeNull()
  })

  it('should return null for invalid shader', () => {
    expect(compileShader(gl, 'invalid', gl.FRAGMENT_SHADER)).toBeNull()
  })
})

// Step 2-3: Implement and refactor (see section 4.1)
// Step 4: npm test && npm run typecheck && npm run build

5.2 Testing Context and Resources

*.ts
TypeScript
describe('WebGL Context', () => {
  it('should handle context loss', async () => {
    const { gl, contextLost } = useWebGL(ref(canvas))
    gl.value?.getExtension('WEBGL_lose_context')?.loseContext()
    await nextTick()
    expect(contextLost.value).toBe(true)
  })
})

describe('Resource Manager', () => {
  it('should enforce memory limits', () => {
    const manager = new WebGLResourceManager(gl)
    expect(manager.createTexture(1024, 1024)).not.toBeNull()
    expect(manager.createTexture(16384, 16384)).toBeNull() // Exceeds limit
  })
})

6. Performance Patterns

6.1 Buffer Reuse

*.ts
TypeScript
// Bad - Creates new buffer every frame
const buffer = gl.createBuffer()
gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW)
gl.deleteBuffer(buffer)

// Good - Reuse buffer, update only data
gl.bufferSubData(gl.ARRAY_BUFFER, 0, data)  // Update existing buffer

6.2 Draw Call Batching

*.ts
TypeScript
// Bad - One draw call per object
objects.forEach(obj => {
  gl.useProgram(obj.program)
  gl.drawElements(...)
})

// Good - Batch by material/shader
const batches = groupByMaterial(objects)
batches.forEach(batch => {
  gl.useProgram(batch.program)
  batch.objects.forEach(obj => gl.drawElements(...))
})

6.3 Texture Compression

*.ts
TypeScript
// Bad - Always uncompressed RGBA
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image)

// Good - Use compressed formats when available
const ext = gl.getExtension('WEBGL_compressed_texture_s3tc')
if (ext) gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGBA_S3TC_DXT5_EXT, ...)

6.4 Instanced Rendering

*.ts
TypeScript
// Bad - Individual draw calls for particles
particles.forEach(p => {
  gl.uniform3fv(uPosition, p.position)
  gl.drawArrays(gl.TRIANGLES, 0, 6)
})

// Good - Single instanced draw call
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, particles.length)

6.5 VAO Usage

*.ts
TypeScript
// Bad - Rebind attributes every frame
gl.enableVertexAttribArray(0)
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0)

// Good - Use VAO to store attribute state
const vao = gl.createVertexArray()
gl.bindVertexArray(vao)
// Set up once, then just bind VAO for rendering

7. Security Standards

7.1 Known Vulnerabilities

CVESeverityDescriptionMitigation
CVE-2024-11691HIGHApple M series memory corruptionUpdate browser, OS patches
CVE-2023-1531HIGHChrome use-after-freeUpdate Chrome

7.2 OWASP Top 10 Coverage

OWASP CategoryRiskMitigation
A06 Vulnerable ComponentsHIGHKeep browsers updated
A10 SSRFLOWContext isolation by browser

7.3 GPU Resource Protection

*.ts
TypeScript
// ✅ Implement resource limits
const LIMITS = {
  maxDrawCalls: 100,
  maxTriangles: 1_000_000,
  maxTextures: 32,
  maxTextureSize: 4096
}

function checkLimits(stats: RenderStats): boolean {
  if (stats.drawCalls > LIMITS.maxDrawCalls) {
    console.error('Draw call limit exceeded')
    return false
  }
  if (stats.triangles > LIMITS.maxTriangles) {
    console.error('Triangle limit exceeded')
    return false
  }
  return true
}

8. Common Mistakes & Anti-Patterns

8.1 Critical Security Anti-Patterns

Never: Skip Context Loss Handling

*.ts
TypeScript
// ❌ DANGEROUS - App crashes on context loss
const gl = canvas.getContext('webgl2')
// No context loss handler!

// ✅ SECURE - Handle gracefully
canvas.addEventListener('webglcontextlost', handleLoss)
canvas.addEventListener('webglcontextrestored', handleRestore)

Never: Unlimited Resource Allocation

*.ts
TypeScript
// ❌ DANGEROUS - GPU memory exhaustion
for (let i = 0; i < userCount; i++) {
  textures.push(gl.createTexture())
}

// ✅ SECURE - Enforce limits
if (textureCount < MAX_TEXTURES) {
  textures.push(gl.createTexture())
}

8.2 Performance Anti-Patterns

Avoid: Excessive State Changes

*.ts
TypeScript
// ❌ BAD - Unbatched draw calls
objects.forEach(obj => {
  gl.useProgram(obj.program)
  gl.bindTexture(gl.TEXTURE_2D, obj.texture)
  gl.drawElements(...)
})

// ✅ GOOD - Batch by material
batches.forEach(batch => {
  gl.useProgram(batch.program)
  gl.bindTexture(gl.TEXTURE_2D, batch.texture)
  batch.objects.forEach(obj => gl.drawElements(...))
})

9. Pre-Implementation Checklist

Phase 1: Before Writing Code

  • Write failing tests for shaders, context, and resources
  • Define performance budgets (draw calls <100, memory <256MB)
  • Identify required WebGL extensions

Phase 2: During Implementation

  • Context loss handling with recovery
  • Resource limits and memory tracking
  • Shader validation before compilation
  • Use VAOs, batch draws, reuse buffers
  • Instanced rendering for particles

Phase 3: Before Committing

  • Tests pass: npm test -- --run tests/webgl/
  • Type check: npm run typecheck
  • Build: npm run build
  • Performance verified (draws, memory)
  • Fallback for no WebGL tested

10. Summary

WebGL provides GPU-accelerated graphics for JARVIS HUD. Key principles: handle context loss, enforce resource limits, validate shaders, track memory, batch draw calls, minimize state changes.

Remember: WebGL bypasses browser sandboxing - always protect against resource exhaustion. References: references/advanced-patterns.md, references/security-examples.md

Ratings

0.0
No ratings yet
5
4
3
2
1

Send this prompt to your agent to leave a review

Read https://lobehub.com/skills/skill.md and follow the instructions to set up the LobeHub Skills Marketplace then submit a review using: `npx -y @lobehub/market-cli skills comment martinholovsky-claude-skills-generator-webgl -c "<your review>" --rating 5 (or 1-4)`. Include what worked well, any issues, and tips for other agents.

Agent Review

No comments yet

Related Skills

View More
avatar

frontend-design

4.9
affaan-m
Github

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

1
Web & Frontend Development
1.2k
142.6k
94
avatar

frontend-ui-ux

4.8
code-yeongyu
Github

Designer-turned-developer who crafts stunning UI/UX even without design mockups

1
Web & Frontend Development
1.3k
39.1k
41
avatar

design-system

4.6
affaan-m
Github

Building a production-ready design system with accessibility, responsiveness, theming, component sets, and design tokens. Integration with Figma, Storybook, and component libraries.

1
Web & Frontend Development
270
185.6k
19
avatar

tailwind-patterns

4.4
srbhr
Github

Production-ready Tailwind CSS patterns for responsive layouts, cards, navigation, forms, buttons, and typography. Includes spacing scale, breakpoints, mobile-first patterns, dark mode, and Swiss International Style overrides for Resume Matcher.

1
Web & Frontend Development
295
26.2k
22
avatar

ui-ux-pro-max

4.1
nextlevelbuilder
Github

UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 9 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind, shadcn/ui). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient. Integrations: shadcn/ui MCP for component search and examples.

3
Web & Frontend Development
573
30.8k
10
avatar

desktop

5.0
lobehub
Github

Electron desktop development guide. Use when implementing desktop features, IPC handlers, controllers, preload scripts, window management, menu configuration, or Electron-specific functionality. Triggers on desktop app development, Electron IPC, or desktop local tools implementation.

5
Web & Frontend Development
238
73.1k
3

Installation Method

View Details

Send this prompt to your agent to install the skill

Agent prompt
Agent prompt
Read https://lobehub.com/skills/martinholovsky-claude-skills-generator-webgl/skill.md to understand how to install and use this skill. Install it as documented, then open the installed SKILL.md and follow its instructions. Ask for confirmation before any credential use, external service setup, or irreversible action.

File Tree

Details
SKILL.md
SKILL.md
LobeHub

Your Chief Agent Operator

Start using LobeHub today and join thousands of super individuals