byegl logo

byegl

This project aims to reimplement the WebGL API on top of WebGPU, which will allow established WebGL-based projects to gradually migrate to the WebGPU over time.

Explore examples Contribute

Getting Started

All you need to migrate your WebGL code to WebGPU is the following:

import * as byegl from 'https://esm.sh/[email protected]';
// npm: import * as byegl from 'byegl';

// Enable and await...
await byegl.enable();

// Intercepted by byegl 🥯🐶
const gl = canvas.getContext('webgl');

Enabling byegl will intercept calls to .getContext('webgl' | 'webgl2' | 'experimental-webgl') on all canvases and return a virtualized WebGL context.

Importing WebGPU resources

Once your WebGL app is running on byegl, you can can hook into the underlying WebGPU API directly.

const wgpuVertexBuffer = device.createBuffer({
//    ^? GPUBuffer
  size: 1024,
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
});

// Create a two-way binding between both resources, allowing
// you to populate the buffer using a WGSL compute shader, and
// use it in a WebGL pipeline 🪄
const vertexBuffer = byegl.importWebGPUBuffer(gl, wgpuVertexBuffer);
//    ^? WebGLBuffer

The Hooks: Water Surface example demonstrates this functionality in practice.

Retrieving WebGPU resources

If you need to access the underlying WebGPU resources, you can use the byegl.getWebGPUBuffer() function.

const wgpuVertexBuffer = byegl.getWebGPUBuffer(gl, vertexBuffer);
//    ^? GPUBuffer

Note that byegl may need to reallocate the buffer (in case the size of the data changes), so make sure to call .getWebGPUBuffer() each time you need to access the buffer, don’t store it off into a variable.

Retriving generated WGSL code

If you need to access the generated WGSL code, you can use the byegl.getWGSLSource() function, passing the WebGL program. Note that since in WebGPU, both the vertex and fragment shaders are colocated.

const program = gl.createProgram();

// ...

const wgsl = byegl.getWGSLSource(gl, program);
//    ^? string | undefined

Checking if byegl is enabled

You can check if byegl has intercepted a specific context by calling byegl.isIntercepted(gl).

const intercepted = byegl.isIntercepted(gl);
//    ^? boolean

Disabling byegl

If you want more granular control over when byegl intercepts contexts, byegl.enable() returns a function to disable it.

const disable = await byegl.enable();

//
// Run your program
//

disable(); // Bye byegl 👋

Things to consider when mixing GLSL and WGSL

WebGL’s clip-space coordinates are in the range [-1, 1] for X, Y and Z, whereas WebGPU’s clip-space Z coordinates are in the range [0, 1]. This is mitigated in the generated WGSL, but when writing your own WGSL shaders, you need to be aware of this difference.

News & Updates

Stay updated with the latest news about byegl on X or Bluesky. Follow posts tagged with #byegl.