Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/glslify/glslify
A node.js-style module system for GLSL! :sparkles:
https://github.com/glslify/glslify
Last synced: 12 days ago
JSON representation
A node.js-style module system for GLSL! :sparkles:
- Host: GitHub
- URL: https://github.com/glslify/glslify
- Owner: glslify
- License: other
- Created: 2012-12-04T06:39:27.000Z (almost 12 years ago)
- Default Branch: master
- Last Pushed: 2022-06-29T02:02:58.000Z (over 2 years ago)
- Last Synced: 2024-05-13T16:24:40.898Z (6 months ago)
- Language: JavaScript
- Homepage:
- Size: 146 KB
- Stars: 2,169
- Watchers: 41
- Forks: 83
- Open Issues: 61
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
- awesome-starred - glslify/glslify - A node.js-style module system for GLSL! :sparkles: (others)
README
# 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](http://browserify.org/) transformIt forms one of the core components of the [stack.gl](http://stack.gl/)
ecosystem, allowing you to install GLSL modules from [npm](http://npmjs.com) 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](https://github.com/hughsk/glsl-fog),
[noise](https://github.com/hughsk/glsl-noise),
[film grain](https://github.com/mattdesl/glsl-film-grain),
[raymarching helpers](https://github.com/stackgl/glsl-smooth-min),
[easing functions](https://github.com/stackgl/glsl-easings) and
[lighting models](https://github.com/stackgl/glsl-specular-cook-torrance).A full list can be found on the [stack.gl packages list](http://stack.gl/packages)
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](http://threejs.org/) and
[pex](http://vorg.github.io/pex/), with more on the way!
[Open an issue](https://github.com/stackgl/glslify/issues/new) 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](http://glslb.in/): it's a fragment shader sandbox similar to
[Shadertoy](http://shadertoy.com/) and
[GLSL Sandbox](http://glslsandbox.com/)
with built in support for glslify.*## Example
``` javascript
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
``` javascript
var glsl = require('glslify')
```### var src = glsl\`shader source...\`
Compile a shader inline using `glsl` as a
[tagged template string function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals).### 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 paths
* `opts.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 in `src`
* `opts.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 in `src`
* `opts.transform` - an array of transform functions, transform module name
strings, or `[trname,tropts]` pairs## Installation
[![NPM](https://nodei.co/npm/glslify.png)](https://nodei.co/npm/glslify/)
To install the command-line interface, install glslify globally like
so:``` bash
npm install -g glslify
```To install glslify for use as a browserify transform, you should
install it locally instead:``` bash
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:``` bash
glslify index.glsl -o output.glsl
```It can also read input from stdin and output to stdout:
``` bash
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:``` bash
browserify -t glslify index.js -o bundle.js
```Alternatively, you may include glslify as a `browserify.transform`
in your `package.json` file:``` json
{
"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:``` javascript
// index.js
var glsl = require('glslify')var src = glsl.file('./shader.glsl')
console.log(src)
```or using tagged template strings:
``` javascript
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!``` javascript
// index.js
var src = "#define GLSLIFY 1\n\nprecision mediump float; ..."console.log(src)
```### [Webpack](http://webpack.github.io/) Loader
You can use the
[glslify-loader](https://github.com/stackgl/glslify-loader)
module to bundle shaders through glslify with Webpack. Check out
[the repository](https://github.com/stackgl/glslify-loader)
for further information.### [Babel](https://babeljs.io) Plugin
You can use [glslify-babel](https://github.com/stackgl/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](https://github.com/stackgl/glslify-babel) 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](https://github.com/mattdesl/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](https://github.com/hughsk/glsl-noise) in
your current directory:``` bash
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:
``` glsl
#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:
``` glsl
#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:``` glsl
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:``` glsl
#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:``` glsl
struct Light {
vec3 position;
vec3 color;
};#pragma glslify: export(Light)
```### Passing references between modules
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:
``` glsl
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`.
``` glsl
float accumulate(float list[N]) {
float z = 0;
for (int i = 0; i