canvas-sketch

:closed_book: canvas-sketchDocumentation → WebGL, GLSL, Three.JS and More


WebGL, GLSL, Three.JS and More

Often, you may want to take advantage of WebGL features to design a certain artwork. You can specify { context: 'webgl' } in the settings, or specify an existing WebGL-enabled { context } from a canvas.

When your sketch is WebGL-enabled, the props will also provide a gl option for better code readability.

Below is an example with regl (a thin WebGL wrapper), which simply fills the WebGL backbuffer with pure red.

const canvasSketch = require('canvas-sketch');
const createRegl = require('regl');

const settings = {
  // Use a WebGL context instead of 2D canvas
  context: 'webgl',
  // Enable MSAA in WebGL
  attributes: {
    antialias: true
  }
};

canvasSketch(({ gl }) => {
  // Setup REGL with our canvas context
  const regl = createRegl({ gl });

  // Create your GL draw commands
  // ...

  // Return the renderer function
  return () => {
    // Update regl sizes
    regl.poll();

    // Clear back buffer with red
    regl.clear({
      color: [ 1, 0, 0, 1 ]
    });

    // Draw your meshes
    // ...
  };
}, settings);

GLSL Files

The canvas-sketch-cli tool comes built-in with glslify support, which will inline GLSL files as strings in your JavaScript bundle.

Save your GLSL file with .frag, .vert, or .glsl extension, and you can require it like so:

const shader = require('./cool-shader.frag');

// the processed GLSL source string
console.log(shader);

Alternatively, you can use glslify syntax directly. The above is equivalent to:

const path = require('path');
const glslify = require('glslify');

// this will get inlined into a string at bundle time
const frag = glslify(path.resolve(__dirname, 'cool-shader.frag'));

You can also use template strings if you wish to keep your GLSL code contained within your sketch files.

Using glslify for modular GLSL

Because the GLSL files are processed, you can import shaders from npm, like glsl-noise. Use the following command to add it to your package.json file:

npm install glsl-noise

Now, you can import it into your GLSL. For example:

const glslify = require('glslify');

const vertex = glslify(`
  #pragma glslify: noise = require('glsl-noise/simplex/3d');

  void main () {
    ...
  }
`)

:bulb:

If you are using VSCode, you can achieve GLSL syntax highlighting with Comment Tagged Templates and GLSL Syntax extensions.

This technique was used in the following animated WebGL sketch:

blob

See here for the full source code of this sketch.

Live Shader Coding

You can use Hot Reloading to make a live coding environment for GLSL shaders. For convenience, you can use the canvas-sketch-util/shader module.

The CLI includes a shader template when creating new sketches:

canvas-sketch test.js --new --template=shader --hot --open

This will scaffold & start a basic shader rendered by regl:

const canvasSketch = require('canvas-sketch');
const createShader = require('canvas-sketch-util/shader');
const glsl = require('glslify');

// Setup our sketch
const settings = {
  context: 'webgl',
  animate: true
};

// Your glsl code
const frag = glsl(`
  precision highp float;

  uniform float time;
  varying vec2 vUv;

  void main () {
    vec3 color = 0.5 + 0.5 * cos(time + vUv.xyx + vec3(0.0, 2.0, 4.0));
    gl_FragColor = vec4(color, 1.0);
  }
`);

// Your sketch, which simply returns the shader
const sketch = ({ gl }) => {
  // Create the shader and return it
  return createShader({
    // Pass along WebGL context
    gl,
    // Specify fragment and/or vertex shader strings
    frag,
    // Specify additional uniforms to pass down to the shaders
    uniforms: {
      // Expose props from canvas-sketch
      time: ({ time }) => time
    }
  });
};

canvasSketch(sketch, settings);

You can now edit & save the script to see the shader hot-reload.

Using Three.js, P5.js, and Other Libraries

As you can see from the previous regl example, it is fairly straight-forward to use other libraries alongside canvas-sketch. In fact, canvas-sketch was intentionally designed to make zero assumptions about the rendering library being used.

Here are some examples:

##

Now that you’ve covered most of the guide, check out Other Topics for a few more tricks, like rendering to an AxiDraw Mechcanical Pen Plotter.

← Back to Documentation