Skip to main content

GLSL Shader Support

The Lab13 CLI includes built-in support for GLSL (OpenGL Shading Language) shaders with automatic minification and TypeScript integration. This makes it easy to create 3D graphics and visual effects in your JS13K games.

Quick Start​

  1. Create shader files in your project
  2. Import them in your TypeScript/JavaScript code
  3. Use with WebGL - the CLI handles the rest!

Supported File Extensions​

The CLI automatically processes these GLSL file types:

  • .glsl - Generic GLSL shader files
  • .vert - Vertex shaders
  • .frag - Fragment shaders
  • .vs - Vertex shaders (alternative)
  • .fs - Fragment shaders (alternative)

Basic Usage​

Create Shader Files​

Create a shaders folder in your src directory:

src/
├── main.ts
└── shaders/
├── vertex.glsl
└── fragment.glsl

vertex.glsl:

attribute vec3 position;
attribute vec2 uv;

uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;

varying vec2 vUv;

void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

fragment.glsl:

precision mediump float;

uniform float time;
varying vec2 vUv;

void main() {
vec2 uv = vUv;
float wave = sin(uv.x * 10.0 + time) * 0.5 + 0.5;
gl_FragColor = vec4(wave, 0.5, 1.0, 1.0);
}

TypeScript Support​

To get proper TypeScript support for GLSL imports, add the vite-plugin-glsl type declarations to your tsconfig.json:

tsconfig.json:

{
"compilerOptions": {
"types": ["vite-plugin-glsl/ext"]
}
}

Or add it as a reference directive to your global types:

/// <reference types="vite-plugin-glsl/ext" />

This gives you:

  • ✅ Type safety - TypeScript knows GLSL files export strings
  • ✅ IntelliSense - Auto-completion in your IDE
  • ✅ Error checking - Catch import errors at compile time

Complete Example​

Here's a complete example using GLSL shaders with the W library:

src/main.ts:

import { useResizer } from 'lab13-sdk'
import vertexShader from './shaders/vertex.glsl'
import fragmentShader from './shaders/fragment.glsl'

// Initialize W
W.reset(c)
W.light({ y: -1 })
W.ambient(0.2)

// Setup canvas resizing
useResizer()

// Create a custom shader material
const material = W.material({
vertexShader,
fragmentShader,
uniforms: {
time: { value: 0 },
},
})

// Create a cube with the custom shader
W.cube({
n: 'animated-cube',
w: 2,
h: 2,
d: 2,
m: material,
})

// Animate the shader
let time = 0
useSpeedThrottledRaf(60, () => {
time += 0.01
material.uniforms.time.value = time
})