💎 glsl-canvas
glsl-canvas-js is a typescript porting of GlslCanvas, a javascript library that helps you easily load GLSL Fragment and Vertex Shaders into an HTMLCanvasElement. Originally made by Patricio Gonzalez Vivo author of Book of Shaders and GlslEditor.
Now supporting WebGL2. just add #version 300 es
at the very start of the file.
Now supporting nested includes with relative paths.
How to use
With link
Load the latest version of glsl-canvas.js
on your page by adding this line to your HTML:
<script type="text/javascript" src="https://unpkg.com/glsl-canvas-js/dist/umd/glsl-canvas.min.js"></script>
With npm
If you are using npm package manager type this command on your terminal:
npm install glsl-canvas-js --save
Run with html
Add a canvas element on your page with class name glsl-canvas
and assign a shader through a url using the data-fragment-url
attribute.
Or write your shader directly in code using the data-fragment
attribute.
<canvas class="glsl-canvas" data-fragment-url="fragment.glsl" width="500" height="500"></canvas>
GlslCanvas
will automatically load a WebGL context in that <canvas>
element, compile the shader and animate it for you.
Run with javascript
Create a <canvas>
element and attach a new instance of glsl.Canvas
.
const canvas = document.createElement('canvas');
const options = {
vertexString: `...`,
fragmentString: `...`,
alpha: false,
antialias: true,
mode: 'flat',
extensions: ['EXT_shader_texture_lod']
};
const glsl = new glsl.Canvas(canvas, options);
All the .glsl-canvas
instances will be stored in the glsl.Canvas.items
array.
Import es6 module
import { Canvas } from 'glsl-canvas-js';
const canvas = document.createElement('canvas');
const options = {
vertexString: `...`,
fragmentString: `...`,
alpha: false,
antialias: true,
mode: 'flat',
extensions: ['EXT_shader_texture_lod']
};
const glsl = new Canvas(canvas, options);
Init options
GlslCanvas options inherit from WebGLContextAttributes. Here the complete list.
const glsl = new Canvas(canvas, {
vertexString: '...',
fragmentString: '...',
backgroundColor: 'rgba(0.0, 0.0, 0.0, 0.0)',
alpha: true,
antialias: true,
depth: true,
desynchronized: false,
failIfMajorPerformanceCaveat: false,
powerPreference: 'default',
premultipliedAlpha: false,
preserveDrawingBuffer: false,
stencil: false,
doubleSided: false,
extensions: ['EXT_shader_texture_lod'],
workpath: 'rootfolder',
mode: 'mesh',
mesh: 'myfolder/myfile.obj',
onError: (error) => {}
});
Default Shader Attributes
These attributes are automatically loaded for you.
name | |
---|---|
a_position |
a vec4 with vertex position. |
a_normal |
a vec4 with normal values. |
a_texture |
a vec2 with texture coords mapping. |
a_color |
a vec4 with face color info. |
Default Uniforms
These uniforms are automatically loaded for you.
name | |
---|---|
u_time |
a float representing elapsed time in seconds. |
u_resolution |
a vec2 representing the dimensions of the viewport. |
u_mouse |
a vec2 representing the position of the mouse, defined in Javascript with .setMouse({x:[value],y:[value]) . |
u_texture_N |
a sampler2D containing textures loaded with the data-textures attribute. |
Attributes
name | |
---|---|
data-fragment |
load a fragment shader by providing the content of the shader as a string |
data-vertex |
load a vertex shader by providing the content of the shader as a string |
data-fragment-url |
load a fragment shader by providing a valid url |
data-vertex-url |
load a vertex shader by providing a valid url |
data-mode |
setup one of those modes flat , box , sphere , torus , mesh |
data-textures |
load a list of texture urls separated by commas (ex: data-textures="color.jpg,normal.png,bump.jpg" ). Textures will be assigned in order to uniform sampler2D variables with names following this style: u_texture_0 , u_texture_1 , u_texture_2 , etc. |
controls |
enable play on over functionality |
data-autoplay |
enable autoplay with controls feature |
Events
name | argument |
---|---|
load |
GlslCanvas instance |
error |
Error |
textureError |
TextureError |
render |
GlslCanvas instance |
over |
MouseEvent |
out |
MouseEvent |
move |
{ x:, y: } |
click |
MouseEvent |
Methods
name | parameters |
---|---|
load |
fragment: string, vertex: string |
on |
eventName: string, callback: Function |
setTexture |
key: string, target: string or element, options:TextureOptions |
setUniform |
key: string, ...values: number or string |
setUniforms |
uniforms: { [key: string]: number[] or string } |
play |
|
pause |
|
toggle |
|
destroy |
#include
Including dependent files with You can include other GLSL code using a traditional #include "file.glsl"
macro.
// example
#include "common/uniforms.glsl"
#include "common/functions.glsl"
void main(){
Multiple buffers
You can use shader buffers by requiring definition with #ifdef
or defined
directly in .glsl
code.
Just ask for BUFFER_
N definition and a u_buffer
N uniform will be created for you:
uniform sampler2D u_buffer0;
#ifdef BUFFER_0
void main() {
vec4 color = texture2D(u_buffer0, uv, 0.0);
...
gl_FragColor = color;
}
#else
void main() {
vec4 color = texture2D(u_buffer0, uv, 0.0);
...
gl_FragColor = color;
}
#endif
Vertex & Fragment shader
You can define both vertex and fragment shader on same file by requiring vertex definition with #ifdef
or defined
directly in .glsl
code.
Just ask for VERTEX
definition and the vertex shader will be created for you:
#if defined(VERTEX)
// attribute vec4 a_position; // data/dolphin.obj
attribute vec4 a_position;
attribute vec4 a_normal;
attribute vec2 a_texcoord;
attribute vec4 a_color;
void main(void) {
v_position = a_position;
v_position = u_projectionMatrix * u_modelViewMatrix * v_position;
v_normal = u_normalMatrix * a_normal;
v_texcoord = a_texcoord;
v_color = a_color;
gl_Position = v_position;
}
// fragment shader
#else
void main() {
...
}
Tips
You can change the content of the shader as many times you want. Here are some examples:
// load only the fragment shader
let fragment = 'main() { gl_FragColor = vec4(1.0); }';
glsl.load(fragment);
// load a fragment and vertex shader
let vertex = 'attribute vec4 a_position; main(){ gl_Position = a_position; }';
glsl.load(fragment, vertex);
You can also send your custom uniforms to a shader with .setUniform('name', ...values)
. GlslCanvas will parse the value you provide to determine its type. If the value is a string
, GlslCanvas will parse it as the url of a texture.
// assign .5 to 'uniform float u_brightness'
glsl.setUniform('u_brightness', 0.5);
// assign (.2,.3) to 'uniform vec2 u_position'
glsl.setUniform('u_position', 0.2, 0.3);
// assign a red color to 'uniform vec3 u_color'
glsl.setUniform('u_color', 1.0, 0.0, 0.0);
// load a new texture and assign it to 'uniform sampler2D u_texture'
glsl.setUniform('u_texture', 'data/texture.jpg');
Examples
You can find some example to start at this page
.
Or you can see a live demo at this link actarian.github.io/glsl-canvas/
Collaborate
If you'd like to contribute to this code, you need to:
- Install node and npm
- Fork and clone this repository
git clone https://github.com/actarian/glsl-canvas.git
- Switch to glsl-canvas directory
cd glsl-canvas
- Install dependencies
npm install
- Run gulp for development and testing with livereload
gulp
- Build for production
gulp build --target dist
- Push to your local fork and make your pull request
Pull requests are welcome and please submit bugs 🐞
Thank you for taking the time to provide feedback and review. This feedback is appreciated and very helpful 🌈
Contact
- Luca Zampetti [email protected]
- Follow @actarian on Twitter
Release Notes
Changelog here.