@plutotcool/glsl-bundler
v1.2.1
Published
Functional regex-based bundling tools for glsl
Keywords
Readme
glsl-bundler
Functional regex-based bundling tools for glsl. Run both on node and the browser.
Install
yarn add @plutotcool/glsl-bundlerUsage
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
bundlefunction 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.141592653589793import { 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.glslis 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 lineAlternatively, 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 lineTranspiler
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
targetis set to'webgl2'andversionis set to'auto', the transpiler will not transform the syntax since both glsl 100 es and 300 es are supported.If
targetis set to'webgl1'andversionis 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
#versiondirective, but primarily with a syntax that is supported by the webgl target.If
versionis 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 */ ])