
Product
Socket Now Supports pylock.toml Files
Socket now supports pylock.toml, enabling secure, reproducible Python builds with advanced scanning and full alignment with PEP 751's new standard.
Supply Chain Security
Vulnerability
Quality
Maintenance
License
glslify is a module system for GLSL (OpenGL Shading Language) that allows you to write modular shader code. It enables you to import and export GLSL code, making it easier to manage and reuse shader code across different projects.
Importing GLSL Modules
This feature allows you to import GLSL code from other files, making it easier to manage and reuse shader code. The `glslify` function takes the path to a GLSL file and returns the shader code as a string.
const glslify = require('glslify');
const shader = glslify('./shader.glsl');
Using GLSL Modules
You can use `glslify` to import both vertex and fragment shaders, allowing you to modularize your shader code. This makes it easier to maintain and update your shaders.
const glslify = require('glslify');
const vertexShader = glslify('./vertex.glsl');
const fragmentShader = glslify('./fragment.glsl');
Inlining GLSL Code
You can also inline GLSL code directly within your JavaScript files using template literals. This is useful for small shaders or for quick prototyping.
const glslify = require('glslify');
const shader = glslify(`
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`);
Transforming GLSL Code
glslify supports transforming GLSL code using plugins. In this example, the `glslify-hex` plugin is used to transform the GLSL code. This allows you to extend the functionality of glslify with custom transformations.
const glslify = require('glslify');
const shader = glslify('./shader.glsl', { transform: ['glslify-hex'] });
shader-loader is a Webpack loader that allows you to import GLSL shaders into your JavaScript code. It is similar to glslify in that it helps manage and import shader code, but it is specifically designed to work with Webpack.
glslify-loader is a Webpack loader that integrates glslify with Webpack. It allows you to use glslify's module system within a Webpack build process. This makes it easier to use glslify in projects that are already using Webpack.
A node.js-style module system for GLSL!
This module contains:
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.
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);
}
`))
var glsl = require('glslify')
Compile a shader inline using glsl
as a
tagged template string function.
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 nameCompile a shader string from a string src
.
opts.basedir
- directory to resolve relative paths in src
opts.transform
- an array of transform functions, transform module name
strings, or [trname,tropts]
pairsCompile a shader from a filename
.
opts.basedir
- directory to resolve relative paths in src
opts.transform
- an array of transform functions, transform module name
strings, or [trname,tropts]
pairsTo 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
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
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)
You can use the glslify-loader module to bundle shaders through glslify with Webpack. Check out the repository for further information.
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.
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
.
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.
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.);
}
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.
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 {
vec3 position;
vec3 color;
};
#pragma glslify: 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.
Give some-module
access to locally declared bar
whenever it looks for foo
internally:
int bar;
#pragma glslify: 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[500]
arrays that we'd like to be summed up.
Here's a module that performs a reduction using a function map
.
float accumulate(float list[N]) {
float z = 0;
for (int i = 0; i<N; i++) {
z = map(z,list[i]);
}
return z;
}
#pragma glslify: export(accumulate)
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 require
function:
const int M = 500;
float add(float a, float b){ return a+b; }
#pragma glslify: 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[17]
arrays the same way:
const int M = 500;
const int L = 17;
float add(float a, float b){ return a+b; }
float mul(float a, float b){ return a*b; }
#pragma glslify: sum500 = require('./accumulator.glsl',N=M,map=add)
#pragma glslify: 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 vec3
s).
There are three kinds of source transform:
-t
it'll only apply itself to files outside of node_modules
, but you
can include it in package.json
too: 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
package.json
file's glslify.transform
property, like so:
{
"name": "my-project",
"dependencies": {
"glslify-hex": "^2.0.0",
"glslify": "^2.0.0"
},
"glslify": {
"transform": ["glslify-hex"]
}
}
You may also include arguments to your transform as you would with browserify:
{
"name": "my-project",
"dependencies": {
"glslify-hex": "^2.0.0",
"glslify": "^2.0.0"
},
"glslify": {
"transform": [
["glslify-hex", {
"option-1": true,
"option-2": 42
}]
]
}
}
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 = require('glslify')
glslify.file(__dirname + '/shader.glsl', {
transform: [
["glslify-hex", {
"option-1": true,
"option-2": 42
}],
["global-transform", { global: true }],
["post-transform", { post: true }]
]
})
See stackgl/contributing for details.
MIT. See LICENSE.md for details.
FAQs
A node.js-style module system for GLSL!
The npm package glslify receives a total of 208,002 weekly downloads. As such, glslify popularity was classified as popular.
We found that glslify demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 19 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket now supports pylock.toml, enabling secure, reproducible Python builds with advanced scanning and full alignment with PEP 751's new standard.
Security News
Research
Socket uncovered two npm packages that register hidden HTTP endpoints to delete all files on command.
Research
Security News
Malicious Ruby gems typosquat Fastlane plugins to steal Telegram bot tokens, messages, and files, exploiting demand after Vietnam’s Telegram ban.