Glslify
A node.js-style module system for GLSL! :sparkles:
Install / Use
/learn @glslify/GlslifyREADME
glslify [![stability][0]][1]
[![npm version][2]][3] [![downloads][4]][5] [![travis][6]][7]
A node.js-style module system for GLSL!
This module contains:
- glslify's command-line interface (CLI)
- glslify node/electron interface
- 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.
If you're interested in playing around with glslify, you should check out glslb.in: it's a fragment shader sandbox similar to Shadertoy and GLSL Sandbox with built in support for glslify.
Example
var glsl = require('glslify')
console.log(glsl(`
#pragma glslify: noise = require('glsl-noise/simplex/3d')
precision mediump float;
varying vec3 vpos;
void main () {
gl_FragColor = vec4(noise(vpos*25.0),1);
}
`))
Module API
var glsl = require('glslify')
var src = glsl`shader source...`
Compile a shader inline using glsl as a
tagged template string function.
var src = glsl(file, opts)
var src = glsl(shaderSource, opts)
Compile a shader using an inline shader string or a file name.
These are convencience methods provided that call glsl.compile() or
glsl.file() accordingly. These methods are also provided for backwards
compatibility with the previous < 6 interface.
Optionally provide:
opts.basedir- directory to resolve relative pathsopts.transform- an array of transform functions, transform module name
var src = glsl.compile(src, opts)
Compile a shader string from a string src.
opts.basedir- directory to resolve relative paths insrcopts.transform- an array of transform functions, transform module name strings, or[trname,tropts]pairs
var src = glsl.file(filename, opts)
Compile a shader from a filename.
opts.basedir- directory to resolve relative paths insrcopts.transform- an array of transform functions, transform module name strings, or[trname,tropts]pairs
Installation
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
Getting Started
CLI
The CLI can take a file as its first argument, and output to a file
using the -o flag:
glslify index.glsl -o output.glsl
It can also read input from stdin and output to stdout:
cat index.glsl | glslify > output.glsl
Browserify Transform
If using browserify from the command-line, simply pass glslify
in as a transform using the -t/--transform flag:
browserify -t glslify index.js -o bundle.js
Alternatively, you may include glslify as a browserify.transform
in your package.json file:
{
"name": "my-app",
"dependencies": {
"glslify": "^2.0.0"
},
"browserify": {
"transform": ["glslify"]
}
}
When writing your app, you should be able to require and call glslify the same as the node/electron interface, like so:
// index.js
var glsl = require('glslify')
var src = glsl.file('./shader.glsl')
console.log(src)
or using tagged template strings:
var glsl = require('glslify')
console.log(glsl`
#pragma glslify: noise = require('glsl-noise/simplex/3d')
precision mediump float;
varying vec3 vpos;
void main () {
gl_FragColor = vec4(noise(vpos*25.0),1);
}
`)
Your glslify calls will be replaced with bundled GLSL strings at build time automatically for you!
// index.js
var src = "#define GLSLIFY 1\n\nprecision mediump float; ..."
console.log(src)
Webpack Loader
You can use the glslify-loader module to bundle shaders through glslify with Webpack. Check out the repository for further information.
Babel Plugin
You can use glslify-babel as a Babel plugin. This allows you to use all ES6 features with glslify, including import statements and tagged template strings. Check out the repository to learn more.
:bulb: A Note on Babel Import/Export
If you are using Babel presets to transpile ES6 import/export to CommonJS require() statements, you may run into issues with glslify. This is because Babel mangles the output into source code that isn't easy to statically analyze. One solution is to directly map glslify to CommonJS statements, using babel-plugin-import-to-require in your .babelrc.
Usage
Installing a GLSL Module
Much like plain JavaScript modules, GLSL modules are stored on npm.
The main difference is that GLSL modules contain an index.glsl file
instead of an index.js. Generally, these modules start with glsl-
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.
Importing a GLSL Module
You can import a module using the following #pragma syntax:
#pragma glslify: noise = require(glsl-noise/simplex/2d)
void main() {
float brightness = noise(gl_FragCoord.xy);
gl_FragColor = vec4(vec3(brightness), 1.);
}
Shader dependencies are resolved using the same algorithm
as node, so the above will load ./node_modules/simplex/2d.glsl
from the shader's directory.
The above example would result in the following output:
#define GLSLIFY 1
//
// 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.
// https://github.com/ashima/webgl-noise
//
vec3 mod289_1_0(vec3 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec2 mod289_1_0(vec2 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec3 permute_1_1(vec3 x) {
return mod289_1_0(((x*34.0)+1.0)*x);
}
float snoise_1_2(vec2 v)
{
const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0
0.366025403784439, // 0.5*(sqrt(3.0)-1.0)
-0.577350269189626, // -1.0 + 2.0 * C.x
0.024390243902439); // 1.0 / 41.0
// First corner
vec2 i = floor(v + dot(v, C.yy) );
vec2 x0 = v - i + dot(i, C.xx);
// Other corners
vec2 i1;
//i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0
//i1.y = 1.0 - i1.x;
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
// x0 = x0 - 0.0 + 0.0 * C.xx ;
// x1 = x0 - i1 + 1.0 * C.xx ;
// x2 = x0 - 1.0 + 2.0 * C.xx ;
vec4 x12 = x0.xyxy + C.xxzz;
x12.xy -= i1;
// Permutations
i = mod289_1_0(i); // Avoid truncation effects in permutation
vec3 p = permute_1_1( permute_1_1( i.y + vec3(0.0, i1.y, 1.0 ))
+ i.x + vec3(0.0, i1.x, 1.0 ));
vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
m = m*m ;
m = m*m ;
// Gradients: 41 points uniformly over a line, mapped onto a diamond.
// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
vec3 x = 2.0 * fract(p * C.www) - 1.0;
vec3 h = abs(x) - 0.5;
vec3 ox = floor(x + 0.5);
vec3 a0 = x - ox;
// Normalise gradients implicitly by scaling m
// Approximation of: m *= inversesqrt( a0*a0 + h*h );
m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
// Compute final noise value at P
vec3 g;
g.x = a0.x * x0.x + h.x * x0.y;
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
return 130.0 * dot(m, g);
}
void main() {
float brightness = snoise_1_2(gl_FragCoord.xy);
gl_FragColor = vec4(vec3(brightness), 1.);
}
Exporting a GLSL Module
You can export a token from a module using the glslify: export
pragma, like so:
float myFunction(vec3 normal) {
return dot(vec3(0, 1, 0), normal);
}
#pragma glslify: export(myFunction)
This means that when you import this module file elsewhere, you'll
get myFunction in return:
#pragma glslify: topDot = require(./my-function.glsl)
topDot(vec3(0, 1, 0)); // 1
If you check the output shader source, you'll notice that variables have been renamed to avoid conflicts between multiple shader files
Related Skills
node-connect
344.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
99.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
344.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
344.4kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。

