@plutotcool/glsl-bundler
v1.2.1
Published
Functional regex-based bundling tools for glsl
Downloads
48
Keywords
Readme
glsl-bundler
Functional regex-based bundling tools for glsl. Run both on node and the browser.
Install
yarn add @plutotcool/glsl-bundler
Usage
Common examples
Load a shader as a string and resolve #include
directives:
import { load } from '@plutotcool/glsl-bundler'
await load(`./fragment.glsl`, import.meta.url)
Edit a shader:
import { define } from '@plutotcool/glsl-bundler'
const source = `
float rad2deg(float angle) {
return angle / PI * 180.0;
}
`
define(source, 'PI', 3.141592653589793)
Transpile a shader:
import { transpile } from '@plutotcool/glsl-bundler'
const source = `#version es 300
uniform diffuse sampler2D;
in vec2 vUv;
out vec4 FragColor;
void main() {
FragColor = texture(diffuse, vUv);
}
`
transpile(source)
Minify a shader:
import { minify } from '@plutotcool/glsl-bundler'
minify(`
float rad2deg(float angle) {
return angle / PI * 180.0;
}
`)
Combine loading, editing, transpiling and minifying into a bundle function:
import {
bundler,
loader,
writer,
transpiler,
minifier
} from '@plutotcool/glsl-bundler'
const bundle = bundler([
loader(import.meta.url),
writer.define('PI', 3.141592653589793),
transpiler(),
minifier()
])
await bundle(`
#include ./pi.glsl
#include ./rad2deg.glsl
void main() {
float turn = rad2deg(PI * 2.0);
}
`)
Bundler
The bundler
factory creates a function that transforms glsl source code given an array of transform functions:
import { bundler } from '@plutotcool/glsl-bundler'
const bundle = bundler([
(source: string) => `#define PI 3.141592653589793\n${source}`
])
bundle(`
float rad2deg(float angle) {
return angle / PI * 180.0;
}
`)
// #define PI 3.141592653589793
// float rad2deg(float angle) {
// return angle / PI * 180.0;
// }
Note that the resulting
bundle
function is itself a transform function
Alternatively, the bundle
shortcut can be used to get the same result in a single call:
import { bundle } from '@plutotcool/glsl-bundler'
bundle(`
float rad2deg(float angle) {
return angle / PI * 180.0;
}
`, [
(source: string) => `#define PI 3.141592653589793\n${source}`
])
Loader
The loader
factory creates an asynchronous transform function that resolves #include
directives from file system (node) or network (browser):
// ./rad2deg.glsl
#include ./pi.glsl
float rad2deg(float angle) {
return angle / PI * 180.0;
}
// ./pi.glsl
#define PI 3.141592653589793
import { loader } from '@plutotcool/glsl-bundler'
const load = loader(import.meta.url)
await load(`
#include ./pi.glsl
#include ./rad2deg.glsl
void main() {
float turn = rad2deg(PI * 2.0);
}
`)
// #define PI 3.141592653589793
//
// float rad2deg(float angle) {
// return angle / PI * 180.0;
// }
//
// void main() {
// float turn = rad2deg(PI * 2.0);
// }
Note that, even if
pi.glsl
is included twice, it is only outputed once as soon as needed. On node, the loader follows node module resolution using import-meta-resolve.
Alternatively, the load
shortcut can be used to load shaders directly from file system or network:
// ./fragment.glsl
#include ./pi.glsl
#include ./rad2deg.glsl
void main() {
float turn = rad2deg(PI * 2.0);
}
import { load } from '@plutotcool/glsl-bundler'
await load('./fragment.glsl', import.meta.url)
Writer
The writer
namespace exposes useful synchronous transform factories for editing glsl code:
import { writer, bundler } from '@plutotcool/glsl-bundler'
const write = bundler([
// insert line at given index or pattern, negative index starts from the end
writer.insert('// comment at line 3', 3)
writer.insert('// comment at last line', -1)
writer.insert('// comment before uniforms', /\buniform\b/)
// remove line at given number or pattern
writer.remove(/\/\/\s+comment line to remove/)
// insert or override define directive
// by default to the top of the code, or at given line index or patten
writer.define('PI', 3.14)
writer.define('A', true)
writer.define('B', 'foo', /uniform float a;/)
// replace given string or pattern
writer.replace(/\bFragColor\b/g, 'Color')
// insert or override glsl version, pass null to remove the version directive
writer.version('300 es')
])
write(`
#define PI 3.141592653589793
// comment line to remove
float rad2deg(float angle) {
return angle / PI * 180.0;
}
uniform float a;
out vec4 FragColor;
void main() {
float turn = rad2deg(PI * 2.0);
FragColor = vec4(turn / 360.0, 0., 0., 1.);
}
`)
// #version es 300
// #define A true
// #define PI 3.14
//
// // comment at line 3
//
// float rad2deg(float angle) {
// return angle / PI * 180.0;
// }
//
// // comment before uniforms
// #define B foo
// uniform float a;
//
// out vec4 Color;
//
// void main() {
// float turn = rad2deg(PI * 2.0);
// Color = vec4(turn / 360.0, 0., 0., 1.);
// }
// // comment at last line
Alternatively, the writer modules exposes shortcuts to edit glsl code in a single call:
import {
insert,
remove,
define,
replace,
version
} from '@plutotcool/glsl-bundler'
const source = `
#define PI 3.141592653589793
// comment line to remove
float rad2deg(float angle) {
return angle / PI * 180.0;
}
uniform float a;
out vec4 FragColor;
void main() {
float turn = rad2deg(PI * 2.0);
FragColor = vec4(turn / 360.0, 0., 0., 1.);
}
`
source = insert(source, '// comment at last line', -1)
source = remove(source, /\/\/\s+comment line to remove/)
source = define(source, 'PI', 3.14)
source = replace(source, /\bFragColor\b/g, 'Color')
source = version(source, '300 es')
// #version es 300
// #define A true
// #define PI 3.14
//
// float rad2deg(float angle) {
// return angle / PI * 180.0;
// }
//
// uniform float a;
//
// out vec4 Color;
//
// void main() {
// float turn = rad2deg(PI * 2.0);
// Color = vec4(turn / 360.0, 0., 0., 1.);
// }
// // comment at last line
Transpiler
The transpiler
factory creates a synchronous transform function that transpiles glsl code from and to versions 300 es and 100 es:
import { transpiler } from '@plutotcool/glsl-bundler'
const transpile = transpiler({
// Default transpile parameters:
target: 'auto',
version: 'auto',
defineTarget: true,
defineVersion: true
})
transpile(`#version es 300
in vec3 position;
in vec2 uv;
out vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4(position, 1.);
}
`)
// #define WEBGL_VERSION 1
// #define GLSL_VERSION 100
// attribute vec3 position;
// attribute vec2 uv;
//
// varying vec2 vUv;
//
// void main() {
// vUv = uv;
// gl_Position = vec4(position, 1.);
// }
transpile(`#version es 300
uniform diffuse sampler2D;
in vec2 vUv;
out vec4 FragColor;
void main() {
FragColor = texture(diffuse, vUv);
}
`)
// #define WEBGL_VERSION 1
// #define GLSL_VERSION 100
// uniform diffuse sampler2D;
//
// varying vec2 vUv;
//
// void main() {
// gl_FragColor = texture2D(diffuse, vUv);
// }
If
target
is set to'webgl2'
andversion
is set to'auto'
, the transpiler will not transform the syntax since both glsl 100 es and 300 es are supported.If
target
is set to'webgl1'
andversion
is set to'auto'
, the transpiler will transform the syntax to support 100 es.Even if the glsl code have mixed syntaxes (when including dependencies for instance), the transpiler will always output valid glsl; With the syntax that satisfies the version detected from the
#version
directive, but primarily with a syntax that is supported by the webgl target.If
version
is set to'100 es'
or'300 es'
, the transpiler will always transform the syntax to support the given glsl version.
Minifier
The minifier
factory creates a synchronous transform function that removes unnecessary characters and renames tokens:
import { minifier } from '@plutotcool/glsl-bundler'
const minify = minifier({
// Default minify parameters:
renameFunctions: true,
renameVariables: true,
renameDefines: true,
renameStructs: true,
trimComments: true,
trimSpaces: true,
trimZeros: true
})
minify(`
#define PI 3.141592653589793
float rad2deg(float angle) {
return angle / PI * 180.0;
}
void main() {
float turn = rad2deg(PI * 2.0);
}
`)
// #define a 3.141592653589793
// float b(float c){return c/a*180.;}void main(){float d=b(a*2.);}
Alternatively, the minify
shortcut can be used to get the same result in a single call:
import { minify } from '@plutotcool/glsl-bundler'
minify(`
#define PI 3.141592653589793
float rad2deg(float angle) {
return angle / PI * 180.0;
}
void main() {
float turn = rad2deg(PI * 2.0);
}
`, { /* Minify parameters */ }, [ /* Additional transform functions */ ])