npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@plutotcool/glsl-bundler

v1.2.1

Published

Functional regex-based bundling tools for glsl

Downloads

28

Readme

glsl-bundler

test build release version types

Functional regex-based bundling tools for glsl. Run both on node and the browser.

Live demo

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' and version 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' and version 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 */ ])