A minimalist WebGL library for the browser
gl-lite is a lightweight, type-safe WebGL wrapper that makes it easy to work with WebGL/WebGL2 in the browser. It provides a clean, declarative API for creating shader programs, managing textures, buffers, and framebuffers without the boilerplate of raw WebGL.
gl-lite is a thin abstraction layer over WebGL/WebGL2 that simplifies common graphics programming tasks. Unlike full-featured 3D engines (Three.js, Babylon.js) or high-level frameworks, gl-lite focuses on providing a minimal, type-safe interface for direct WebGL operations. It's perfect for:
- Shader-based graphics - Creating custom shader effects, visualizations, and GPU-accelerated computations
- 2D/3D rendering - Building custom rendering pipelines without the overhead of a full 3D engine
- WebGL utilities - Managing WebGL resources (textures, buffers, programs) with automatic cleanup
- Learning WebGL - Understanding WebGL concepts with a cleaner API than raw WebGL
- Performance-critical graphics - When you need direct GPU control without framework overhead
- Render-to-texture - Post-processing effects, off-screen rendering, and multi-pass rendering
✅ Use gl-lite when:
- You need direct WebGL control with less boilerplate
- You're building custom shader-based visualizations or effects
- You want type safety and modern TypeScript APIs
- You need a lightweight library (zero dependencies, small bundle)
- You're creating 2D graphics, data visualizations, or procedural art
- You want to learn WebGL with a cleaner API
❌ Consider alternatives when:
- You need a full 3D engine with scene graphs, cameras, and lighting (use Three.js, Babylon.js)
- You're building complex 3D applications with models, animations, and physics
- You need built-in geometry primitives and materials
- You want a high-level framework that handles everything for you
- 🎯 Minimalist API - Simple, intuitive interface for WebGL operations
- 📦 Zero dependencies - Pure TypeScript with no external deps
- 🎨 Type-safe - Full TypeScript support with comprehensive types
- 🚀 Modern - Built for ES modules and modern browsers
- 🔧 Flexible - Low-level control when you need it
- 🪶 Lightweight - Small bundle size
- 🧹 Resource management - Automatic cleanup and disposal of WebGL resources
- 💾 Program caching - Efficient program reuse via WeakMap-based caching
- 🔄 Dynamic uniforms/attributes - Support for function-based uniforms and attributes
npm install gl-liteimport { GLRenderer } from "gl-lite";
// Create a renderer
const renderer = new GLRenderer({
canvas: document.querySelector("canvas"),
});
// Create a shader program
const program = renderer.program({
vert: `
attribute vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
`,
frag: `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.5, 1.0);
}
`,
attributes: {
position: {
buffer: renderer.buffer({
data: new Float32Array([-1, -1, 1, -1, 0, 1]),
}),
size: 2,
},
},
count: 3,
});
// Render loop
function render() {
renderer.clear([0, 0, 0, 1]);
program.draw();
requestAnimationFrame(render);
}
render();The main entry point for creating a WebGL context and managing resources.
const renderer = new GLRenderer({
canvas: HTMLCanvasElement, // Optional: custom canvas element
context: WebGLContext, // Optional: existing context
attributes: WebGLContextAttributes, // Optional: context attributes
});
renderer.resize(width, height); // Resize canvas and viewport
renderer.clear([r, g, b, a]); // Clear with color
renderer.program(definition); // Create/cache a program
renderer.texture(params); // Create a texture
renderer.framebuffer(texture); // Create a framebuffer
renderer.buffer(params); // Create a buffer
renderer.dispose(); // Clean up resourcesManages shaders, uniforms, and attributes.
const program = renderer.program({
vert: string, // Vertex shader source
frag: string, // Fragment shader source
attributes: GLAttributes, // Vertex attributes
uniforms: GLUniforms, // Shader uniforms
primitive: 'triangles', // Draw mode
count: number, // Vertex count
offset: number, // Vertex offset
blend: GLBlendConfig, // Blend configuration
elements: GLBuffer, // Index buffer (optional)
});
program.draw(props); // Draw with optional props
program.use(() => { ... }); // Use program in callback
program.dispose(); // Clean upHandles texture creation and management.
const texture = renderer.texture({
width: number,
height: number,
data: ImageData | HTMLImageElement | ArrayBufferView | null,
format: "rgba" | "rgb" | "alpha" | "luminance" | "luminanceAlpha",
type: "uint8" | "float",
wrapS: "clamp" | "repeat" | "mirror",
wrapT: "clamp" | "repeat" | "mirror",
minFilter: "nearest" | "linear",
magFilter: "nearest" | "linear",
flipY: boolean,
});
texture.bind(unit); // Bind to texture unit
texture.update(params); // Update texture data
texture.resize(width, height); // Resize texture
texture.dispose(); // Clean upManages vertex and index buffers.
const buffer = renderer.buffer({
target: 'array' | 'element', // Buffer type
usage: 'static' | 'dynamic' | 'stream',
data: Float32Array | number[], // Buffer data
});
buffer.update(data); // Update buffer data
buffer.use(() => { ... }); // Bind buffer in callback
buffer.dispose(); // Clean upRender to texture functionality.
const fbo = renderer.framebuffer(texture);
fbo.use(() => {
// Render to texture
renderer.clear([0, 0, 0, 1]);
program.draw();
});
fbo.dispose(); // Clean up (also disposes texture)const program = renderer.program({
frag: `
precision mediump float;
uniform float time;
uniform vec2 resolution;
varying vec2 uv;
void main() {
vec2 p = uv * 2.0 - 1.0;
float d = length(p);
float c = sin(d * 10.0 - time) * 0.5 + 0.5;
gl_FragColor = vec4(vec3(c), 1.0);
}
`,
uniforms: {
time: (props) => props.time,
resolution: (props) => [props.width, props.height],
},
});
// Render loop
let time = 0;
function render() {
time += 0.016;
renderer.clear();
program.draw({
time,
width: canvas.width,
height: canvas.height,
});
requestAnimationFrame(render);
}const image = new Image();
image.onload = () => {
const texture = renderer.texture({
data: image,
flipY: true,
});
const program = renderer.program({
frag: `
precision mediump float;
uniform sampler2D tex;
varying vec2 uv;
void main() {
gl_FragColor = texture2D(tex, uv);
}
`,
uniforms: {
tex: texture,
},
});
program.draw();
};
image.src = "image.png";const positions = new Float32Array([
-0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5,
]);
const indices = new Uint16Array([0, 1, 2, 0, 2, 3]);
const program = renderer.program({
attributes: {
position: {
buffer: renderer.buffer({ data: positions }),
size: 2,
},
},
elements: renderer.buffer({
target: "element",
data: indices,
}),
count: indices.length,
});
program.draw();gl-lite is fully typed with TypeScript. All classes and functions have comprehensive type definitions:
import type {
GLContext,
GLMap,
GLTextureParams,
GLBufferParams,
GLProgramDefinition,
GLAttribute,
GLUniforms,
GLBlendConfig,
} from "gl-lite";Use human-readable names instead of WebGL constants:
import { glMap } from "gl-lite";
const map = glMap(gl);
// Instead of gl.CLAMP_TO_EDGE
const wrap = map.wrap.clamp;
// Instead of gl.LINEAR
const filter = map.filter.linear;
// Instead of gl.TRIANGLES
const primitive = map.primitive.triangles;| Feature | gl-lite | Three.js | Raw WebGL |
|---|---|---|---|
| Bundle size | ~10KB | ~500KB+ | 0KB |
| Dependencies | Zero | Many | None |
| Learning curve | Low | Medium | High |
| Type safety | Full TypeScript | Partial | None |
| API style | Declarative | Object-oriented | Imperative |
| Use case | Custom shaders, lightweight graphics | Full 3D engine | Maximum control |
| Scene graph | ❌ | ✅ | ❌ |
| Built-in geometry | ❌ | ✅ | ❌ |
| Shader management | ✅ | ✅ | Manual |
| Resource cleanup | ✅ | ✅ | Manual |
gl-lite sits between raw WebGL and full-featured engines, providing just enough abstraction to reduce boilerplate while maintaining direct control over the GPU.
gl-lite works in all modern browsers that support WebGL or WebGL2:
- Chrome/Edge 56+
- Firefox 51+
- Safari 15+
# Install dependencies
bun install
# Build the library
bun run build
# Watch mode for development
bun run dev
# Run the example (builds and serves on http://localhost:3000)
bun run example
# Preview the landing page
bun run preview
# Format code
bun run formatgl-lite/
├── src/ # Library source code
├── dist/ # Built library (generated)
├── web/ # Landing page (deployed to gl-lite.dev)
├── example.html # Local example/demo
└── README.md
- 🌐 Website: gl-lite.dev
- 📦 GitHub: github.com/roprgm/gl-lite
MIT © roprgm
Contributions are welcome! Please feel free to submit a Pull Request.