A node.js-style module system for GLSL!
A node.js-style module system for GLSL!
This module contains glslify's command-line interface (CLI) and browserify transform. It forms one of the core components of the stack.gl ecosystem, allowing you to install GLSL modules from npm and use them in your shaders. This makes it trivial to piece together different effects and techniques from the community, including but certainly not limited to fog, noise, film grain, raymarching helpers, easing functions and lighting models.
A full list can be found on the stack.gl packages list under the "Shader Components" category.
Because glslify just outputs a single shader file as a string, it's easy to use it with any WebGL framework of your choosing, provided they accept custom shaders. Integration is planned for three.js and pex, with more on the way! Open an issue here if you'd like to discuss integrating glslify with your platform of choice.
To install the command-line interface, install glslify globally like so:
npm install -g glslify
To install glslify for use as a browserify transform, you should install it locally instead:
npm install glslify
The CLI can take a file as its first argument, and output to a file
glslify index.glsl -o output.glsl
It can also read input from stdin and output to stdout:
cat index.glsl | glslify > output.glsl
If using browserify from the command-line, simply pass glslify
in as a transform using the
browserify -t glslify index.js -o bundle.js
Alternatively, you may include glslify as a
When writing your app, you should be able to require and call glslify like so:
// index.jsvar glslify =var src =console
Your glslify calls will be replaced with bundled GLSL strings at build time automatically for you!
// index.jsvar src = "#define GLSLIFY 1\n\nprecision mediump float; ..."console
By passing the
inline option as true, you can write your
shader inline instead of requiring it to be in a separate
var glslify =var src =
The main difference is that GLSL modules contain an
instead of an
index.js. Generally, these modules start with
in their name.
To install glsl-noise in your current directory:
npm install glsl-noise
This will download glsl-noise and any of its dependencies, placing
them in a
node_modules directory for glslify to use.
You can import a module using the following
# noise = require(glsl-noise/simplex/2d)void
Shader dependencies are resolved using the same algorithm
as node, so the above will load
from the shader's directory.
The above example would result in the following output:
//// Description : Array and textureless GLSL 2D simplex noise function.// Author : Ian McEwan, Ashima Arts.// Maintainer : ijm// Lastmod : 20110822 (ijm)// License : Copyright (C) 2011 Ashima Arts. All rights reserved.// Distributed under the MIT License. See LICENSE file.////vec3vec2vec3floatvoid
You can export a token from a module using the
pragma, like so:
This means that when you import this module file elsewhere, you'll
myFunction in return:
# topDot = require(./my-function.glsl)// 1
If you check the output shader source, you'll notice that variables have been renamed to avoid conflicts between multiple shader files.
You're not limited to exporting functions either: you should be able to export any GLSL token, such as a struct for reuse between your modules:
struct Light;# export(Light)
Normally, glslify renames tokens to avoid conflicts across contexts. Sometimes, however, you want to reference the same thing from different contexts. The
require function lets you explicitly fix reference names in order to guarantee that two different modules are talking about the same reference.
some-module access to locally declared
bar whenever it looks for
int bar;# require('some-module',foo=bar,...)
It's important to make sure that
bar has already been declared when you invoke
#pragma glslify: require(...).
Now time for some imagination. Let's pretend that we have some
float arrays that we'd like to be summed up.
Here's a module that performs a reduction using a function
But notice that this module doesn't actually declare
const int N; or define a function
map anywhere. We have to make sure they are already defined when we require the module, and pass their names along with the
const int M = 500;float# sum500 = require('./accumulator.glsl',N=M,map=add)
The accumulator has been imported and glslified into a
sum function. We can also multiply all of the floats in some
float arrays the same way:
const int M = 500;const int L = 17;floatfloat# sum500 = require('./accumulator.glsl',N=M,map=add)# product17 = require('./accumulator.glsl',N=L,map=mul)
Glsl-hash-blur is an example of a module that uses this feature.
Source transforms are a feature inspired by browserify, allowing you to
modify your GLSL source at build time on a per-package basis. This is
useful both for transpilation (e.g. converting from or to
HLSL) or for
making incremental improvements to GLSL syntax. (e.g. you can use
glslify-hex to include CSS-style
hex strings for colors in place of
There are three kinds of source transform:
-tit'll only apply itself to files outside of
node_modules, but you can include it in
package.jsontoo: these will be applied only to that package without interfering with any of the package's parents or children.
There are a number of ways to use a transform. Start by installing it in your project:
npm install --save glslify-hex
The preferred way to enable a transform is through your project's
glslify.transform property, like so:
You may also include arguments to your transform as you would with browserify:
Note that this method is only available for local transforms.
You may also specify transforms via the CLI:
glslify -t 'local-transform' -g 'global-transform' -p 'post-transform'
Or when using the browserify transform by including them as options like so:
var glslify =
There are two important changes to note:
var glslify =var shader =gl
Should now be created like so:
var glShader =var glslify =var shader =
You can use glslify from Node using
glslify.bundle. The operation is
performed asynchronously, but otherwise it shares the same API as
glslify's browserify transform.
file and calls
done(err, source, files) with the finished shader
files is an array of all the files required from the
dependency tree, including the entry file.
inline: if set to true, you can pass the GLSL source directly in place of the
transform: an array of transforms to apply to the shader.
basedir: the directory from which to resolve modules from in your first shader. Defaults to the first file's directory, or
process.cwd()if inline mode is enabled.
See stackgl/contributing for details.
MIT. See LICENSE.md for details.