What is regl?
regl is a functional abstraction for WebGL that simplifies the process of creating and managing WebGL contexts and rendering pipelines. It provides a declarative API for defining shaders, buffers, and other WebGL resources, making it easier to build complex graphics applications.
What are regl's main functionalities?
Creating a WebGL Context
This code initializes a new regl instance, which sets up a WebGL context and prepares it for rendering.
const regl = require('regl')();
Drawing a Simple Triangle
This code defines a simple triangle using regl. It specifies the vertex and fragment shaders, the vertex positions, and the draw call. The triangle is drawn in each frame.
const drawTriangle = regl({
frag: `
precision mediump float;
void main () {
gl_FragColor = vec4(1, 0, 0, 1);
}
`,
vert: `
precision mediump float;
attribute vec2 position;
void main () {
gl_Position = vec4(position, 0, 1);
}
`,
attributes: {
position: [
[-1, 0],
[0, -1],
[1, 1]
]
},
count: 3
});
regl.frame(() => {
regl.clear({
color: [0, 0, 0, 1],
depth: 1
});
drawTriangle();
});
Managing Buffers
This code demonstrates how to create and use a buffer in regl. The buffer stores vertex positions, which are then used in the draw call.
const positionBuffer = regl.buffer([
[-1, 0],
[0, -1],
[1, 1]
]);
const drawWithBuffer = regl({
frag: `
precision mediump float;
void main () {
gl_FragColor = vec4(0, 1, 0, 1);
}
`,
vert: `
precision mediump float;
attribute vec2 position;
void main () {
gl_Position = vec4(position, 0, 1);
}
`,
attributes: {
position: positionBuffer
},
count: 3
});
regl.frame(() => {
regl.clear({
color: [0, 0, 0, 1],
depth: 1
});
drawWithBuffer();
});
Using Uniforms
This code shows how to use uniforms in regl. The uniform 'color' is passed to the fragment shader, allowing dynamic control over the color of the rendered triangle.
const drawWithUniforms = regl({
frag: `
precision mediump float;
uniform vec4 color;
void main () {
gl_FragColor = color;
}
`,
vert: `
precision mediump float;
attribute vec2 position;
void main () {
gl_Position = vec4(position, 0, 1);
}
`,
attributes: {
position: [
[-1, 0],
[0, -1],
[1, 1]
]
},
uniforms: {
color: [0, 0, 1, 1]
},
count: 3
});
regl.frame(() => {
regl.clear({
color: [0, 0, 0, 1],
depth: 1
});
drawWithUniforms();
});
Other packages similar to regl
three
Three.js is a popular JavaScript library for creating 3D graphics in the browser. It provides a higher-level abstraction compared to regl, making it easier to create complex 3D scenes with less code. However, it may not offer the same level of control and performance optimization as regl.
pixi
PixiJS is a 2D rendering engine that uses WebGL for high-performance graphics. It is designed for creating interactive graphics and games, offering a simpler API compared to regl. While it is more focused on 2D graphics, it can also handle some 3D rendering tasks.
babylonjs
Babylon.js is a powerful, open-source 3D engine that provides a comprehensive set of features for creating 3D applications. It offers a higher-level API than regl, making it easier to get started with 3D graphics, but it may not provide the same fine-grained control over WebGL resources.
regl
This repo is an attempt at building new functional abstractions for working with WebGL. It is still experimental, so expect things to change a lot in the near future! If you want to know more about why I am writing this thing and why it looks the way it does, take a look at the rationale.
Why use regl
regl
offers the following advantages over raw WebGL code:
- Less state Draw commands in regl are self contained, so you don't have to worry about some other weird subroutine breaking your rendering code
- No
bind()
In regl, shaders, buffers, textures and fbos are specified declaratively, so there is no need to ever bind()
them or unbind them. - Fewer silent failures If you pass incorrect parameters to some WebGL method, the default behavior is to set an error code and continue on. Because
regl
commands have more structure, we can do more validation up front without the run time performance cost. - Sane defaults Many WebGL APIs have redundant or outright broken parameters (for example
border
in gl.texImage2D
or transpose
in gl.uniformMatrix4fv
). regl
wraps these APIs in such a way that you will never have to see this mess. - Low overhead regl uses caching and code generation to minimize overhead from
- Still just WebGL regl exposes the full power of the WebGL API, no features are removed or hidden.
Simple example
In regl
, there are two fundamental abstractions, resources and commands:
- A resource is a handle to a GPU resident object, like a texture, FBO or buffer.
- A command is a complete representation of the WebGL state required to perform some draw call.
To define a command you specify a mixture of static and dynamic data for the object. Once this is done, regl
takes this description and then compiles it into optimized JavaScript code. For example, here is a simple regl
program to draw a colored triangle:
const regl = require('regl')()
const drawTriangle = regl({
frag: `
precision mediump float;
uniform vec4 color;
void main() {
gl_FragColor = color;
}`,
vert: `
precision mediump float;
attribute vec2 position;
void main() {
gl_Position = vec4(position, 0, 1);
}`,
attributes: {
position: regl.buffer([
[-2, -2],
[4, -2],
[4, 4]
]))
},
uniforms: {
color: regl.prop('color')
},
count: 3
})
regl.frame(() => {
regl.clear({
color: [0, 0, 0, 0],
depth: 1
})
drawTriangle({
color: [
Math.cos(Date.now() * 0.001),
Math.sin(Date.now() * 0.0008),
Math.cos(Date.now() * 0.003),
1
]
})
})
More examples
Check out the demo gallery
Setup
regl has no dependencies, so setting it up is pretty easy
Live editing
To try out regl right away, you can use RequireBin or codepen. The following links should help get you started:
npm
The easiest way to use regl
in a project is via npm. Once you have node set up, you can install and use regl
in your project using the following command:
npm i -S regl
For more info on how to use npm, check out the official docs.
Standalone script tag
You can also use regl
as a standalone script if you are really stubborn. The most recent versions can be found under the releases tab. To do this, add the following script tag to your HTML:
<script src="[some cdn tbd]/regl.min.js"></script>
Comparisons
TODO implement spinning textured cube in each of the following frameworks
- vs WebGL
- vs gl-* modules from stack.gl
- vs TWGL
- vs THREE.js
Benchmarks
You can run benchmarks locally using npm run bench
or check them out here:
Contributing
For info on how to build and test headless, see the contributing guide here
Credits
All code (c) 2016 MIT License
Development supported by the Freeman Lab and the Howard Hughes Medical Institute (@freeman-lab on GitHub)
Test video (doggie-chromakey.ogv) by L0ckergn0me, used under creative commons license
Cube maps (posx.jpeg, negx.jpeg, posy.jpeg, negy.jpeg, posz.jpeg, negz.jpeg) by Humus, used under creative commons 3 license
Environment map of Oregon (ogd-oregon-360.jpg) due to Max Ogden (@ogd on GitHub)
DDS test images (alpine_cliff_a, alpine_cliff_a_norm, alpine_cliff_a_spec) taken from the CC0 license 0-AD texture pack by Wildfire games