├── .prettierignore ├── .gitmodules ├── examples ├── blursketch.js ├── blurtraceexample.html ├── hueexample.html ├── blurexample.html ├── inkyexample.html ├── colordistexample.html ├── instanceexample.html ├── mandalaexample.html ├── blurtracesketch.js ├── inkysketch.js ├── huesketch.js ├── colordistsketch.js ├── instancesketch.js └── mandalasketch.js ├── LICENSE ├── README.md ├── p5extensions.js └── post5.js /.prettierignore: -------------------------------------------------------------------------------- 1 | everythingpass.js 2 | p5.js -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "postpre"] 2 | path = postpre 3 | url = https://github.com/bandaloo/postpre 4 | ignore = dirty 5 | -------------------------------------------------------------------------------- /examples/blursketch.js: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | let black = false; 3 | 4 | function setup() { 5 | createCanvas(400, 400); 6 | addEffects(blur2d(2, 2, 13), motionBlur()); 7 | addChannels(null); 8 | } 9 | 10 | function draw() { 11 | background(255); 12 | fill(255, 0, 0); 13 | noStroke(); 14 | ellipse(mouseX, mouseY, 70, 70); 15 | } 16 | -------------------------------------------------------------------------------- /examples/blurtraceexample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

blur and trace

10 |

use mouse to paint and click to change color

11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/hueexample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

hue shift

10 |

use mouse to paint and click to change color

11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/blurexample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

types of blur

10 |

move the mouse to move the circle around

11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/inkyexample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

inky sunbeams

10 |

use mouse to paint and click to change color

11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/colordistexample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

types of blur

10 |

move the mouse to move the circle around

11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/instanceexample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

instance mode

10 |

use mouse to paint and click to change color

11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/mandalaexample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

mandala

10 |

use mouse to paint and click to change color

11 |

x position controls tracing color

12 |

y position controls noisiness

13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/blurtracesketch.js: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | let white = false; 3 | 4 | function setup() { 5 | createCanvas(400, 400); 6 | background(0); 7 | addEffects(blurAndTrace()); 8 | addChannels(null); 9 | } 10 | 11 | function draw() { 12 | if (white) { 13 | fill(0); 14 | } else { 15 | fill(Math.random() * 255, Math.random() * 255, Math.random() * 255); 16 | } 17 | noStroke(); 18 | ellipse(mouseX, mouseY, 20 + (r = 60 * Math.random()), 20 + r); 19 | } 20 | 21 | function mouseClicked() { 22 | white = !white; 23 | } 24 | -------------------------------------------------------------------------------- /examples/inkysketch.js: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | let black = false; 3 | 4 | function setup() { 5 | createCanvas(400, 400); 6 | background(255); 7 | addEffects( 8 | noiseDisplacement(), 9 | godrays({ samplerNum: -1, lightPos: nMouse() }), 10 | oldFilm(), 11 | vignette() 12 | ); 13 | } 14 | 15 | function draw() { 16 | const col = black ? 255 : 0; 17 | fill(col, col, col); 18 | noStroke(); 19 | ellipse(mouseX, mouseY, 20 + (r = 60 * Math.random()), 20 + r); 20 | } 21 | 22 | function mouseClicked() { 23 | black = !black; 24 | } 25 | -------------------------------------------------------------------------------- /examples/huesketch.js: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | let white = false; 3 | 4 | function setup() { 5 | createCanvas(400, 400); 6 | background(255); 7 | addEffects( 8 | noiseDisplacement(0.01, 0), 9 | hsvToRgb(changeComp(rgbToHsv(fColor()), getComp(nMouse(), "x"), "x", "+")) 10 | ); 11 | } 12 | 13 | function draw() { 14 | if (white) { 15 | colorMode(RGB); 16 | fill(255, 255, 255); 17 | } else { 18 | colorMode(HSB, 100); 19 | fill(Math.random() * 100, 100, 100); 20 | } 21 | noStroke(); 22 | ellipse(mouseX, mouseY, 20 + (r = 60 * Math.random()), 20 + r); 23 | } 24 | 25 | function mouseClicked() { 26 | white = !white; 27 | } 28 | -------------------------------------------------------------------------------- /examples/colordistsketch.js: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | let white = false; 3 | 4 | function setup() { 5 | createCanvas(400, 400); 6 | background(255); 7 | addEffects( 8 | godrays({ samplerNum: -1, lightPos: nMouse(), density: 0.5 }), 9 | channel( 10 | -1, 11 | op(pos(), "+", op(get2Comp(fColor(), "rg"), "*", op(nMouse(), "-", 0.5))) 12 | ) 13 | ); 14 | } 15 | 16 | function draw() { 17 | if (white) { 18 | colorMode(RGB); 19 | fill(255, 255, 255); 20 | } else { 21 | colorMode(HSB, 100); 22 | fill(Math.random() * 100, 100, 100); 23 | } 24 | noStroke(); 25 | ellipse(mouseX, mouseY, 20 + (r = 60 * Math.random()), 20 + r); 26 | } 27 | 28 | function mouseClicked() { 29 | white = !white; 30 | } 31 | -------------------------------------------------------------------------------- /examples/instancesketch.js: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | new p5(function (sketch) { 3 | sketch.black = false; 4 | 5 | sketch.setup = () => { 6 | const c = sketch.createCanvas(400, 400); 7 | sketch.background(255); 8 | sketch.addEffects( 9 | sketch.noiseDisplacement(), 10 | sketch.godrays({ samplerNum: -1, lightPos: sketch.nMouse() }), 11 | sketch.oldFilm(), 12 | sketch.vignette() 13 | ); 14 | }; 15 | 16 | sketch.draw = () => { 17 | const col = sketch.black ? 255 : 0; 18 | sketch.fill(col, col, col); 19 | sketch.noStroke(); 20 | sketch.ellipse( 21 | sketch.mouseX, 22 | sketch.mouseY, 23 | 20 + (r = 60 * Math.random()), 24 | 20 + r 25 | ); 26 | }; 27 | 28 | sketch.mouseClicked = () => { 29 | sketch.black = !sketch.black; 30 | }; 31 | }); 32 | -------------------------------------------------------------------------------- /examples/mandalasketch.js: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | let black = false; 3 | 4 | function setup() { 5 | createCanvas(400, 400); 6 | background(0); 7 | const intensity = op(getComp(nMouse(), "y"), "*", 0.03); 8 | const tracing = op(op(getComp(nMouse(), "x"), "-", 0.5), "*", 2); 9 | addEffects( 10 | noiseDisplacement(0.05, 1, intensity), 11 | blurAndTrace(tracing, 2), 12 | kaleidoscope(), 13 | godrays({ samplerNum: -1, lightPos: nMouse(), density: 0.5 }) 14 | ); 15 | addChannels(null); 16 | } 17 | 18 | function draw() { 19 | if (black) { 20 | fill(0); 21 | } else { 22 | fill(Math.random() * 255, Math.random() * 255, Math.random() * 255); 23 | } 24 | noStroke(); 25 | ellipse(mouseX, mouseY, 20 + (r = 60 * Math.random()), 20 + r); 26 | } 27 | 28 | function mouseClicked() { 29 | black = !black; 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Cole Granof 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # post5 2 | 3 | post5 is a library for p5 that enables you to do interesting post-processing 4 | effects with the power of WebGL2. You can build it or download it from the 5 | "releases" section on the sidebar in GitHub. It wraps 6 | [merge-pass](https://github.com/bandaloo/merge-pass) and 7 | [postpre](https://github.com/bandaloo/postpre). 8 | 9 | Check out the 10 | [merge-pass live example](https://www.bandaloo.fun/merge-pass/example.html) 11 | and the [postpre live example](https://www.bandaloo.fun/postpre/example.html) 12 | to get an idea of how to nest and sequence these effects in interesting ways. 13 | Also check out the included examples in this repo or the examples 14 | [in the web editor](https://editor.p5js.org/bandaloo/collections/KKmpKHP-V). 15 | 16 | To get started, all you need to do is include the `post5.js` script after 17 | the `p5` script and before your sketch script: 18 | 19 | ```html 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ``` 30 | 31 | ## Mappings from merge-pass and postpre to post5 32 | 33 | This library is really just a thin wrapper for merge-pass and postpre. 34 | (Although the default arguments for the provided functions will get you 35 | pretty far, a number of things could be done to make this easier to use 36 | without TypeScript and the surrounding tooling.) As mentioned previously, 37 | check out the 38 | [merge-pass live example](https://www.bandaloo.fun/merge-pass/example.html) 39 | and the [postpre live example](https://www.bandaloo.fun/postpre/example.html) 40 | for examples on how to use this library. Below is a table to keep track of 41 | the mappings in post5; you want to use the names in the left column. Most are 42 | just changed to camelCase, but some names had to change totally due to naming 43 | conflicts with p5. 44 | 45 | | post5 | merge-pass/postpre | 46 | | ----------------- | ------------------ | 47 | | foggyRays | foggyrays | 48 | | vignette | vignette | 49 | | blurAndTrace | blurandtrace | 50 | | lightBands | lightbands | 51 | | noiseDisplacement | noisedisplacement | 52 | | oldFilm | oldfilm | 53 | | kaleidoscope | kaleidoscope | 54 | | effectLoop | loop | 55 | | gauss | gauss | 56 | | fColor | fcolor | 57 | | vec2 | vec2 | 58 | | vec3 | vec3 | 59 | | vec4 | vec4 | 60 | | pVec2 | pvec2 | 61 | | pVec3 | pvec3 | 62 | | pVec4 | pvec4 | 63 | | op | op | 64 | | blur2d | blur2d | 65 | | len | len | 66 | | normalize | norm | 67 | | pixel | pixel | 68 | | pos | pos | 69 | | center | center | 70 | | input | input | 71 | | bright | brightness | 72 | | contrast | contrast | 73 | | grain | grain | 74 | | getComp | getcomp | 75 | | get2Comp | get2comp | 76 | | get3Comp | get3comp | 77 | | get4Comp | get4comp | 78 | | changeComp | changecomp | 79 | | rgbToHsv | rgb2hsv | 80 | | hsvToRgb | hsv2rgb | 81 | | time | time | 82 | | a1 | a1 | 83 | | a2 | a2 | 84 | | fxaa | fxaa | 85 | | channel | channel | 86 | | depthOfField | dof | 87 | | trueDepth | truedepth | 88 | | godrays | godrays | 89 | | depthToOcclusion | depth2occlusion | 90 | | resolution | resolution | 91 | | mouse | mouse | 92 | | rotate2d | rotate | 93 | | translate2d | translate | 94 | | nMouse | nmouse | 95 | | perlin | perlin | 96 | | simplex | simplex | 97 | | motionBlur | motionblur | 98 | | randomFloat | random | 99 | | sobel | sobel | 100 | | bloom | bloom | 101 | | monochrome | monochrome | 102 | | invert | invert | 103 | | edge | edge | 104 | | edgeColor | edgecolor | 105 | | ternary | ternary | 106 | | region | region | 107 | | cFloat | cfloat | 108 | | cVec2 | cvec2 | 109 | | cVec3 | cvec3 | 110 | | cVec4 | cvec4 | 111 | | mut | mut | 112 | | basicFloat | float | 113 | | pFloat | pfloat | 114 | | tag | tag | 115 | | celShade | celshade | 116 | 117 | ## Building 118 | 119 | Run `sh build.sh`. This will automatically run `npm install` if 120 | `node_modules` does not exist in the postpre submodule and generate 121 | `post5.js`, which is the file you include as a script. Run `sh build.sh` to 122 | run postpre's `npm install` regardless. 123 | -------------------------------------------------------------------------------- /p5extensions.js: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | { 3 | const addToProto = (pr, name, add) => { 4 | if (p5.prototype.hasOwnProperty(name)) { 5 | throw new Error("p5 already has this: " + name); 6 | } 7 | pr[name] = add; 8 | }; 9 | 10 | const pr = p5.prototype; 11 | // this avoids collisions with names in p5 and changes to camelCase 12 | addToProto(pr, "foggyRays", MP.foggyrays); 13 | addToProto(pr, "vignette", MP.vignette); 14 | addToProto(pr, "blurAndTrace", MP.blurandtrace); 15 | addToProto(pr, "lightBands", MP.lightbands); 16 | addToProto(pr, "noiseDisplacement", MP.noisedisplacement); 17 | addToProto(pr, "oldFilm", MP.oldfilm); 18 | addToProto(pr, "kaleidoscope", MP.kaleidoscope); 19 | addToProto(pr, "effectLoop", MP.loop); 20 | addToProto(pr, "gauss", MP.gauss); 21 | addToProto(pr, "fColor", MP.fcolor); 22 | addToProto(pr, "vec2", MP.vec2); 23 | addToProto(pr, "vec3", MP.vec3); 24 | addToProto(pr, "vec4", MP.vec4); 25 | addToProto(pr, "pVec2", MP.pvec2); 26 | addToProto(pr, "pVec3", MP.pvec3); 27 | addToProto(pr, "pVec4", MP.pvec4); 28 | addToProto(pr, "op", MP.op); 29 | addToProto(pr, "blur2d", MP.blur2d); 30 | addToProto(pr, "len", MP.len); 31 | addToProto(pr, "normalize", MP.norm); 32 | addToProto(pr, "pixel", MP.pixel); 33 | addToProto(pr, "pos", MP.pos); 34 | addToProto(pr, "center", MP.center); 35 | addToProto(pr, "input", MP.input); 36 | addToProto(pr, "bright", MP.brightness); 37 | addToProto(pr, "contrast", MP.contrast); 38 | addToProto(pr, "grain", MP.grain); 39 | addToProto(pr, "getComp", MP.getcomp); 40 | addToProto(pr, "get2Comp", MP.get2comp); 41 | addToProto(pr, "get3Comp", MP.get3comp); 42 | addToProto(pr, "get4Comp", MP.get4comp); 43 | addToProto(pr, "changeComp", MP.changecomp); 44 | addToProto(pr, "rgbToHsv", MP.rgb2hsv); 45 | addToProto(pr, "hsvToRgb", MP.hsv2rgb); 46 | addToProto(pr, "time", MP.time); 47 | addToProto(pr, "a1", MP.a1); 48 | addToProto(pr, "a2", MP.a2); 49 | addToProto(pr, "fxaa", MP.fxaa); 50 | addToProto(pr, "channel", MP.channel); 51 | addToProto(pr, "depthOfField", MP.dof); 52 | addToProto(pr, "trueDepth", MP.truedepth); 53 | addToProto(pr, "godrays", MP.godrays); 54 | addToProto(pr, "depthToOcclusion", MP.depth2occlusion); 55 | addToProto(pr, "resolution", MP.resolution); 56 | addToProto(pr, "mouse", MP.mouse); 57 | addToProto(pr, "rotate2d", MP.rotate); 58 | addToProto(pr, "translate2d", MP.translate); 59 | addToProto(pr, "nMouse", MP.nmouse); 60 | addToProto(pr, "perlin", MP.perlin); 61 | addToProto(pr, "simplex", MP.simplex); 62 | addToProto(pr, "motionBlur", MP.motionblur); 63 | addToProto(pr, "randomFloat", MP.random); 64 | addToProto(pr, "sobel", MP.sobel); 65 | addToProto(pr, "bloom", MP.bloom); 66 | addToProto(pr, "monochrome", MP.monochrome); 67 | addToProto(pr, "invert", MP.invert); 68 | addToProto(pr, "edge", MP.edge); 69 | addToProto(pr, "edgeColor", MP.edgecolor); 70 | addToProto(pr, "ternary", MP.ternary); 71 | addToProto(pr, "region", MP.region); 72 | addToProto(pr, "cFloat", MP.cfloat); 73 | addToProto(pr, "cVec2", MP.cvec2); 74 | addToProto(pr, "cVec3", MP.cvec3); 75 | addToProto(pr, "cVec4", MP.cvec4); 76 | addToProto(pr, "mut", MP.mut); 77 | addToProto(pr, "basicFloat", MP.float); 78 | addToProto(pr, "pFloat", MP.pfloat); 79 | addToProto(pr, "tag", MP.tag); 80 | addToProto(pr, "celShade", MP.celshade); 81 | 82 | addToProto(pr, "__info", { 83 | replaced: false, 84 | orig: null, 85 | canvas: null, 86 | gl: null, 87 | verbosity: 0, 88 | startTime: 0, 89 | mousePos: { x: 0, y: 0 }, 90 | effects: [], 91 | channels: [], 92 | }); 93 | 94 | console.log(pr.__info); 95 | 96 | addToProto(pr, "addEffects", function () { 97 | pr.__info.effects.push(...arguments); 98 | }); 99 | 100 | addToProto(pr, "addChannels", function () { 101 | pr.__info.channels.push(...arguments); 102 | }); 103 | 104 | const info = p5.prototype.__info; 105 | 106 | function mpInit() { 107 | if (info.verbosity > 0) console.log("mp init"); 108 | } 109 | 110 | function mpPre() { 111 | if (info.replaced || !info.effects) return; 112 | if (info.verbosity > 0) console.log("mp pre x1"); 113 | 114 | info.startTime = new Date().getTime(); 115 | 116 | info.orig = document.getElementById("defaultCanvas0"); 117 | 118 | if (!info.orig) throw new Error("mergepass couldn't get the p5 canvas"); 119 | const parent = info.orig.parentElement; 120 | parent.style.position = "relative"; 121 | 122 | info.canvas = document.createElement("canvas"); 123 | 124 | info.canvas.width = info.orig.width; 125 | info.canvas.height = info.orig.height; 126 | info.canvas.style.width = info.orig.style.width; 127 | info.canvas.style.height = info.orig.style.height; 128 | 129 | info.gl = info.canvas.getContext("webgl2"); 130 | if (!info.gl) throw new Error("mergepass couldn't get the webgl2 context"); 131 | 132 | parent.appendChild(info.canvas); 133 | 134 | info.merger = new MP.Merger(pr.__info.effects, info.orig, info.gl, { 135 | channels: pr.__info.channels, 136 | }); 137 | 138 | const align = (c, z) => { 139 | c.style.position = "absolute"; 140 | c.style.left = 0; 141 | c.style.top = 0; 142 | c.style.zIndex = z; 143 | }; 144 | 145 | align(info.canvas, 0); 146 | align(info.orig, 1); 147 | 148 | info.orig.style.visibility = "hidden"; 149 | 150 | info.canvas.addEventListener("mousemove", (e) => { 151 | const rect = info.orig.getBoundingClientRect(); 152 | info.mousePos.x = 153 | (info.canvas.width * (e.clientX - rect.left)) / rect.width; 154 | info.mousePos.y = 155 | (info.canvas.height * (rect.height - (e.clientY - rect.top))) / 156 | rect.height; 157 | }); 158 | 159 | info.replaced = true; 160 | } 161 | 162 | function mpPost() { 163 | if (info.verbosity > 1) console.log("mp post"); 164 | if (!info.effects) return; 165 | const time = info.startTime - new Date().getTime(); 166 | info.merger.draw(time / 1000, info.mousePos.x, info.mousePos.y); 167 | } 168 | 169 | p5.prototype.registerMethod("pre", mpPre); 170 | p5.prototype.registerMethod("init", mpInit); 171 | p5.prototype.registerMethod("post", mpPost); 172 | } 173 | -------------------------------------------------------------------------------- /post5.js: -------------------------------------------------------------------------------- 1 | /* post5 0.1.0 | (c) 2020, Cole Granof | MIT License */ 2 | // @ts-nocheck 3 | (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i merge_pass_1.simplex(merge_pass_1.op(merge_pass_1.op(merge_pass_1.changecomp(merge_pass_1.op(merge_pass_1.pos(), "/", periodFloat), merge_pass_1.op(merge_pass_1.time(), "*", speedFloat), comp, "+"), "*", merge_pass_1.op(merge_pass_1.resolution(), "/", merge_pass_1.getcomp(merge_pass_1.resolution(), "y"))), "+", comp === "x" ? X_OFF : Y_OFF)); 249 | super(merge_pass_1.channel(-1, merge_pass_1.op(merge_pass_1.op(merge_pass_1.op(merge_pass_1.vec2(noise("x"), noise("y")), "*", intensityFloat), "*", merge_pass_1.op(merge_pass_1.get2comp(merge_pass_1.resolution(), "yx"), "/", merge_pass_1.getcomp(merge_pass_1.resolution(), "y"))), "+", merge_pass_1.pos()))); 250 | this.periodFloat = periodFloat; 251 | this.speedFloat = speedFloat; 252 | this.intensityFloat = intensityFloat; 253 | this.period = period; 254 | this.speed = speed; 255 | this.intensity = intensity; 256 | } 257 | setPeriod(period) { 258 | this.periodFloat.setVal(merge_pass_1.wrapInValue(period)); 259 | this.period = merge_pass_1.wrapInValue(period); 260 | } 261 | setSpeed(speed) { 262 | this.speedFloat.setVal(merge_pass_1.wrapInValue(speed)); 263 | this.speed = merge_pass_1.wrapInValue(speed); 264 | } 265 | setIntensity(intensity) { 266 | this.intensityFloat.setVal(merge_pass_1.wrapInValue(intensity)); 267 | this.speed = merge_pass_1.wrapInValue(intensity); 268 | } 269 | } 270 | exports.NoiseDisplacement = NoiseDisplacement; 271 | function noisedisplacement(period = merge_pass_1.mut(0.1), speed = merge_pass_1.mut(1), intensity = merge_pass_1.mut(0.005)) { 272 | return new NoiseDisplacement(merge_pass_1.wrapInValue(period), merge_pass_1.wrapInValue(speed), merge_pass_1.wrapInValue(intensity)); 273 | } 274 | exports.noisedisplacement = noisedisplacement; 275 | 276 | },{"@bandaloo/merge-pass":62}],8:[function(require,module,exports){ 277 | "use strict"; 278 | Object.defineProperty(exports, "__esModule", { value: true }); 279 | exports.oldfilm = exports.OldFilm = void 0; 280 | const merge_pass_1 = require("@bandaloo/merge-pass"); 281 | class OldFilm extends merge_pass_1.WrappedExpr { 282 | constructor(speckIntensity, lineIntensity, grainIntensity) { 283 | const speckIntensityFloat = merge_pass_1.float(speckIntensity); 284 | const lineIntensityFloat = merge_pass_1.float(lineIntensity); 285 | const grainIntensityFloat = merge_pass_1.float(grainIntensity); 286 | const ftime = merge_pass_1.a1("floor", merge_pass_1.op(merge_pass_1.time(), "*", 24)); 287 | const grainy = merge_pass_1.op(merge_pass_1.random(merge_pass_1.op(merge_pass_1.pixel(), "+", merge_pass_1.a2("mod", merge_pass_1.op(ftime, "*", 99), 3000))), "*", grainIntensityFloat); 288 | const rate = 10; 289 | const triangles = merge_pass_1.op(merge_pass_1.op(merge_pass_1.op(merge_pass_1.a1("abs", merge_pass_1.op(merge_pass_1.op(2, "*", merge_pass_1.a1("fract", merge_pass_1.op(rate, "*", merge_pass_1.getcomp(merge_pass_1.pos(), "x")))), "-", 1)), "-", 0.5), "*", 2), "*", lineIntensityFloat); 290 | const stepping = merge_pass_1.a2("step", merge_pass_1.op(1, "-", merge_pass_1.op(1, "/", rate * 12)), merge_pass_1.a2("mod", merge_pass_1.op(merge_pass_1.getcomp(merge_pass_1.pos(), "x"), "+", merge_pass_1.random(merge_pass_1.op(merge_pass_1.vec2(50, 50), "*", merge_pass_1.time()))), 1)); 291 | const lines = merge_pass_1.op(triangles, "*", stepping); 292 | const spos = merge_pass_1.a2("mod", merge_pass_1.op(merge_pass_1.op(merge_pass_1.pos(), "*", merge_pass_1.op(merge_pass_1.resolution(), "/", merge_pass_1.getcomp(merge_pass_1.resolution(), "y"))), "+", ftime), merge_pass_1.vec2(100, 100)); 293 | const fsimplex = merge_pass_1.op(merge_pass_1.op(merge_pass_1.simplex(merge_pass_1.op(spos, "*", 7)), "*", 0.44), "+", 0.5); 294 | const spots = merge_pass_1.op(merge_pass_1.a2("step", fsimplex, 0.08), "*", speckIntensityFloat); 295 | super(merge_pass_1.monochrome(merge_pass_1.brightness(spots, merge_pass_1.brightness(lines, merge_pass_1.brightness(grainy))))); 296 | this.speckIntensityFloat = speckIntensityFloat; 297 | this.lineIntensityFloat = lineIntensityFloat; 298 | this.grainIntensityFloat = grainIntensityFloat; 299 | this.speckIntensity = speckIntensity; 300 | this.lineIntensity = lineIntensity; 301 | this.grainIntensity = grainIntensity; 302 | } 303 | setSpeckIntensity(speckIntensity) { 304 | this.speckIntensityFloat.setVal(merge_pass_1.wrapInValue(speckIntensity)); 305 | this.speckIntensity = merge_pass_1.wrapInValue(speckIntensity); 306 | } 307 | setLineIntensity(lineIntensity) { 308 | this.lineIntensityFloat.setVal(merge_pass_1.wrapInValue(lineIntensity)); 309 | this.lineIntensity = merge_pass_1.wrapInValue(lineIntensity); 310 | } 311 | setGrainIntensity(grainIntensity) { 312 | this.grainIntensityFloat.setVal(merge_pass_1.wrapInValue(grainIntensity)); 313 | this.grainIntensity = merge_pass_1.wrapInValue(grainIntensity); 314 | } 315 | } 316 | exports.OldFilm = OldFilm; 317 | function oldfilm(speckIntensity = merge_pass_1.mut(0.4), lineIntensity = merge_pass_1.mut(0.12), grainIntensity = merge_pass_1.mut(0.11)) { 318 | return new OldFilm(merge_pass_1.wrapInValue(speckIntensity), merge_pass_1.wrapInValue(lineIntensity), merge_pass_1.wrapInValue(grainIntensity)); 319 | } 320 | exports.oldfilm = oldfilm; 321 | 322 | },{"@bandaloo/merge-pass":62}],9:[function(require,module,exports){ 323 | "use strict"; 324 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 325 | if (k2 === undefined) k2 = k; 326 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 327 | }) : (function(o, m, k, k2) { 328 | if (k2 === undefined) k2 = k; 329 | o[k2] = m[k]; 330 | })); 331 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 332 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 333 | }) : function(o, v) { 334 | o["default"] = v; 335 | }); 336 | var __importStar = (this && this.__importStar) || function (mod) { 337 | if (mod && mod.__esModule) return mod; 338 | var result = {}; 339 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 340 | __setModuleDefault(result, mod); 341 | return result; 342 | }; 343 | Object.defineProperty(exports, "__esModule", { value: true }); 344 | // @ts-nocheck 345 | const postpre = __importStar(require("./index")); 346 | const mergepass = __importStar(require("@bandaloo/merge-pass")); 347 | window.MP = Object.assign({}, postpre, mergepass); 348 | 349 | },{"./index":4,"@bandaloo/merge-pass":62}],10:[function(require,module,exports){ 350 | "use strict"; 351 | Object.defineProperty(exports, "__esModule", { value: true }); 352 | exports.vignette = exports.Vignette = void 0; 353 | const merge_pass_1 = require("@bandaloo/merge-pass"); 354 | class Vignette extends merge_pass_1.EffectLoop { 355 | constructor(blurScalar, brightnessScalar, brightnessExponent) { 356 | const blurScalarFloat = merge_pass_1.float(blurScalar); 357 | const brightnessScalarFloat = merge_pass_1.float(brightnessScalar); 358 | const brightnessExponentFloat = merge_pass_1.float(brightnessExponent); 359 | const blurLen = merge_pass_1.op(merge_pass_1.len(merge_pass_1.center()), "*", blurScalarFloat); 360 | const blurExpr = merge_pass_1.blur2d(blurLen, blurLen); 361 | const brightLen = merge_pass_1.a2("pow", merge_pass_1.len(merge_pass_1.center()), brightnessExponentFloat); 362 | const brightExpr = merge_pass_1.brightness(merge_pass_1.op(brightLen, "*", merge_pass_1.op(brightnessScalarFloat, "*", -1))); 363 | super([blurExpr, brightExpr], { num: 1 }); 364 | this.blurScalarFloat = blurScalarFloat; 365 | this.brightnessScalarFloat = brightnessScalarFloat; 366 | this.brightnessExponentFloat = brightnessExponentFloat; 367 | this.blurScalar = blurScalar; 368 | this.brightnessScalar = brightnessScalar; 369 | this.brightnessExponent = brightnessExponent; 370 | } 371 | setBlurScalar(blurScalar) { 372 | this.blurScalarFloat.setVal(merge_pass_1.wrapInValue(blurScalar)); 373 | this.blurScalar = merge_pass_1.wrapInValue(blurScalar); 374 | } 375 | setBrightnessScalar(brightnessScalar) { 376 | this.brightnessScalarFloat.setVal(merge_pass_1.wrapInValue(brightnessScalar)); 377 | this.brightnessScalar = merge_pass_1.wrapInValue(brightnessScalar); 378 | } 379 | setBrightnessExponent(brightnessExponent) { 380 | this.brightnessExponentFloat.setVal(merge_pass_1.wrapInValue(brightnessExponent)); 381 | this.brightnessExponent = merge_pass_1.wrapInValue(brightnessExponent); 382 | } 383 | } 384 | exports.Vignette = Vignette; 385 | function vignette(blurScalar = merge_pass_1.mut(3), brightnessScalar = merge_pass_1.mut(1.8), brightnessExponent = merge_pass_1.mut(1.8)) { 386 | return new Vignette(merge_pass_1.wrapInValue(blurScalar), merge_pass_1.wrapInValue(brightnessScalar), merge_pass_1.wrapInValue(brightnessExponent)); 387 | } 388 | exports.vignette = vignette; 389 | 390 | },{"@bandaloo/merge-pass":62}],11:[function(require,module,exports){ 391 | "use strict"; 392 | Object.defineProperty(exports, "__esModule", { value: true }); 393 | exports.CodeBuilder = exports.channelSamplerName = void 0; 394 | const expr_1 = require("./exprs/expr"); 395 | const webglprogramloop_1 = require("./webglprogramloop"); 396 | const settings_1 = require("./settings"); 397 | /** @ignore */ 398 | const FRAG_SET = ` gl_FragColor = texture2D(uSampler, gl_FragCoord.xy / uResolution);\n`; 399 | /** @ignore */ 400 | const SCENE_SET = `uniform sampler2D uSceneSampler;\n`; 401 | /** @ignore */ 402 | const TIME_SET = `uniform mediump float uTime;\n`; 403 | /** @ignore */ 404 | const MOUSE_SET = `uniform mediump vec2 uMouse;\n`; 405 | /** @ignore */ 406 | const COUNT_SET = `uniform int uCount;\n`; 407 | /** @ignore */ 408 | const BOILERPLATE = `#ifdef GL_ES 409 | precision mediump float; 410 | #endif 411 | 412 | uniform sampler2D uSampler; 413 | uniform mediump vec2 uResolution;\n`; 414 | /** 415 | * returns the string name of the sampler uniform for code generation purposes 416 | * @param num channel number to sample from 417 | */ 418 | function channelSamplerName(num) { 419 | // texture 2 sampler has number 0 (0 and 1 are used for back buffer and scene) 420 | return num === -1 ? "uSampler" : `uBufferSampler${num}`; 421 | } 422 | exports.channelSamplerName = channelSamplerName; 423 | /** 424 | * returns the string of the declaration of the sampler for code generation 425 | * purposes 426 | * @param num channel number to sample from 427 | */ 428 | function channelSamplerDeclaration(num) { 429 | return `uniform sampler2D ${channelSamplerName(num)};`; 430 | } 431 | /** class that manages generation and compilation of GLSL code */ 432 | class CodeBuilder { 433 | constructor(effectLoop) { 434 | this.calls = []; 435 | this.externalFuncs = new Set(); 436 | this.uniformDeclarations = new Set(); 437 | this.counter = 0; 438 | this.baseLoop = effectLoop; 439 | const buildInfo = { 440 | uniformTypes: {}, 441 | externalFuncs: new Set(), 442 | exprs: [], 443 | // update me on change to needs 444 | needs: { 445 | centerSample: false, 446 | neighborSample: false, 447 | sceneBuffer: false, 448 | timeUniform: false, 449 | mouseUniform: false, 450 | passCount: false, 451 | extraBuffers: new Set(), 452 | }, 453 | }; 454 | this.addEffectLoop(effectLoop, 1, buildInfo); 455 | // add all the types to uniform declarations from the `BuildInfo` instance 456 | for (const name in buildInfo.uniformTypes) { 457 | const typeName = buildInfo.uniformTypes[name]; 458 | this.uniformDeclarations.add(`uniform mediump ${typeName} ${name};`); 459 | } 460 | // add all external functions from the `BuildInfo` instance 461 | buildInfo.externalFuncs.forEach((func) => this.externalFuncs.add(func)); 462 | this.totalNeeds = buildInfo.needs; 463 | this.exprs = buildInfo.exprs; 464 | } 465 | addEffectLoop(effectLoop, indentLevel, buildInfo, topLevel = true) { 466 | const needsLoop = !topLevel && effectLoop.loopInfo.num > 1; 467 | if (needsLoop) { 468 | const iName = "i" + this.counter; 469 | indentLevel++; 470 | const forStart = " ".repeat(indentLevel - 1) + 471 | `for (int ${iName} = 0; ${iName} < ${effectLoop.loopInfo.num}; ${iName}++) {`; 472 | this.calls.push(forStart); 473 | } 474 | for (const e of effectLoop.effects) { 475 | if (e instanceof expr_1.Expr) { 476 | e.parse(buildInfo); 477 | this.calls.push(" ".repeat(indentLevel) + "gl_FragColor = " + e.sourceCode + ";"); 478 | this.counter++; 479 | } 480 | else { 481 | this.addEffectLoop(e, indentLevel, buildInfo, false); 482 | } 483 | } 484 | if (needsLoop) { 485 | this.calls.push(" ".repeat(indentLevel - 1) + "}"); 486 | } 487 | } 488 | /** generate the code and compile the program into a loop */ 489 | compileProgram(gl, vShader, uniformLocs, shaders = []) { 490 | // set up the fragment shader 491 | const fShader = gl.createShader(gl.FRAGMENT_SHADER); 492 | if (fShader === null) { 493 | throw new Error("problem creating fragment shader"); 494 | } 495 | const fullCode = BOILERPLATE + 496 | (this.totalNeeds.sceneBuffer ? SCENE_SET : "") + 497 | (this.totalNeeds.timeUniform ? TIME_SET : "") + 498 | (this.totalNeeds.mouseUniform ? MOUSE_SET : "") + 499 | (this.totalNeeds.passCount ? COUNT_SET : "") + 500 | Array.from(this.totalNeeds.extraBuffers) 501 | .map((n) => channelSamplerDeclaration(n)) 502 | .join("\n") + 503 | "\n" + 504 | [...this.uniformDeclarations].join("\n") + 505 | "\n" + 506 | [...this.externalFuncs].join("\n") + 507 | "\n" + 508 | "void main() {\n" + 509 | (this.totalNeeds.centerSample ? FRAG_SET : "") + 510 | this.calls.join("\n") + 511 | "\n}"; 512 | if (settings_1.settings.verbosity > 0) 513 | console.log(fullCode); 514 | gl.shaderSource(fShader, fullCode); 515 | gl.compileShader(fShader); 516 | // set up the program 517 | const program = gl.createProgram(); 518 | if (program === null) { 519 | throw new Error("problem creating program"); 520 | } 521 | gl.attachShader(program, vShader); 522 | gl.attachShader(program, fShader); 523 | shaders.push(fShader); 524 | const shaderLog = (name, shader) => { 525 | const output = gl.getShaderInfoLog(shader); 526 | if (output) 527 | console.log(`${name} shader info log\n${output}`); 528 | }; 529 | shaderLog("vertex", vShader); 530 | shaderLog("fragment", fShader); 531 | gl.linkProgram(program); 532 | // we need to use the program here so we can get uniform locations 533 | gl.useProgram(program); 534 | // find all uniform locations and add them to the dictionary 535 | for (const expr of this.exprs) { 536 | for (const name in expr.uniformValChangeMap) { 537 | const location = gl.getUniformLocation(program, name); 538 | if (location === null) { 539 | throw new Error("couldn't find uniform " + name); 540 | } 541 | // TODO enforce unique names in the same program 542 | if (uniformLocs[name] === undefined) { 543 | uniformLocs[name] = { locs: [], counter: 0 }; 544 | } 545 | // assign the name to the location 546 | uniformLocs[name].locs.push(location); 547 | } 548 | } 549 | // set the uniform resolution (every program has this uniform) 550 | const uResolution = gl.getUniformLocation(program, "uResolution"); 551 | gl.uniform2f(uResolution, gl.drawingBufferWidth, gl.drawingBufferHeight); 552 | if (this.totalNeeds.sceneBuffer) { 553 | // TODO allow for texture options for scene texture 554 | const location = gl.getUniformLocation(program, "uSceneSampler"); 555 | // put the scene buffer in texture 1 (0 is used for the backbuffer) 556 | gl.uniform1i(location, 1 + settings_1.settings.offset); 557 | } 558 | // set all sampler uniforms 559 | for (const b of this.totalNeeds.extraBuffers) { 560 | const location = gl.getUniformLocation(program, channelSamplerName(b)); 561 | // offset the texture location by 2 (0 and 1 are used for scene and original) 562 | gl.uniform1i(location, b + 2 + settings_1.settings.offset); 563 | } 564 | // set the default sampler if there is an offset 565 | if (settings_1.settings.offset !== 0) { 566 | const location = gl.getUniformLocation(program, "uSampler"); 567 | gl.uniform1i(location, settings_1.settings.offset); 568 | } 569 | // TODO do we need to do this every time? 570 | // get attribute 571 | const position = gl.getAttribLocation(program, "aPosition"); 572 | // enable the attribute 573 | gl.enableVertexAttribArray(position); 574 | // points to the vertices in the last bound array buffer 575 | gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0); 576 | return new webglprogramloop_1.WebGLProgramLoop(new webglprogramloop_1.WebGLProgramLeaf(program, this.totalNeeds, this.exprs), this.baseLoop.loopInfo, gl); 577 | } 578 | } 579 | exports.CodeBuilder = CodeBuilder; 580 | 581 | },{"./exprs/expr":25,"./settings":64,"./webglprogramloop":66}],12:[function(require,module,exports){ 582 | "use strict"; 583 | Object.defineProperty(exports, "__esModule", { value: true }); 584 | exports.a1 = exports.Arity1HomogenousExpr = void 0; 585 | const expr_1 = require("./expr"); 586 | /** @ignore */ 587 | function genArity1SourceList(name, val) { 588 | return { 589 | sections: [name + "(", ")"], 590 | values: [val], 591 | }; 592 | } 593 | /** arity 1 homogenous function expression */ 594 | class Arity1HomogenousExpr extends expr_1.Operator { 595 | constructor(val, operation) { 596 | super(val, genArity1SourceList(operation, val), ["uVal"]); 597 | this.val = val; 598 | } 599 | /** set the value being passed into the arity 1 homogenous function */ 600 | setVal(val) { 601 | this.setUniform("uVal" + this.id, val); 602 | this.val = expr_1.wrapInValue(val); 603 | } 604 | } 605 | exports.Arity1HomogenousExpr = Arity1HomogenousExpr; 606 | /** 607 | * built-in functions that take in one `genType x` and return a `genType x` 608 | * @param name function name (see [[Arity1HomogenousName]] for valid function names) 609 | * @param val the `genType x` argument 610 | */ 611 | function a1(name, val) { 612 | return new Arity1HomogenousExpr(expr_1.wrapInValue(val), name); 613 | } 614 | exports.a1 = a1; 615 | 616 | },{"./expr":25}],13:[function(require,module,exports){ 617 | "use strict"; 618 | Object.defineProperty(exports, "__esModule", { value: true }); 619 | exports.a2 = exports.Arity2HomogenousExpr = void 0; 620 | const expr_1 = require("./expr"); 621 | // note: glsl has atan(y/x) as well as atan(y, x) 622 | /** @ignore */ 623 | function genArity1SourceList(name, val1, val2) { 624 | return { 625 | sections: [name + "(", ",", ")"], 626 | values: [val1, val2], 627 | }; 628 | } 629 | /** arity 2 homogenous function expression */ 630 | class Arity2HomogenousExpr extends expr_1.Operator { 631 | constructor(name, val1, val2) { 632 | super(val1, genArity1SourceList(name, val1, val2), ["uVal1", "uVal2"]); 633 | this.val1 = val1; 634 | this.val2 = val2; 635 | } 636 | /** set the first value being passed into the arity 2 homogenous function */ 637 | setFirstVal(val1) { 638 | this.setUniform("uVal1" + this.id, val1); 639 | this.val1 = expr_1.wrapInValue(val1); 640 | } 641 | /** set the second value being passed into the arity 2 homogenous function */ 642 | setSecondVal(val2) { 643 | this.setUniform("uVal2" + this.id, val2); 644 | this.val2 = expr_1.wrapInValue(val2); 645 | } 646 | } 647 | exports.Arity2HomogenousExpr = Arity2HomogenousExpr; 648 | // implementation 649 | /** 650 | * built-in functions that take in two `genType x` arguments and return a `genType x` 651 | * @param name function name (see [[Arity2HomogenousName]] for valid function names) 652 | * @param val1 the first `genType x` argument 653 | * @param val2 the second `genType x` argument 654 | */ 655 | function a2(name, val1, val2) { 656 | return new Arity2HomogenousExpr(name, expr_1.wrapInValue(val1), expr_1.wrapInValue(val2)); 657 | } 658 | exports.a2 = a2; 659 | 660 | },{"./expr":25}],14:[function(require,module,exports){ 661 | "use strict"; 662 | Object.defineProperty(exports, "__esModule", { value: true }); 663 | exports.bloom = exports.BloomLoop = void 0; 664 | const mergepass_1 = require("../mergepass"); 665 | const arity2_1 = require("./arity2"); 666 | const blurexpr_1 = require("./blurexpr"); 667 | const brightnessexpr_1 = require("./brightnessexpr"); 668 | const channelsampleexpr_1 = require("./channelsampleexpr"); 669 | const contrastexpr_1 = require("./contrastexpr"); 670 | const expr_1 = require("./expr"); 671 | const fragcolorexpr_1 = require("./fragcolorexpr"); 672 | const opexpr_1 = require("./opexpr"); 673 | const vecexprs_1 = require("./vecexprs"); 674 | // TODO bloom uses `input` so it has to be the first 675 | // TODO maybe a way to update the scene buffer? 676 | /** bloom loop */ 677 | class BloomLoop extends mergepass_1.EffectLoop { 678 | constructor(threshold = expr_1.float(expr_1.mut(0.4)), horizontal = expr_1.float(expr_1.mut(1)), vertical = expr_1.float(expr_1.mut(1)), boost = expr_1.float(expr_1.mut(1.3)), samplerNum = 1, taps = 9, reps = 3) { 679 | const bright = expr_1.cfloat(expr_1.tag `((${channelsampleexpr_1.channel(samplerNum)}.r + ${channelsampleexpr_1.channel(samplerNum)}.g + ${channelsampleexpr_1.channel(samplerNum)}.b) / 3.)`); 680 | const step = arity2_1.a2("step", bright, threshold); 681 | const col = expr_1.cvec4(expr_1.tag `vec4(${channelsampleexpr_1.channel(samplerNum)}.rgb * (1. - ${step}), 1.)`); 682 | const list = [ 683 | mergepass_1.loop([col]).target(samplerNum), 684 | mergepass_1.loop([ 685 | blurexpr_1.gauss(vecexprs_1.vec2(horizontal, 0), taps), 686 | blurexpr_1.gauss(vecexprs_1.vec2(0, vertical), taps), 687 | brightnessexpr_1.brightness(0.1), 688 | contrastexpr_1.contrast(boost), 689 | ], reps).target(samplerNum), 690 | opexpr_1.op(fragcolorexpr_1.fcolor(), "+", channelsampleexpr_1.channel(samplerNum)), 691 | ]; 692 | super(list, { num: 1 }); 693 | this.threshold = threshold; 694 | this.horizontal = horizontal; 695 | this.vertical = vertical; 696 | this.boost = boost; 697 | } 698 | /** 699 | * set the horizontal stretch of the blur effect (no greater than 1 for best 700 | * effect) 701 | */ 702 | setHorizontal(num) { 703 | if (!(this.horizontal instanceof expr_1.BasicFloat)) 704 | throw new Error("horizontal expression not basic float"); 705 | this.horizontal.setVal(num); 706 | } 707 | /** 708 | * set the vertical stretch of the blur effect (no greater than 1 for best 709 | * effect) 710 | */ 711 | setVertical(num) { 712 | if (!(this.vertical instanceof expr_1.BasicFloat)) 713 | throw new Error("vertical expression not basic float"); 714 | this.vertical.setVal(num); 715 | } 716 | /** set the treshold */ 717 | setThreshold(num) { 718 | if (!(this.threshold instanceof expr_1.BasicFloat)) 719 | throw new Error("threshold expression not basic float"); 720 | this.threshold.setVal(num); 721 | } 722 | /** set the contrast boost */ 723 | setBoost(num) { 724 | if (!(this.boost instanceof expr_1.BasicFloat)) 725 | throw new Error("boost expression not basic float"); 726 | this.boost.setVal(num); 727 | } 728 | } 729 | exports.BloomLoop = BloomLoop; 730 | /** 731 | * creates a bloom loop 732 | * @param threshold values below this brightness don't get blurred (0.4 is 733 | * about reasonable, which is also the default) 734 | * @param horizontal how much to blur vertically (defaults to 1 pixel) 735 | * @param vertical how much to blur horizontally (defaults to 1 pixel) 736 | * @param taps how many taps for the blur (defaults to 9) 737 | * @param reps how many times to loop the blur (defaults to 3) 738 | */ 739 | function bloom(threshold, horizontal, vertical, boost, samplerNum, taps, reps) { 740 | return new BloomLoop(expr_1.wrapInValue(threshold), expr_1.wrapInValue(horizontal), expr_1.wrapInValue(vertical), expr_1.wrapInValue(boost), samplerNum, taps, reps); 741 | } 742 | exports.bloom = bloom; 743 | 744 | },{"../mergepass":63,"./arity2":13,"./blurexpr":16,"./brightnessexpr":17,"./channelsampleexpr":19,"./contrastexpr":20,"./expr":25,"./fragcolorexpr":26,"./opexpr":43,"./vecexprs":59}],15:[function(require,module,exports){ 745 | "use strict"; 746 | Object.defineProperty(exports, "__esModule", { value: true }); 747 | exports.blur2d = exports.Blur2dLoop = void 0; 748 | const mergepass_1 = require("../mergepass"); 749 | const blurexpr_1 = require("./blurexpr"); 750 | const expr_1 = require("./expr"); 751 | const vecexprs_1 = require("./vecexprs"); 752 | /** 2D blur loop */ 753 | class Blur2dLoop extends mergepass_1.EffectLoop { 754 | constructor(horizontal = expr_1.float(expr_1.mut(1)), vertical = expr_1.float(expr_1.mut(1)), reps = 2, taps, samplerNum) { 755 | const side = blurexpr_1.gauss(vecexprs_1.vec2(horizontal, 0), taps, samplerNum); 756 | const up = blurexpr_1.gauss(vecexprs_1.vec2(0, vertical), taps, samplerNum); 757 | super([side, up], { num: reps }); 758 | this.horizontal = horizontal; 759 | this.vertical = vertical; 760 | } 761 | /** 762 | * set the horizontal stretch of the blur effect (no greater than 1 for best 763 | * effect) 764 | */ 765 | setHorizontal(num) { 766 | if (!(this.horizontal instanceof expr_1.BasicFloat)) 767 | throw new Error("horizontal expression not basic float"); 768 | this.horizontal.setVal(num); 769 | } 770 | /** 771 | * set the vertical stretch of the blur effect (no greater than 1 for best 772 | * effect) 773 | */ 774 | setVertical(num) { 775 | if (!(this.vertical instanceof expr_1.BasicFloat)) 776 | throw new Error("vertical expression not basic float"); 777 | this.vertical.setVal(num); 778 | } 779 | } 780 | exports.Blur2dLoop = Blur2dLoop; 781 | /** 782 | * creates a loop that runs a horizontal, then vertical gaussian blur (anything 783 | * more than 1 pixel in the horizontal or vertical direction will create a 784 | * ghosting effect, which is usually not desirable) 785 | * @param horizontalExpr float for the horizontal blur (1 pixel default) 786 | * @param verticalExpr float for the vertical blur (1 pixel default) 787 | * @param reps how many passes (defaults to 2) 788 | * @param taps how many taps (defaults to 5) 789 | * @param samplerNum change if you want to sample from a different channel and 790 | * the outer loop has a different target 791 | */ 792 | function blur2d(horizontalExpr, verticalExpr, reps, taps, samplerNum) { 793 | return new Blur2dLoop(expr_1.wrapInValue(horizontalExpr), expr_1.wrapInValue(verticalExpr), reps, taps, samplerNum); 794 | } 795 | exports.blur2d = blur2d; 796 | 797 | },{"../mergepass":63,"./blurexpr":16,"./expr":25,"./vecexprs":59}],16:[function(require,module,exports){ 798 | "use strict"; 799 | Object.defineProperty(exports, "__esModule", { value: true }); 800 | exports.gauss = exports.BlurExpr = void 0; 801 | const glslfunctions_1 = require("../glslfunctions"); 802 | const expr_1 = require("./expr"); 803 | /** @ignore */ 804 | function genBlurSource(direction, taps) { 805 | return { 806 | sections: [`gauss${taps}(`, ")"], 807 | values: [direction], 808 | }; 809 | } 810 | /** @ignore */ 811 | function tapsToFuncSource(taps) { 812 | switch (taps) { 813 | case 5: 814 | return glslfunctions_1.glslFuncs.gauss5; 815 | case 9: 816 | return glslfunctions_1.glslFuncs.gauss9; 817 | case 13: 818 | return glslfunctions_1.glslFuncs.gauss13; 819 | } 820 | } 821 | /** gaussian blur expression */ 822 | class BlurExpr extends expr_1.ExprVec4 { 823 | constructor(direction, taps = 5, samplerNum) { 824 | // this is already guaranteed by typescript, but creates helpful error for 825 | // use in gibber or anyone just using javascript 826 | if (![5, 9, 13].includes(taps)) { 827 | throw new Error("taps for gauss blur can only be 5, 9 or 13"); 828 | } 829 | super(genBlurSource(direction, taps), ["uDirection"]); 830 | this.direction = direction; 831 | this.externalFuncs = [tapsToFuncSource(taps)]; 832 | this.brandExprWithChannel(0, samplerNum); 833 | } 834 | /** set the blur direction (keep magnitude no greater than 1 for best effect) */ 835 | setDirection(direction) { 836 | this.setUniform("uDirection" + this.id, direction); 837 | this.direction = direction; 838 | } 839 | } 840 | exports.BlurExpr = BlurExpr; 841 | /** 842 | * creates expression that performs one pass of a gaussian blur 843 | * @param direction direction to blur (keep magnitude less than or equal to 1 844 | * for best effect) 845 | * @param taps number of taps (defaults to 5) 846 | * @param samplerNum which channel to sample from (default 0) 847 | */ 848 | function gauss(direction, taps = 5, samplerNum) { 849 | return new BlurExpr(direction, taps, samplerNum); 850 | } 851 | exports.gauss = gauss; 852 | 853 | },{"../glslfunctions":61,"./expr":25}],17:[function(require,module,exports){ 854 | "use strict"; 855 | Object.defineProperty(exports, "__esModule", { value: true }); 856 | exports.brightness = exports.Brightness = void 0; 857 | const glslfunctions_1 = require("../glslfunctions"); 858 | const expr_1 = require("./expr"); 859 | const fragcolorexpr_1 = require("./fragcolorexpr"); 860 | /** brightness expression */ 861 | class Brightness extends expr_1.ExprVec4 { 862 | constructor(brightness, col = fragcolorexpr_1.fcolor()) { 863 | super(expr_1.tag `brightness(${brightness}, ${col})`, ["uBrightness", "uColor"]); 864 | this.brightness = brightness; 865 | this.externalFuncs = [glslfunctions_1.glslFuncs.brightness]; 866 | } 867 | /** set the brightness (should probably be between -1 and 1) */ 868 | setBrightness(brightness) { 869 | this.setUniform("uBrightness" + this.id, brightness); 870 | this.brightness = expr_1.wrapInValue(brightness); 871 | } 872 | } 873 | exports.Brightness = Brightness; 874 | /** 875 | * changes the brightness of a color 876 | * @param val float for how much to change the brightness by (should probably be 877 | * between -1 and 1) 878 | * @param col the color to increase the brightness of (defaults to current 879 | * fragment color) 880 | */ 881 | function brightness(val, col) { 882 | return new Brightness(expr_1.wrapInValue(val), col); 883 | } 884 | exports.brightness = brightness; 885 | 886 | },{"../glslfunctions":61,"./expr":25,"./fragcolorexpr":26}],18:[function(require,module,exports){ 887 | "use strict"; 888 | Object.defineProperty(exports, "__esModule", { value: true }); 889 | exports.changecomp = exports.ChangeCompExpr = void 0; 890 | const expr_1 = require("./expr"); 891 | const getcompexpr_1 = require("./getcompexpr"); 892 | /** @ignore */ 893 | function getChangeFunc(typ, id, setter, comps, op = "") { 894 | return `${typ} changecomp_${id}(${typ} col, ${setter.typeString()} setter) { 895 | col.${comps} ${op}= setter; 896 | return col; 897 | }`; 898 | } 899 | /** 900 | * throws a runtime error if component access is not valid, and disallows 901 | * duplicate components because duplicate components can not be in a left 902 | * expression. (for example `v.xyx = vec3(1., 2., 3.)` is illegal, but `v1.xyz 903 | * = v2.xyx` is legal.) also checks for type errors such as `v1.xy = vec3(1., 904 | * 2., 3.)`; the right hand side can only be a `vec2` if only two components 905 | * are supplied 906 | * @param comps component string 907 | * @param setter how the components are being changed 908 | * @param vec the vector where components are being accessed 909 | */ 910 | function checkChangeComponents(comps, setter, vec) { 911 | // setter has different length than components 912 | if (comps.length !== getcompexpr_1.typeStringToLength(setter.typeString())) { 913 | throw new Error("components length must be equal to the target float/vec"); 914 | } 915 | // duplicate components 916 | if (duplicateComponents(comps)) { 917 | throw new Error("duplicate components not allowed on left side"); 918 | } 919 | // legal components 920 | getcompexpr_1.checkLegalComponents(comps, vec); 921 | } 922 | /** @ignore */ 923 | function duplicateComponents(comps) { 924 | return new Set(comps.split("")).size !== comps.length; 925 | } 926 | /** change component expression */ 927 | class ChangeCompExpr extends expr_1.Operator { 928 | constructor(vec, setter, comps, op) { 929 | checkChangeComponents(comps, setter, vec); 930 | // part of name of custom function 931 | const operation = op === "+" 932 | ? "plus" 933 | : op === "-" 934 | ? "minus" 935 | : op === "*" 936 | ? "mult" 937 | : op === "/" 938 | ? "div" 939 | : "assign"; 940 | const suffix = `${vec.typeString()}_${setter.typeString()}_${comps}_${operation}`; 941 | super(vec, { sections: [`changecomp_${suffix}(`, ", ", ")"], values: [vec, setter] }, ["uOriginal", "uNew"]); 942 | this.originalVec = vec; 943 | this.newVal = setter; 944 | this.externalFuncs = [ 945 | getChangeFunc(vec.typeString(), suffix, setter, comps, op), 946 | ]; 947 | } 948 | /** set the original vector */ 949 | setOriginal(originalVec) { 950 | this.setUniform("uOriginal" + this.id, originalVec); 951 | this.originalVec = originalVec; 952 | } 953 | /** set the neww vector */ 954 | setNew(newVal) { 955 | this.setUniform("uNew" + this.id, newVal); 956 | this.newVal = expr_1.wrapInValue(newVal); 957 | } 958 | } 959 | exports.ChangeCompExpr = ChangeCompExpr; 960 | /** 961 | * change the components of a vector 962 | * @param vec the vector to augment components of 963 | * @param setter the vector (or float, if only one component is changed) for 964 | * how to change the components 965 | * @param comps string representing the components to change (e.g. `"xy"` or 966 | * `"r"` or `"stpq"`.) 967 | * @param op optionally perform an operation on the original component 968 | * (defaults to no operation, just assigning that component to a new value) 969 | */ 970 | function changecomp(vec, setter, comps, op) { 971 | return new ChangeCompExpr(vec, expr_1.wrapInValue(setter), comps, op); 972 | } 973 | exports.changecomp = changecomp; 974 | 975 | },{"./expr":25,"./getcompexpr":30}],19:[function(require,module,exports){ 976 | "use strict"; 977 | Object.defineProperty(exports, "__esModule", { value: true }); 978 | exports.channel = exports.ChannelSampleExpr = void 0; 979 | const codebuilder_1 = require("../codebuilder"); 980 | const expr_1 = require("./expr"); 981 | const normfragcoordexpr_1 = require("./normfragcoordexpr"); 982 | const glslfunctions_1 = require("../glslfunctions"); 983 | /** @ignore */ 984 | function genChannelSampleSource(buf, coord) { 985 | return { 986 | sections: ["channel(", `, ${codebuilder_1.channelSamplerName(buf)})`], 987 | values: [coord], 988 | }; 989 | } 990 | // TODO create a way to sample but not clamp by region 991 | /** channel sample expression */ 992 | class ChannelSampleExpr extends expr_1.ExprVec4 { 993 | constructor(buf, coord = normfragcoordexpr_1.pos()) { 994 | super(genChannelSampleSource(buf, coord), ["uVec"]); 995 | this.coord = coord; 996 | this.externalFuncs = [glslfunctions_1.glslFuncs.channel]; 997 | if (buf !== -1) 998 | this.needs.extraBuffers = new Set([buf]); 999 | else 1000 | this.needs.neighborSample = true; 1001 | } 1002 | setCoord(coord) { 1003 | this.setUniform("uVec", coord); 1004 | this.coord = coord; 1005 | } 1006 | } 1007 | exports.ChannelSampleExpr = ChannelSampleExpr; 1008 | /** 1009 | * creates an expression that samples from one of the user-defined channels. 1010 | * don't sample from the same channel that you are using [[target]] on in a 1011 | * loop, just use [[fcolor]] 1012 | * @param channel which channel to sample from 1013 | * @param vec where to sample the channel texture (defaults to the normalized 1014 | * frag coord) 1015 | */ 1016 | function channel(channel, vec) { 1017 | return new ChannelSampleExpr(channel, vec); 1018 | } 1019 | exports.channel = channel; 1020 | 1021 | },{"../codebuilder":11,"../glslfunctions":61,"./expr":25,"./normfragcoordexpr":41}],20:[function(require,module,exports){ 1022 | "use strict"; 1023 | Object.defineProperty(exports, "__esModule", { value: true }); 1024 | exports.contrast = exports.ContrastExpr = void 0; 1025 | const glslfunctions_1 = require("../glslfunctions"); 1026 | const expr_1 = require("./expr"); 1027 | const fragcolorexpr_1 = require("./fragcolorexpr"); 1028 | class ContrastExpr extends expr_1.ExprVec4 { 1029 | constructor(contrast, col = fragcolorexpr_1.fcolor()) { 1030 | super(expr_1.tag `contrast(${contrast}, ${col})`, ["uVal", "uCol"]); 1031 | this.contrast = contrast; 1032 | this.externalFuncs = [glslfunctions_1.glslFuncs.contrast]; 1033 | } 1034 | /** sets the contrast */ 1035 | setContrast(contrast) { 1036 | this.setUniform("uContrast" + this.id, contrast); 1037 | this.contrast = expr_1.wrapInValue(contrast); 1038 | } 1039 | } 1040 | exports.ContrastExpr = ContrastExpr; 1041 | /** 1042 | * changes the contrast of a color 1043 | * @param val float for how much to change the contrast by (should probably be 1044 | * between -1 and 1) 1045 | * @param col the color to increase the contrast of (defaults to current 1046 | * fragment color) 1047 | */ 1048 | function contrast(val, col) { 1049 | return new ContrastExpr(expr_1.wrapInValue(val), col); 1050 | } 1051 | exports.contrast = contrast; 1052 | 1053 | },{"../glslfunctions":61,"./expr":25,"./fragcolorexpr":26}],21:[function(require,module,exports){ 1054 | "use strict"; 1055 | Object.defineProperty(exports, "__esModule", { value: true }); 1056 | exports.depth2occlusion = exports.DepthToOcclusionExpr = void 0; 1057 | const channelsampleexpr_1 = require("./channelsampleexpr"); 1058 | const expr_1 = require("./expr"); 1059 | const vecexprs_1 = require("./vecexprs"); 1060 | /** depth info to occlussion info expression */ 1061 | class DepthToOcclusionExpr extends expr_1.ExprVec4 { 1062 | constructor(depthCol = channelsampleexpr_1.channel(0), newCol = expr_1.mut(vecexprs_1.pvec4(1, 1, 1, 1)), threshold = expr_1.mut(expr_1.pfloat(0.01))) { 1063 | super(expr_1.tag `depth2occlusion(${depthCol}, ${newCol}, ${threshold})`, [ 1064 | "uDepth", 1065 | "uNewCol", 1066 | "uThreshold", 1067 | ]); 1068 | this.depthCol = depthCol; 1069 | this.newCol = newCol; 1070 | this.threshold = threshold; 1071 | } 1072 | setDepthColor(depthCol) { 1073 | this.setUniform("uDepth" + this.id, depthCol); 1074 | this.depthCol = depthCol; 1075 | } 1076 | setNewColor(newCol) { 1077 | this.setUniform("uNewCol" + this.id, newCol); 1078 | this.newCol = newCol; 1079 | } 1080 | setThreshold(threshold) { 1081 | this.setUniform("uThreshold" + this.id, threshold); 1082 | this.threshold = expr_1.wrapInValue(threshold); 1083 | } 1084 | } 1085 | exports.DepthToOcclusionExpr = DepthToOcclusionExpr; 1086 | /** 1087 | * converts a `1 / distance` depth texture to an occlusion texture, with all 1088 | * occluded geometry being rendered as black 1089 | * @param depthCol the color representing the inverse depth (defaults to 1090 | * sampling from channel 0) 1091 | * @param newCol the color to replace unoccluded areas by (defaults to white 1092 | * and is mutable by default) 1093 | * @param threshold values below this are not occluded (set to something low, 1094 | * like 0.1 or lower; defaults to 0.01 and is mutable by default) 1095 | */ 1096 | function depth2occlusion(depthCol, newCol, threshold) { 1097 | return new DepthToOcclusionExpr(depthCol, newCol, expr_1.wrapInValue(threshold)); 1098 | } 1099 | exports.depth2occlusion = depth2occlusion; 1100 | 1101 | },{"./channelsampleexpr":19,"./expr":25,"./vecexprs":59}],22:[function(require,module,exports){ 1102 | "use strict"; 1103 | Object.defineProperty(exports, "__esModule", { value: true }); 1104 | exports.dof = exports.DoFLoop = void 0; 1105 | const mergepass_1 = require("../mergepass"); 1106 | const arity2_1 = require("./arity2"); 1107 | const blurexpr_1 = require("./blurexpr"); 1108 | const channelsampleexpr_1 = require("./channelsampleexpr"); 1109 | const expr_1 = require("./expr"); 1110 | const gaussianexpr_1 = require("./gaussianexpr"); 1111 | const getcompexpr_1 = require("./getcompexpr"); 1112 | const opexpr_1 = require("./opexpr"); 1113 | const vecexprs_1 = require("./vecexprs"); 1114 | class DoFLoop extends mergepass_1.EffectLoop { 1115 | constructor(depth = expr_1.mut(expr_1.pfloat(0.3)), rad = expr_1.mut(expr_1.pfloat(0.01)), depthInfo = getcompexpr_1.getcomp(channelsampleexpr_1.channel(0), "r"), reps = 2, taps = 13) { 1116 | let guassianExpr = gaussianexpr_1.gaussian(depthInfo, depth, rad); 1117 | const side = blurexpr_1.gauss(vecexprs_1.vec2(arity2_1.a2("pow", opexpr_1.op(1, "-", guassianExpr), 4), 0), taps); 1118 | const up = blurexpr_1.gauss(vecexprs_1.vec2(0, arity2_1.a2("pow", opexpr_1.op(1, "-", guassianExpr), 4)), taps); 1119 | super([side, up], { num: reps }); 1120 | this.gaussian = guassianExpr; 1121 | } 1122 | setDepth(depth) { 1123 | // this translates the gaussian curve to the side 1124 | this.gaussian.setA(depth); 1125 | } 1126 | setRadius(radius) { 1127 | // this scales the gaussian curve to focus on a larger band of depth 1128 | this.gaussian.setB(radius); 1129 | } 1130 | } 1131 | exports.DoFLoop = DoFLoop; 1132 | /** 1133 | * creates depth of field expression; all values are mutable by default 1134 | * @param depth float for what inverse depth to focus on (1 on top of the 1135 | * camera; 0 is infinity) 1136 | * @param rad float for how deep the band of in-focus geometry is (a value 1137 | * between 0.01 and 0.1 is reasonable) 1138 | * @param depthInfo float the expression that represents the inverse depth 1139 | * (defaults to sampling the red component from channel 0) 1140 | * @param reps how many times to repeat the gaussian blur 1141 | */ 1142 | function dof(depth, rad, depthInfo, reps) { 1143 | return new DoFLoop(expr_1.wrapInValue(depth), expr_1.wrapInValue(rad), expr_1.wrapInValue(depthInfo), reps); 1144 | } 1145 | exports.dof = dof; 1146 | 1147 | },{"../mergepass":63,"./arity2":13,"./blurexpr":16,"./channelsampleexpr":19,"./expr":25,"./gaussianexpr":29,"./getcompexpr":30,"./opexpr":43,"./vecexprs":59}],23:[function(require,module,exports){ 1148 | "use strict"; 1149 | Object.defineProperty(exports, "__esModule", { value: true }); 1150 | exports.edgecolor = exports.EdgeColorExpr = void 0; 1151 | const arity2_1 = require("./arity2"); 1152 | const expr_1 = require("./expr"); 1153 | const fragcolorexpr_1 = require("./fragcolorexpr"); 1154 | const monochromeexpr_1 = require("./monochromeexpr"); 1155 | const sobelexpr_1 = require("./sobelexpr"); 1156 | const vecexprs_1 = require("./vecexprs"); 1157 | /** edge color expression */ 1158 | class EdgeColorExpr extends expr_1.WrappedExpr { 1159 | constructor(color, samplerNum, stepped = true) { 1160 | const expr = stepped 1161 | ? expr_1.cvec4(expr_1.tag `mix(${color}, ${fragcolorexpr_1.fcolor()}, ${monochromeexpr_1.monochrome(arity2_1.a2("step", vecexprs_1.vec4(0.5, 0.5, 0.5, 0.0), sobelexpr_1.sobel(samplerNum)))})`) 1162 | : expr_1.cvec4(expr_1.tag `mix(${color}, ${fragcolorexpr_1.fcolor()}, ${monochromeexpr_1.monochrome(sobelexpr_1.sobel(samplerNum))})`); 1163 | super(expr); 1164 | this.color = color; 1165 | this.expr = expr; 1166 | } 1167 | setColor(color) { 1168 | this.expr.setUniform("uCustomName0" + this.expr.id, color); 1169 | this.color = color; 1170 | } 1171 | } 1172 | exports.EdgeColorExpr = EdgeColorExpr; 1173 | /** 1174 | * creates a colored edge detection expression 1175 | * @param color what color to make the edge 1176 | * @param samplerNum where to sample from 1177 | * @param stepped whether to round the result of sobel edge detection (defaults 1178 | * to true) 1179 | */ 1180 | function edgecolor(color, samplerNum, stepped) { 1181 | return new EdgeColorExpr(color, samplerNum, stepped); 1182 | } 1183 | exports.edgecolor = edgecolor; 1184 | 1185 | },{"./arity2":13,"./expr":25,"./fragcolorexpr":26,"./monochromeexpr":36,"./sobelexpr":54,"./vecexprs":59}],24:[function(require,module,exports){ 1186 | "use strict"; 1187 | Object.defineProperty(exports, "__esModule", { value: true }); 1188 | exports.edge = exports.EdgeExpr = void 0; 1189 | const brightnessexpr_1 = require("./brightnessexpr"); 1190 | const expr_1 = require("./expr"); 1191 | const getcompexpr_1 = require("./getcompexpr"); 1192 | const invertexpr_1 = require("./invertexpr"); 1193 | const monochromeexpr_1 = require("./monochromeexpr"); 1194 | const opexpr_1 = require("./opexpr"); 1195 | const sobelexpr_1 = require("./sobelexpr"); 1196 | class EdgeExpr extends expr_1.WrappedExpr { 1197 | constructor(mult = expr_1.mut(-1.0), samplerNum) { 1198 | const operator = opexpr_1.op(getcompexpr_1.getcomp(invertexpr_1.invert(monochromeexpr_1.monochrome(sobelexpr_1.sobel(samplerNum))), "r"), "*", mult); 1199 | super(brightnessexpr_1.brightness(operator)); 1200 | this.mult = mult; 1201 | this.operator = operator; 1202 | } 1203 | setMult(mult) { 1204 | this.operator.setRight(mult); 1205 | this.mult = expr_1.wrapInValue(mult); 1206 | } 1207 | } 1208 | exports.EdgeExpr = EdgeExpr; 1209 | /** 1210 | * returns an expression highlights edges where they appear 1211 | * @param style `"dark"` for dark edges and `"light"` for light edges, or a 1212 | * custom number or expression (between -1 and 1) for a more gray style of edge 1213 | * @param samplerNum where to sample from 1214 | */ 1215 | function edge(style, samplerNum) { 1216 | const mult = style === "dark" ? -1 : style === "light" ? 1 : style; 1217 | return new EdgeExpr(expr_1.wrapInValue(mult), samplerNum); 1218 | } 1219 | exports.edge = edge; 1220 | 1221 | },{"./brightnessexpr":17,"./expr":25,"./getcompexpr":30,"./invertexpr":34,"./monochromeexpr":36,"./opexpr":43,"./sobelexpr":54}],25:[function(require,module,exports){ 1222 | "use strict"; 1223 | Object.defineProperty(exports, "__esModule", { value: true }); 1224 | exports.tag = exports.wrapInValue = exports.pfloat = exports.Operator = exports.WrappedExpr = exports.ExprVec4 = exports.ExprVec3 = exports.ExprVec2 = exports.float = exports.ExprFloat = exports.BasicFloat = exports.ExprVec = exports.BasicVec4 = exports.BasicVec3 = exports.BasicVec2 = exports.BasicVec = exports.PrimitiveVec4 = exports.PrimitiveVec3 = exports.PrimitiveVec2 = exports.PrimitiveVec = exports.PrimitiveFloat = exports.Primitive = exports.mut = exports.Mutable = exports.cvec4 = exports.cvec3 = exports.cvec2 = exports.cfloat = exports.Expr = void 0; 1225 | const mergepass_1 = require("../mergepass"); 1226 | const webglprogramloop_1 = require("../webglprogramloop"); 1227 | const utils_1 = require("../utils"); 1228 | /** 1229 | * adds a `.` after a number if needed (e.g converts `1` to `"1."` but leaves 1230 | * `1.2` as `"1.2"`) 1231 | * @param num number to convert 1232 | */ 1233 | function toGLSLFloatString(num) { 1234 | let str = "" + num; 1235 | if (!str.includes(".")) 1236 | str += "."; 1237 | return str; 1238 | } 1239 | class Expr { 1240 | constructor(sourceLists, defaultNames) { 1241 | // update me on change to needs 1242 | this.needs = { 1243 | neighborSample: false, 1244 | centerSample: false, 1245 | sceneBuffer: false, 1246 | timeUniform: false, 1247 | mouseUniform: false, 1248 | passCount: false, 1249 | extraBuffers: new Set(), 1250 | }; 1251 | this.uniformValChangeMap = {}; 1252 | this.defaultNameMap = {}; 1253 | this.externalFuncs = []; 1254 | this.sourceCode = ""; 1255 | this.funcIndex = 0; 1256 | this.regionBranded = false; 1257 | this.id = "_id_" + Expr.count; 1258 | Expr.count++; 1259 | if (sourceLists.sections.length - sourceLists.values.length !== 1) { 1260 | // this cannot happen if you use `tag` to destructure a template string 1261 | throw new Error("wrong lengths for source and values"); 1262 | } 1263 | if (sourceLists.values.length !== defaultNames.length) { 1264 | console.log(sourceLists); 1265 | console.log(defaultNames); 1266 | throw new Error("default names list length doesn't match values list length"); 1267 | } 1268 | this.sourceLists = sourceLists; 1269 | this.defaultNames = defaultNames; 1270 | } 1271 | applyUniforms(gl, uniformLocs) { 1272 | for (const name in this.uniformValChangeMap) { 1273 | const loc = uniformLocs[name]; 1274 | if (this.uniformValChangeMap[name].changed) { 1275 | //this.uniformValChangeMap[name].changed = false; 1276 | this.uniformValChangeMap[name].val.applyUniform(gl, loc.locs[loc.counter]); 1277 | } 1278 | // increment and reset the counter to wrap back around to first location 1279 | loc.counter++; 1280 | loc.counter %= loc.locs.length; 1281 | // once we have wrapped then we know all uniforms have been changed 1282 | if (loc.counter === 0) { 1283 | this.uniformValChangeMap[name].changed = false; 1284 | } 1285 | } 1286 | } 1287 | getSampleNum(mult = 1) { 1288 | return this.needs.neighborSample 1289 | ? mult 1290 | : this.sourceLists.values 1291 | .map((v) => v.getSampleNum()) 1292 | .reduce((acc, curr) => acc + curr, 0) > 0 1293 | ? mult 1294 | : 0; 1295 | } 1296 | /** 1297 | * set a uniform by name directly 1298 | * @param name uniform name in the source code 1299 | * @param newVal value to set the uniform to 1300 | */ 1301 | setUniform(name, newVal) { 1302 | var _a, _b; 1303 | newVal = wrapInValue(newVal); 1304 | const originalName = name; 1305 | if (typeof newVal === "number") { 1306 | newVal = wrapInValue(newVal); 1307 | } 1308 | if (!(newVal instanceof Primitive)) { 1309 | throw new Error("cannot set a non-primitive"); 1310 | } 1311 | // if name does not exist, try mapping default name to new name 1312 | if (((_a = this.uniformValChangeMap[name]) === null || _a === void 0 ? void 0 : _a.val) === undefined) { 1313 | name = this.defaultNameMap[name]; 1314 | } 1315 | const oldVal = (_b = this.uniformValChangeMap[name]) === null || _b === void 0 ? void 0 : _b.val; 1316 | if (oldVal === undefined) { 1317 | throw new Error("tried to set uniform " + 1318 | name + 1319 | " which doesn't exist. original name: " + 1320 | originalName); 1321 | } 1322 | if (oldVal.typeString() !== newVal.typeString()) { 1323 | throw new Error("tried to set uniform " + name + " to a new type"); 1324 | } 1325 | this.uniformValChangeMap[name].val = newVal; 1326 | this.uniformValChangeMap[name].changed = true; 1327 | } 1328 | /** 1329 | * parses this expression into a string, adding info as it recurses into 1330 | * nested expressions 1331 | */ 1332 | parse(buildInfo) { 1333 | this.sourceCode = ""; 1334 | buildInfo.exprs.push(this); 1335 | buildInfo.needs = webglprogramloop_1.updateNeeds(buildInfo.needs, this.needs); 1336 | // add each of the external funcs to the builder 1337 | this.externalFuncs.forEach((func) => buildInfo.externalFuncs.add(func)); 1338 | // put all of the values between all of the source sections 1339 | for (let i = 0; i < this.sourceLists.values.length; i++) { 1340 | this.sourceCode += 1341 | this.sourceLists.sections[i] + 1342 | this.sourceLists.values[i].parse(buildInfo, this.defaultNames[i], this); 1343 | } 1344 | // TODO does sourceCode have to be a member? 1345 | this.sourceCode += this.sourceLists.sections[this.sourceLists.sections.length - 1]; 1346 | return this.sourceCode; 1347 | } 1348 | addFuncs(funcs) { 1349 | this.externalFuncs.push(...funcs); 1350 | return this; 1351 | } 1352 | brandExprWithChannel(funcIndex, samplerNum) { 1353 | utils_1.brandWithChannel(this.sourceLists, this.externalFuncs, this.needs, funcIndex, samplerNum); 1354 | return this; 1355 | } 1356 | brandExprWithRegion(space) { 1357 | utils_1.brandWithRegion(this, this.funcIndex, space); 1358 | for (const v of this.sourceLists.values) { 1359 | v.brandExprWithRegion(space); 1360 | } 1361 | return this; 1362 | } 1363 | } 1364 | exports.Expr = Expr; 1365 | /** 1366 | * increments for each expression created; used to uniquely id each expression 1367 | */ 1368 | Expr.count = 0; 1369 | function genCustomNames(sourceLists) { 1370 | const names = []; 1371 | for (let i = 0; i < sourceLists.values.length; i++) { 1372 | names.push("uCustomName" + i); 1373 | } 1374 | return names; 1375 | } 1376 | /** create a custom float function (use with [[tag]]) */ 1377 | function cfloat(sourceLists, externalFuncs = []) { 1378 | return new ExprFloat(sourceLists, genCustomNames(sourceLists)).addFuncs(externalFuncs); 1379 | } 1380 | exports.cfloat = cfloat; 1381 | /** create a custom vec2 function (use with [[tag]]) */ 1382 | function cvec2(sourceLists, externalFuncs = []) { 1383 | return new ExprVec2(sourceLists, genCustomNames(sourceLists)).addFuncs(externalFuncs); 1384 | } 1385 | exports.cvec2 = cvec2; 1386 | /** create a custom vec3 function (use with [[tag]]) */ 1387 | function cvec3(sourceLists, externalFuncs = []) { 1388 | return new ExprVec3(sourceLists, genCustomNames(sourceLists)).addFuncs(externalFuncs); 1389 | } 1390 | exports.cvec3 = cvec3; 1391 | /** create a custom vec4 function (use with [[tag]]) */ 1392 | function cvec4(sourceLists, externalFuncs = []) { 1393 | return new ExprVec4(sourceLists, genCustomNames(sourceLists)).addFuncs(externalFuncs); 1394 | } 1395 | exports.cvec4 = cvec4; 1396 | class Mutable { 1397 | constructor(primitive, name) { 1398 | this.primitive = primitive; 1399 | this.name = name; 1400 | } 1401 | parse(buildInfo, defaultName, enc) { 1402 | if (enc === undefined) { 1403 | throw new Error("tried to put a mutable expression at the top level"); 1404 | } 1405 | // accept the default name if given no name 1406 | if (this.name === undefined) 1407 | this.name = defaultName + enc.id; 1408 | // set to true so they are set to their default values on first draw 1409 | buildInfo.uniformTypes[this.name] = this.primitive.typeString(); 1410 | // add the name mapping 1411 | enc.uniformValChangeMap[this.name] = { 1412 | val: this.primitive, 1413 | changed: true, 1414 | }; 1415 | // add the new type to the map 1416 | enc.defaultNameMap[defaultName + enc.id] = this.name; 1417 | return this.name; 1418 | } 1419 | applyUniform(gl, loc) { 1420 | this.primitive.applyUniform(gl, loc); 1421 | } 1422 | typeString() { 1423 | return this.primitive.typeString(); 1424 | } 1425 | getSampleNum() { 1426 | return 0; 1427 | } 1428 | brandExprWithRegion(space) { 1429 | return this; 1430 | } 1431 | } 1432 | exports.Mutable = Mutable; 1433 | /** 1434 | * makes a primitive value mutable. wrapping a [[PrimitiveVec]] or 1435 | * [[PrimitiveFloat]] in [[mut]] before passing it into an expression will 1436 | * allow you to use the setters on that expression to change those values at 1437 | * runtime 1438 | * @param val the primitive float or primitive vec to make mutable 1439 | * @param name the optional name for the uniform 1440 | */ 1441 | function mut(val, name) { 1442 | const primitive = typeof val === "number" ? wrapInValue(val) : val; 1443 | return new Mutable(primitive, name); 1444 | } 1445 | exports.mut = mut; 1446 | class Primitive { 1447 | parse() { 1448 | return this.toString(); 1449 | } 1450 | getSampleNum() { 1451 | return 0; 1452 | } 1453 | brandExprWithRegion(space) { 1454 | return this; 1455 | } 1456 | } 1457 | exports.Primitive = Primitive; 1458 | class PrimitiveFloat extends Primitive { 1459 | constructor(num) { 1460 | if (!isFinite(num)) 1461 | throw new Error("number not finite"); 1462 | super(); 1463 | this.value = num; 1464 | } 1465 | toString() { 1466 | let str = "" + this.value; 1467 | if (!str.includes(".")) 1468 | str += "."; 1469 | return str; 1470 | } 1471 | typeString() { 1472 | return "float"; 1473 | } 1474 | applyUniform(gl, loc) { 1475 | gl.uniform1f(loc, this.value); 1476 | } 1477 | } 1478 | exports.PrimitiveFloat = PrimitiveFloat; 1479 | class PrimitiveVec extends Primitive { 1480 | constructor(comps) { 1481 | super(); 1482 | this.values = comps; 1483 | } 1484 | typeString() { 1485 | return ("vec" + this.values.length); 1486 | } 1487 | toString() { 1488 | return `${this.typeString()}(${this.values 1489 | .map((n) => toGLSLFloatString(n)) 1490 | .join(", ")})`; 1491 | } 1492 | } 1493 | exports.PrimitiveVec = PrimitiveVec; 1494 | class PrimitiveVec2 extends PrimitiveVec { 1495 | applyUniform(gl, loc) { 1496 | gl.uniform2f(loc, this.values[0], this.values[1]); 1497 | } 1498 | } 1499 | exports.PrimitiveVec2 = PrimitiveVec2; 1500 | class PrimitiveVec3 extends PrimitiveVec { 1501 | applyUniform(gl, loc) { 1502 | gl.uniform3f(loc, this.values[0], this.values[1], this.values[2]); 1503 | } 1504 | } 1505 | exports.PrimitiveVec3 = PrimitiveVec3; 1506 | class PrimitiveVec4 extends PrimitiveVec { 1507 | applyUniform(gl, loc) { 1508 | gl.uniform4f(loc, this.values[0], this.values[1], this.values[2], this.values[3]); 1509 | } 1510 | } 1511 | exports.PrimitiveVec4 = PrimitiveVec4; 1512 | class BasicVec extends Expr { 1513 | constructor(sourceLists, defaultNames) { 1514 | super(sourceLists, defaultNames); 1515 | // this cast is fine as long as you only instantiate these with the 1516 | // shorthand version and not the constructor 1517 | const values = sourceLists.values; 1518 | this.values = values; 1519 | this.defaultNames = defaultNames; 1520 | } 1521 | typeString() { 1522 | return ("vec" + this.values.length); 1523 | } 1524 | /** sets a component of the vector */ 1525 | setComp(index, primitive) { 1526 | if (index < 0 || index >= this.values.length) { 1527 | throw new Error("out of bounds of setting component"); 1528 | } 1529 | this.setUniform(this.defaultNames[index] + this.id, wrapInValue(primitive)); 1530 | } 1531 | } 1532 | exports.BasicVec = BasicVec; 1533 | class BasicVec2 extends BasicVec { 1534 | constructor() { 1535 | super(...arguments); 1536 | this.bvec2 = undefined; // brand for nominal typing 1537 | } 1538 | } 1539 | exports.BasicVec2 = BasicVec2; 1540 | class BasicVec3 extends BasicVec { 1541 | constructor() { 1542 | super(...arguments); 1543 | this.bvec3 = undefined; // brand for nominal typing 1544 | } 1545 | } 1546 | exports.BasicVec3 = BasicVec3; 1547 | class BasicVec4 extends BasicVec { 1548 | constructor() { 1549 | super(...arguments); 1550 | this.bvec4 = undefined; // brand for nominal typing 1551 | } 1552 | } 1553 | exports.BasicVec4 = BasicVec4; 1554 | class ExprVec extends Expr { 1555 | constructor(sourceLists, defaultNames) { 1556 | super(sourceLists, defaultNames); 1557 | const values = sourceLists.values; 1558 | this.values = values; 1559 | this.defaultNames = defaultNames; 1560 | } 1561 | } 1562 | exports.ExprVec = ExprVec; 1563 | class BasicFloat extends Expr { 1564 | constructor(sourceLists, defaultNames) { 1565 | super(sourceLists, defaultNames); 1566 | this.float = undefined; // brand for nominal typing 1567 | } 1568 | setVal(primitive) { 1569 | this.setUniform("uFloat" + this.id, wrapInValue(primitive)); 1570 | } 1571 | typeString() { 1572 | return "float"; 1573 | } 1574 | } 1575 | exports.BasicFloat = BasicFloat; 1576 | class ExprFloat extends Expr { 1577 | constructor(sourceLists, defaultNames) { 1578 | super(sourceLists, defaultNames); 1579 | this.float = undefined; // brand for nominal typing 1580 | } 1581 | setVal(primitive) { 1582 | this.setUniform("uFloat" + this.id, wrapInValue(primitive)); 1583 | } 1584 | typeString() { 1585 | return "float"; 1586 | } 1587 | } 1588 | exports.ExprFloat = ExprFloat; 1589 | function float(value) { 1590 | if (typeof value === "number") 1591 | value = wrapInValue(value); 1592 | return new BasicFloat({ sections: ["", ""], values: [value] }, ["uFloat"]); 1593 | } 1594 | exports.float = float; 1595 | class ExprVec2 extends ExprVec { 1596 | constructor() { 1597 | super(...arguments); 1598 | this.vec2 = undefined; // brand for nominal typing 1599 | } 1600 | typeString() { 1601 | return "vec2"; 1602 | } 1603 | } 1604 | exports.ExprVec2 = ExprVec2; 1605 | class ExprVec3 extends ExprVec { 1606 | constructor() { 1607 | super(...arguments); 1608 | this.vec3 = undefined; // brand for nominal typing 1609 | } 1610 | typeString() { 1611 | return "vec3"; 1612 | } 1613 | } 1614 | exports.ExprVec3 = ExprVec3; 1615 | class ExprVec4 extends ExprVec { 1616 | constructor() { 1617 | super(...arguments); 1618 | this.vec4 = undefined; // brand for nominal typing 1619 | } 1620 | repeat(num) { 1621 | return new mergepass_1.EffectLoop([this], { num: num }); 1622 | } 1623 | genPrograms(gl, vShader, uniformLocs, shaders) { 1624 | return new mergepass_1.EffectLoop([this], { num: 1 }).genPrograms(gl, vShader, uniformLocs, shaders); 1625 | } 1626 | typeString() { 1627 | return "vec4"; 1628 | } 1629 | } 1630 | exports.ExprVec4 = ExprVec4; 1631 | class WrappedExpr { 1632 | constructor(expr) { 1633 | this.expr = expr; 1634 | } 1635 | typeString() { 1636 | return this.expr.typeString(); 1637 | } 1638 | parse(buildInfo, defaultName, enc) { 1639 | return this.expr.parse(buildInfo, defaultName, enc); 1640 | } 1641 | getSampleNum() { 1642 | return this.expr.getSampleNum(); 1643 | } 1644 | brandExprWithRegion(space) { 1645 | return this.expr.brandExprWithRegion(space); 1646 | } 1647 | } 1648 | exports.WrappedExpr = WrappedExpr; 1649 | class Operator extends Expr { 1650 | constructor(ret, sourceLists, defaultNames) { 1651 | super(sourceLists, defaultNames); 1652 | this.ret = ret; 1653 | } 1654 | typeString() { 1655 | return this.ret.typeString(); 1656 | } 1657 | } 1658 | exports.Operator = Operator; 1659 | /** creates a primitive float */ 1660 | function pfloat(num) { 1661 | return new PrimitiveFloat(num); 1662 | } 1663 | exports.pfloat = pfloat; 1664 | function wrapInValue(num) { 1665 | if (num === undefined) 1666 | return undefined; 1667 | if (typeof num === "number") 1668 | return pfloat(num); 1669 | return num; 1670 | } 1671 | exports.wrapInValue = wrapInValue; 1672 | /** 1673 | * takes a template strings array and converts it to a source list; very useful 1674 | * for [[cfloat]], [[cvec2]], [[cvec3]] and [[cvec4]] 1675 | */ 1676 | function tag(strings, ...values) { 1677 | return { sections: strings.concat([]), values: values }; 1678 | } 1679 | exports.tag = tag; 1680 | 1681 | },{"../mergepass":63,"../utils":65,"../webglprogramloop":66}],26:[function(require,module,exports){ 1682 | "use strict"; 1683 | Object.defineProperty(exports, "__esModule", { value: true }); 1684 | exports.fcolor = exports.FragColorExpr = void 0; 1685 | const expr_1 = require("./expr"); 1686 | /** fragment color expression */ 1687 | class FragColorExpr extends expr_1.ExprVec4 { 1688 | constructor() { 1689 | super(expr_1.tag `gl_FragColor`, []); 1690 | this.needs.centerSample = true; 1691 | } 1692 | } 1693 | exports.FragColorExpr = FragColorExpr; 1694 | /** creates an expression that evaluates to the fragment color */ 1695 | function fcolor() { 1696 | return new FragColorExpr(); 1697 | } 1698 | exports.fcolor = fcolor; 1699 | 1700 | },{"./expr":25}],27:[function(require,module,exports){ 1701 | "use strict"; 1702 | Object.defineProperty(exports, "__esModule", { value: true }); 1703 | exports.pixel = exports.FragCoordExpr = void 0; 1704 | const expr_1 = require("./expr"); 1705 | /** frag coord expression (xy components only) */ 1706 | class FragCoordExpr extends expr_1.ExprVec2 { 1707 | constructor() { 1708 | super(expr_1.tag `gl_FragCoord.xy`, []); 1709 | } 1710 | } 1711 | exports.FragCoordExpr = FragCoordExpr; 1712 | /** 1713 | * creates an expression that evaluates to the frag coord in pixels (samplers 1714 | * take normalized coordinates, so you might want [[nfcoord]] instead) 1715 | */ 1716 | function pixel() { 1717 | return new FragCoordExpr(); 1718 | } 1719 | exports.pixel = pixel; 1720 | 1721 | },{"./expr":25}],28:[function(require,module,exports){ 1722 | "use strict"; 1723 | Object.defineProperty(exports, "__esModule", { value: true }); 1724 | exports.fxaa = void 0; 1725 | const expr_1 = require("./expr"); 1726 | const glslfunctions_1 = require("../glslfunctions"); 1727 | /** FXAA expression */ 1728 | class FXAAExpr extends expr_1.ExprVec4 { 1729 | constructor() { 1730 | super(expr_1.tag `fxaa()`, []); 1731 | this.externalFuncs = [glslfunctions_1.glslFuncs.fxaa]; 1732 | this.needs.neighborSample = true; 1733 | } 1734 | } 1735 | /** FXAA antaliasing expression */ 1736 | function fxaa() { 1737 | return new FXAAExpr(); 1738 | } 1739 | exports.fxaa = fxaa; 1740 | 1741 | },{"../glslfunctions":61,"./expr":25}],29:[function(require,module,exports){ 1742 | "use strict"; 1743 | Object.defineProperty(exports, "__esModule", { value: true }); 1744 | exports.gaussian = exports.GaussianExpr = void 0; 1745 | const glslfunctions_1 = require("../glslfunctions"); 1746 | const expr_1 = require("./expr"); 1747 | /** gaussian expression */ 1748 | class GaussianExpr extends expr_1.ExprFloat { 1749 | constructor(x, a, b) { 1750 | super(expr_1.tag `gaussian(${x}, ${a}, ${b})`, ["uFloatX", "uFloatA", "uFloatB"]); 1751 | this.x = x; 1752 | this.a = a; 1753 | this.b = b; 1754 | this.externalFuncs = [glslfunctions_1.glslFuncs.gaussian]; 1755 | } 1756 | setX(x) { 1757 | this.setUniform("uFloatX" + this.id, x); 1758 | this.x = expr_1.wrapInValue(x); 1759 | } 1760 | setA(a) { 1761 | this.setUniform("uFloatA" + this.id, a); 1762 | this.a = expr_1.wrapInValue(a); 1763 | } 1764 | setB(b) { 1765 | this.setUniform("uFloatB" + this.id, b); 1766 | this.b = expr_1.wrapInValue(b); 1767 | } 1768 | } 1769 | exports.GaussianExpr = GaussianExpr; 1770 | /** 1771 | * gaussian function that defaults to normal distribution 1772 | * @param x x position in the curve 1773 | * @param a horizontal position of peak (defaults to 0 for normal distribution) 1774 | * @param b horizontal stretch of the curve (defaults to 1 for normal distribution) 1775 | */ 1776 | function gaussian(x, a = 0, b = 1) { 1777 | return new GaussianExpr(expr_1.wrapInValue(x), expr_1.wrapInValue(a), expr_1.wrapInValue(b)); 1778 | } 1779 | exports.gaussian = gaussian; 1780 | 1781 | },{"../glslfunctions":61,"./expr":25}],30:[function(require,module,exports){ 1782 | "use strict"; 1783 | Object.defineProperty(exports, "__esModule", { value: true }); 1784 | exports.get4comp = exports.get3comp = exports.get2comp = exports.getcomp = exports.Get4CompExpr = exports.Get3CompExpr = exports.Get2CompExpr = exports.GetCompExpr = exports.checkLegalComponents = exports.typeStringToLength = void 0; 1785 | const expr_1 = require("./expr"); 1786 | // TODO this should probably be somewhere else 1787 | /** @ignore */ 1788 | function typeStringToLength(str) { 1789 | switch (str) { 1790 | case "float": 1791 | return 1; 1792 | case "vec2": 1793 | return 2; 1794 | case "vec3": 1795 | return 3; 1796 | case "vec4": 1797 | return 4; 1798 | } 1799 | } 1800 | exports.typeStringToLength = typeStringToLength; 1801 | /** @ignore */ 1802 | function genCompSource(vec, components) { 1803 | return { 1804 | sections: ["", "." + components], 1805 | values: [vec], 1806 | }; 1807 | } 1808 | /** 1809 | * checks if components accessing a vector are legal. components can be illegal 1810 | * if they mix sets (e.g. `v.rgzw`) or contain characters outside of any set 1811 | * (e.g. `v.lmno`) 1812 | * @param comps components string 1813 | * @param vec vector being accessed 1814 | */ 1815 | function checkLegalComponents(comps, vec) { 1816 | const check = (range, domain) => { 1817 | let inside = 0; 1818 | let outside = 0; 1819 | for (const c of range) { 1820 | domain.includes(c) ? inside++ : outside++; 1821 | } 1822 | return inside === inside && !outside; 1823 | }; 1824 | const inLen = typeStringToLength(vec.typeString()); 1825 | const rgbaCheck = check(comps, "rgba".substr(0, inLen)); 1826 | const xyzwCheck = check(comps, "xyzw".substr(0, inLen)); 1827 | const stpqCheck = check(comps, "stpq".substr(0, inLen)); 1828 | if (!(rgbaCheck || xyzwCheck || stpqCheck)) { 1829 | throw new Error("component sets are mixed or incorrect entirely"); 1830 | } 1831 | } 1832 | exports.checkLegalComponents = checkLegalComponents; 1833 | /** 1834 | * performs all validity checks of [[checkLegalComponents]] and checks if the 1835 | * number of accessed components does not exceed the size of the vector being 1836 | * assigned to 1837 | * @param comps components string 1838 | * @param outLen length of the resultant vector 1839 | * @param vec vector being accessed 1840 | */ 1841 | function checkGetComponents(comps, outLen, vec) { 1842 | if (comps.length > outLen) 1843 | throw new Error("too many components"); 1844 | checkLegalComponents(comps, vec); 1845 | } 1846 | /** get component expression */ 1847 | class GetCompExpr extends expr_1.ExprFloat { 1848 | constructor(vec, comps) { 1849 | checkGetComponents(comps, 1, vec); 1850 | super(genCompSource(vec, comps), ["uVec1Min"]); 1851 | this.vec1Min = vec; 1852 | } 1853 | setVec(vec) { 1854 | this.setUniform("uVec1Min", vec); 1855 | this.vec1Min = vec; 1856 | } 1857 | } 1858 | exports.GetCompExpr = GetCompExpr; 1859 | /** get 2 components expression */ 1860 | class Get2CompExpr extends expr_1.ExprVec2 { 1861 | constructor(vec, comps) { 1862 | checkGetComponents(comps, 2, vec); 1863 | super(genCompSource(vec, comps), ["uVec2Min"]); 1864 | this.vec2Min = vec; 1865 | } 1866 | setVec(vec) { 1867 | this.setUniform("uVec2Min", vec); 1868 | this.vec2Min = vec; 1869 | } 1870 | } 1871 | exports.Get2CompExpr = Get2CompExpr; 1872 | /** get 3 components expression */ 1873 | class Get3CompExpr extends expr_1.ExprVec3 { 1874 | constructor(vec, comps) { 1875 | checkGetComponents(comps, 3, vec); 1876 | super(genCompSource(vec, comps), ["uVec3Min"]); 1877 | this.vec3Min = vec; 1878 | } 1879 | setVec(vec) { 1880 | this.setUniform("uVec3Min", vec); 1881 | this.vec3Min = vec; 1882 | } 1883 | } 1884 | exports.Get3CompExpr = Get3CompExpr; 1885 | /** get 3 components expression */ 1886 | class Get4CompExpr extends expr_1.ExprVec4 { 1887 | constructor(vec, comps) { 1888 | checkGetComponents(comps, 4, vec); 1889 | super(genCompSource(vec, comps), ["uVec4Min"]); 1890 | this.vec4Min = vec; 1891 | } 1892 | setVec(vec) { 1893 | this.setUniform("uVec4Min", vec); 1894 | this.vec4Min = vec; 1895 | } 1896 | } 1897 | exports.Get4CompExpr = Get4CompExpr; 1898 | /** 1899 | * creates an expression that gets 1 component from a vector 1900 | * @param vec the vector to get components of 1901 | * @param comps components string 1902 | */ 1903 | function getcomp(vec, comps) { 1904 | return new GetCompExpr(vec, comps); 1905 | } 1906 | exports.getcomp = getcomp; 1907 | /** 1908 | * creates an expression that gets 2 components from a vector 1909 | * @param vec the vector to get components of 1910 | * @param comps components string 1911 | */ 1912 | function get2comp(vec, comps) { 1913 | return new Get2CompExpr(vec, comps); 1914 | } 1915 | exports.get2comp = get2comp; 1916 | /** 1917 | * creates an expression that gets 3 components from a vector 1918 | * @param vec the vector to get components of 1919 | * @param comps components string 1920 | */ 1921 | function get3comp(vec, comps) { 1922 | return new Get3CompExpr(vec, comps); 1923 | } 1924 | exports.get3comp = get3comp; 1925 | /** 1926 | * creates an expression that gets 4 components from a vector 1927 | * @param vec the vector to get components of 1928 | * @param comps components string 1929 | */ 1930 | function get4comp(vec, comps) { 1931 | return new Get4CompExpr(vec, comps); 1932 | } 1933 | exports.get4comp = get4comp; 1934 | 1935 | },{"./expr":25}],31:[function(require,module,exports){ 1936 | "use strict"; 1937 | Object.defineProperty(exports, "__esModule", { value: true }); 1938 | exports.godrays = exports.GodRaysExpr = void 0; 1939 | const glslfunctions_1 = require("../glslfunctions"); 1940 | const expr_1 = require("./expr"); 1941 | const fragcolorexpr_1 = require("./fragcolorexpr"); 1942 | const vecexprs_1 = require("./vecexprs"); 1943 | /** 1944 | * @ignore 1945 | * the number of samples in the source code already 1946 | */ 1947 | const DEFAULT_SAMPLES = 100; 1948 | /** godrays expression */ 1949 | class GodRaysExpr extends expr_1.ExprVec4 { 1950 | // sane godray defaults from https://github.com/Erkaman/glsl-godrays/blob/master/example/index.js 1951 | constructor(col = fragcolorexpr_1.fcolor(), exposure = expr_1.mut(1.0), decay = expr_1.mut(1.0), density = expr_1.mut(1.0), weight = expr_1.mut(0.01), lightPos = expr_1.mut(vecexprs_1.pvec2(0.5, 0.5)), samplerNum = 0, numSamples = DEFAULT_SAMPLES, convertDepth) { 1952 | // TODO the metaprogramming here is not so good! 1953 | // leaving off the function call section for now (we addd it back later) 1954 | const sourceLists = expr_1.tag `${col}, ${exposure}, ${decay}, ${density}, ${weight}, ${lightPos}, ${convertDepth !== undefined ? convertDepth.threshold : expr_1.float(0)}, ${convertDepth !== undefined ? convertDepth.newColor : vecexprs_1.vec4(0, 0, 0, 0)})`; 1955 | // TODO make this more generic 1956 | // append the _ onto the function name 1957 | // also add _depth if this is a version of the function that uses depth buffer 1958 | const customName = `godrays${convertDepth !== undefined ? "_depth" : ""}${numSamples !== 100 ? "_s" + numSamples : ""}(`; 1959 | sourceLists.sections[0] = customName; 1960 | super(sourceLists, [ 1961 | "uCol", 1962 | "uExposure", 1963 | "uDecay", 1964 | "uDensity", 1965 | "uWeight", 1966 | "uLightPos", 1967 | "uThreshold", 1968 | "uNewColor", 1969 | ]); 1970 | this.col = col; 1971 | this.exposure = exposure; 1972 | this.decay = decay; 1973 | this.density = density; 1974 | this.weight = weight; 1975 | this.lightPos = lightPos; 1976 | this.threshold = convertDepth === null || convertDepth === void 0 ? void 0 : convertDepth.threshold; 1977 | this.newColor = convertDepth === null || convertDepth === void 0 ? void 0 : convertDepth.newColor; 1978 | // will be 1 if needs to convert depth, and 0 otherwise 1979 | this.funcIndex = ~~(convertDepth !== undefined); 1980 | let customGodRayFunc = glslfunctions_1.glslFuncs.godrays 1981 | .split("godrays(") 1982 | .join(customName) 1983 | .replace(`NUM_SAMPLES = ${DEFAULT_SAMPLES}`, "NUM_SAMPLES = " + numSamples); 1984 | if (convertDepth !== undefined) { 1985 | // with regex, uncomment the line in the source code that does the 1986 | // conversion (if you think about it that's basically what a preprocessor 1987 | // does...) 1988 | customGodRayFunc = customGodRayFunc.replace(/\/\/uncomment\s/g, ""); 1989 | this.externalFuncs.push(glslfunctions_1.glslFuncs.depth2occlusion); 1990 | } 1991 | this.externalFuncs.push(customGodRayFunc); 1992 | this.brandExprWithChannel(this.funcIndex, samplerNum); 1993 | } 1994 | /** sets the light color */ 1995 | setColor(color) { 1996 | this.setUniform("uCol" + this.id, color); 1997 | this.col = color; 1998 | } 1999 | /** sets the exposure */ 2000 | setExposure(exposure) { 2001 | this.setUniform("uExposure" + this.id, exposure); 2002 | this.exposure = expr_1.wrapInValue(exposure); 2003 | } 2004 | /** sets the decay */ 2005 | setDecay(decay) { 2006 | this.setUniform("uDecay" + this.id, decay); 2007 | this.decay = expr_1.wrapInValue(decay); 2008 | } 2009 | /** sets the density */ 2010 | setDensity(density) { 2011 | this.setUniform("uDensity" + this.id, density); 2012 | this.density = expr_1.wrapInValue(density); 2013 | } 2014 | /** sets the weight */ 2015 | setWeight(weight) { 2016 | this.setUniform("uWeight" + this.id, weight); 2017 | this.weight = expr_1.wrapInValue(weight); 2018 | } 2019 | /** sets the light position */ 2020 | setLightPos(lightPos) { 2021 | this.setUniform("uLightPos" + this.id, lightPos); 2022 | this.lightPos = lightPos; 2023 | } 2024 | // these only matter when you're using a depth buffer and not an occlusion 2025 | // buffer (although right now, you'll still be able to set them) 2026 | setThreshold(threshold) { 2027 | this.setUniform("uThreshold" + this.id, threshold); 2028 | this.threshold = expr_1.wrapInValue(threshold); 2029 | } 2030 | setNewColor(newColor) { 2031 | this.setUniform("uNewColor" + this.id, newColor); 2032 | this.newColor = newColor; 2033 | } 2034 | } 2035 | exports.GodRaysExpr = GodRaysExpr; 2036 | /** 2037 | * create a godrays expression which requires an occlusion map; all values are 2038 | * mutable by default 2039 | * @param options object that defines godrays properties (has sane defaults) 2040 | */ 2041 | function godrays(options = {}) { 2042 | return new GodRaysExpr(options.color, expr_1.wrapInValue(options.exposure), expr_1.wrapInValue(options.decay), expr_1.wrapInValue(options.density), expr_1.wrapInValue(options.weight), options.lightPos, options.samplerNum, options.numSamples, options.convertDepth === undefined 2043 | ? undefined 2044 | : { 2045 | threshold: expr_1.wrapInValue(options.convertDepth.threshold), 2046 | newColor: options.convertDepth.newColor, 2047 | }); 2048 | } 2049 | exports.godrays = godrays; 2050 | 2051 | },{"../glslfunctions":61,"./expr":25,"./fragcolorexpr":26,"./vecexprs":59}],32:[function(require,module,exports){ 2052 | "use strict"; 2053 | Object.defineProperty(exports, "__esModule", { value: true }); 2054 | exports.grain = exports.GrainExpr = void 0; 2055 | const glslfunctions_1 = require("../glslfunctions"); 2056 | const expr_1 = require("./expr"); 2057 | // TODO consider getting rid of this since it's easy to make your own with 2058 | // `random` and `brightness` 2059 | /** grain expression */ 2060 | class GrainExpr extends expr_1.ExprVec4 { 2061 | constructor(grain) { 2062 | super(expr_1.tag `vec4((1.0 - ${grain} * random(gl_FragCoord.xy)) * gl_FragColor.rgb, gl_FragColor.a);`, ["uGrain"]); 2063 | this.grain = grain; 2064 | this.externalFuncs = [glslfunctions_1.glslFuncs.random]; 2065 | this.needs.centerSample = true; 2066 | } 2067 | /** sets the grain level */ 2068 | setGrain(grain) { 2069 | this.setUniform("uGrain" + this.id, grain); 2070 | this.grain = expr_1.wrapInValue(grain); 2071 | } 2072 | } 2073 | exports.GrainExpr = GrainExpr; 2074 | /** 2075 | * creates an expression that adds random grain 2076 | * @param val how much the grain should impact the image (0 to 1 is reasonable) 2077 | */ 2078 | function grain(val) { 2079 | return new GrainExpr(expr_1.wrapInValue(val)); 2080 | } 2081 | exports.grain = grain; 2082 | 2083 | },{"../glslfunctions":61,"./expr":25}],33:[function(require,module,exports){ 2084 | "use strict"; 2085 | Object.defineProperty(exports, "__esModule", { value: true }); 2086 | exports.hsv2rgb = exports.HSVToRGBExpr = void 0; 2087 | const expr_1 = require("./expr"); 2088 | const glslfunctions_1 = require("../glslfunctions"); 2089 | /** HSV to RGB expression */ 2090 | class HSVToRGBExpr extends expr_1.ExprVec4 { 2091 | constructor(color) { 2092 | super(expr_1.tag `hsv2rgb(${color})`, ["uHSVCol"]); 2093 | this.color = color; 2094 | this.externalFuncs = [glslfunctions_1.glslFuncs.hsv2rgb]; 2095 | } 2096 | /** sets the color to convert */ 2097 | setColor(color) { 2098 | this.setUniform("uHSVCol", color); 2099 | this.color = color; 2100 | } 2101 | } 2102 | exports.HSVToRGBExpr = HSVToRGBExpr; 2103 | /** 2104 | * converts a color (with an alpha compoment) from hsv to rgb 2105 | * @param col the hsva color to convert to rgba 2106 | */ 2107 | function hsv2rgb(col) { 2108 | return new HSVToRGBExpr(col); 2109 | } 2110 | exports.hsv2rgb = hsv2rgb; 2111 | 2112 | },{"../glslfunctions":61,"./expr":25}],34:[function(require,module,exports){ 2113 | "use strict"; 2114 | Object.defineProperty(exports, "__esModule", { value: true }); 2115 | exports.invert = exports.InvertExpr = void 0; 2116 | const expr_1 = require("./expr"); 2117 | const glslfunctions_1 = require("../glslfunctions"); 2118 | /** invert expression */ 2119 | class InvertExpr extends expr_1.ExprVec4 { 2120 | constructor(color) { 2121 | super(expr_1.tag `invert(${color})`, ["uColor"]); 2122 | this.externalFuncs = [glslfunctions_1.glslFuncs.invert]; 2123 | this.color = color; 2124 | } 2125 | /** sets the color */ 2126 | setColor(color) { 2127 | this.setUniform("uColor", color); 2128 | this.color = color; 2129 | } 2130 | } 2131 | exports.InvertExpr = InvertExpr; 2132 | /** 2133 | * creates an expression that inverts the color, keeping the original alpha 2134 | */ 2135 | function invert(col) { 2136 | return new InvertExpr(col); 2137 | } 2138 | exports.invert = invert; 2139 | 2140 | },{"../glslfunctions":61,"./expr":25}],35:[function(require,module,exports){ 2141 | "use strict"; 2142 | Object.defineProperty(exports, "__esModule", { value: true }); 2143 | exports.len = exports.LenExpr = void 0; 2144 | const expr_1 = require("./expr"); 2145 | /** length expression */ 2146 | class LenExpr extends expr_1.ExprFloat { 2147 | constructor(vec) { 2148 | super(expr_1.tag `length(${vec})`, ["uVec"]); 2149 | this.vec = vec; 2150 | } 2151 | setVec(vec) { 2152 | this.setUniform("uVec" + this.id, vec); 2153 | this.vec = vec; 2154 | } 2155 | } 2156 | exports.LenExpr = LenExpr; 2157 | /** creates an expreession that calculates the length of a vector */ 2158 | function len(vec) { 2159 | return new LenExpr(vec); 2160 | } 2161 | exports.len = len; 2162 | 2163 | },{"./expr":25}],36:[function(require,module,exports){ 2164 | "use strict"; 2165 | Object.defineProperty(exports, "__esModule", { value: true }); 2166 | exports.monochrome = exports.MonochromeExpr = void 0; 2167 | const expr_1 = require("./expr"); 2168 | const glslfunctions_1 = require("../glslfunctions"); 2169 | /** monochrome expression */ 2170 | class MonochromeExpr extends expr_1.ExprVec4 { 2171 | constructor(color) { 2172 | super(expr_1.tag `monochrome(${color})`, ["uColor"]); 2173 | this.externalFuncs = [glslfunctions_1.glslFuncs.monochrome]; 2174 | this.color = color; 2175 | } 2176 | /** sets the color */ 2177 | setColor(color) { 2178 | this.setUniform("uColor", color); 2179 | this.color = color; 2180 | } 2181 | } 2182 | exports.MonochromeExpr = MonochromeExpr; 2183 | /** 2184 | * creates an expression that converts a color into grayscale, keeping the 2185 | * original alpha 2186 | */ 2187 | function monochrome(col) { 2188 | return new MonochromeExpr(col); 2189 | } 2190 | exports.monochrome = monochrome; 2191 | 2192 | },{"../glslfunctions":61,"./expr":25}],37:[function(require,module,exports){ 2193 | "use strict"; 2194 | Object.defineProperty(exports, "__esModule", { value: true }); 2195 | exports.motionblur = exports.MotionBlurLoop = void 0; 2196 | const mergepass_1 = require("../mergepass"); 2197 | const channelsampleexpr_1 = require("./channelsampleexpr"); 2198 | const expr_1 = require("./expr"); 2199 | const fragcolorexpr_1 = require("./fragcolorexpr"); 2200 | const opexpr_1 = require("./opexpr"); 2201 | /** frame averaging motion blur loop */ 2202 | class MotionBlurLoop extends mergepass_1.EffectLoop { 2203 | constructor(target = 0, persistence = expr_1.float(expr_1.mut(0.3))) { 2204 | const col1 = opexpr_1.op(channelsampleexpr_1.channel(target), "*", persistence); 2205 | const col2 = opexpr_1.op(fragcolorexpr_1.fcolor(), "*", opexpr_1.op(1, "-", persistence)); 2206 | const effects = [ 2207 | mergepass_1.loop([opexpr_1.op(col1, "+", col2)]).target(target), 2208 | channelsampleexpr_1.channel(target), 2209 | ]; 2210 | super(effects, { num: 1 }); 2211 | this.persistence = persistence; 2212 | } 2213 | /** set the persistence (keep between 0 and 1) */ 2214 | setPersistence(float) { 2215 | if (!(this.persistence instanceof expr_1.BasicFloat)) 2216 | throw new Error("persistence expression not basic float"); 2217 | this.persistence.setVal(float); 2218 | } 2219 | } 2220 | exports.MotionBlurLoop = MotionBlurLoop; 2221 | /** 2222 | * creates a frame averaging motion blur effect 2223 | * @param target the channel where your accumulation buffer is (defaults to 0, 2224 | * which you might be using for something like the depth texture, so be sure to 2225 | * change this to suit your needs) 2226 | * @param persistence close to 0 is more ghostly, and close to 1 is nearly no 2227 | * motion blur at all (defaults to 0.3) 2228 | */ 2229 | function motionblur(target, persistence) { 2230 | return new MotionBlurLoop(target, expr_1.wrapInValue(persistence)); 2231 | } 2232 | exports.motionblur = motionblur; 2233 | 2234 | },{"../mergepass":63,"./channelsampleexpr":19,"./expr":25,"./fragcolorexpr":26,"./opexpr":43}],38:[function(require,module,exports){ 2235 | "use strict"; 2236 | Object.defineProperty(exports, "__esModule", { value: true }); 2237 | exports.mouse = exports.MouseExpr = void 0; 2238 | const expr_1 = require("./expr"); 2239 | /** mouse position expression */ 2240 | class MouseExpr extends expr_1.ExprVec2 { 2241 | constructor() { 2242 | super(expr_1.tag `uMouse`, []); 2243 | this.needs.mouseUniform = true; 2244 | } 2245 | } 2246 | exports.MouseExpr = MouseExpr; 2247 | /** 2248 | * creates an expression that evaluates to a vector representing the mouse 2249 | * position in pixels 2250 | */ 2251 | function mouse() { 2252 | return new MouseExpr(); 2253 | } 2254 | exports.mouse = mouse; 2255 | 2256 | },{"./expr":25}],39:[function(require,module,exports){ 2257 | "use strict"; 2258 | Object.defineProperty(exports, "__esModule", { value: true }); 2259 | exports.center = exports.NormCenterFragCoordExpr = void 0; 2260 | const expr_1 = require("./expr"); 2261 | /** normalized centered frag coord expression */ 2262 | class NormCenterFragCoordExpr extends expr_1.ExprVec2 { 2263 | constructor() { 2264 | super(expr_1.tag `(gl_FragCoord.xy / uResolution - 0.5)`, []); 2265 | } 2266 | } 2267 | exports.NormCenterFragCoordExpr = NormCenterFragCoordExpr; 2268 | /** 2269 | * creates an expression that calculates the normalized centered coord 2270 | * (coordinates range from -0.5 to 0.5) 2271 | */ 2272 | function center() { 2273 | return new NormCenterFragCoordExpr(); 2274 | } 2275 | exports.center = center; 2276 | 2277 | },{"./expr":25}],40:[function(require,module,exports){ 2278 | "use strict"; 2279 | Object.defineProperty(exports, "__esModule", { value: true }); 2280 | exports.norm = exports.NormExpr = void 0; 2281 | const expr_1 = require("./expr"); 2282 | /** normalize expression */ 2283 | class NormExpr extends expr_1.Operator { 2284 | constructor(vec) { 2285 | super(vec, expr_1.tag `normalize(${vec})`, ["uVec"]); 2286 | this.vec = vec; 2287 | } 2288 | /** sets the vec to normalize */ 2289 | setVec(vec) { 2290 | this.setUniform("uVec" + this.id, vec); 2291 | this.vec = vec; 2292 | } 2293 | } 2294 | exports.NormExpr = NormExpr; 2295 | /** creates an expression that normalizes a vector */ 2296 | function norm(vec) { 2297 | return new NormExpr(vec); 2298 | } 2299 | exports.norm = norm; 2300 | 2301 | },{"./expr":25}],41:[function(require,module,exports){ 2302 | "use strict"; 2303 | Object.defineProperty(exports, "__esModule", { value: true }); 2304 | exports.pos = exports.NormFragCoordExpr = void 0; 2305 | const expr_1 = require("./expr"); 2306 | /** normalized frag coord expression */ 2307 | class NormFragCoordExpr extends expr_1.ExprVec2 { 2308 | constructor() { 2309 | // don't remove these parens! even if you think you are being clever about 2310 | // order of operations 2311 | super(expr_1.tag `(gl_FragCoord.xy / uResolution)`, []); 2312 | } 2313 | } 2314 | exports.NormFragCoordExpr = NormFragCoordExpr; 2315 | /** 2316 | * creates an expression that calculates the normalized frag coord (coordinates 2317 | * range from 0 to 1) 2318 | */ 2319 | function pos() { 2320 | return new NormFragCoordExpr(); 2321 | } 2322 | exports.pos = pos; 2323 | 2324 | },{"./expr":25}],42:[function(require,module,exports){ 2325 | "use strict"; 2326 | Object.defineProperty(exports, "__esModule", { value: true }); 2327 | exports.nmouse = exports.NormMouseExpr = void 0; 2328 | const expr_1 = require("./expr"); 2329 | /** normalized mouse position expression */ 2330 | class NormMouseExpr extends expr_1.ExprVec2 { 2331 | constructor() { 2332 | super(expr_1.tag `(uMouse / uResolution.xy)`, []); 2333 | this.needs.mouseUniform = true; 2334 | } 2335 | } 2336 | exports.NormMouseExpr = NormMouseExpr; 2337 | /** 2338 | * creates an expression that calculates the normalized mouse position 2339 | * (coordinates range from 0 to 1) 2340 | */ 2341 | function nmouse() { 2342 | return new NormMouseExpr(); 2343 | } 2344 | exports.nmouse = nmouse; 2345 | 2346 | },{"./expr":25}],43:[function(require,module,exports){ 2347 | "use strict"; 2348 | Object.defineProperty(exports, "__esModule", { value: true }); 2349 | exports.op = exports.OpExpr = void 0; 2350 | const expr_1 = require("./expr"); 2351 | function genOpSourceList(left, op, right) { 2352 | return { 2353 | sections: ["(", ` ${op} `, ")"], 2354 | values: [left, right], 2355 | }; 2356 | } 2357 | class OpExpr extends expr_1.Operator { 2358 | constructor(left, op, right) { 2359 | super(left, genOpSourceList(left, op, right), ["uLeft", "uRight"]); 2360 | this.left = left; 2361 | this.right = right; 2362 | } 2363 | setLeft(left) { 2364 | this.setUniform("uLeft" + this.id, left); 2365 | this.left = expr_1.wrapInValue(left); 2366 | } 2367 | setRight(right) { 2368 | this.setUniform("uRight" + this.id, right); 2369 | this.right = expr_1.wrapInValue(right); 2370 | } 2371 | } 2372 | exports.OpExpr = OpExpr; 2373 | // implementation 2374 | /** 2375 | * creates an arithmetic operator expression 2376 | * @param left expression left of operator 2377 | * @param op string representing arithmetic operator 2378 | * @param right expression right of operator 2379 | */ 2380 | function op(left, op, right) { 2381 | return new OpExpr(expr_1.wrapInValue(left), op, expr_1.wrapInValue(right)); 2382 | } 2383 | exports.op = op; 2384 | 2385 | },{"./expr":25}],44:[function(require,module,exports){ 2386 | "use strict"; 2387 | Object.defineProperty(exports, "__esModule", { value: true }); 2388 | exports.fractalize = exports.perlin = exports.PerlinExpr = void 0; 2389 | const glslfunctions_1 = require("../glslfunctions"); 2390 | const expr_1 = require("./expr"); 2391 | const opexpr_1 = require("./opexpr"); 2392 | /** Perlin noise expression */ 2393 | class PerlinExpr extends expr_1.ExprFloat { 2394 | // TODO include a default 2395 | constructor(pos) { 2396 | super(expr_1.tag `gradientnoise(${pos})`, ["uPos"]); 2397 | this.pos = pos; 2398 | this.externalFuncs = [glslfunctions_1.glslFuncs.random2, glslfunctions_1.glslFuncs.gradientnoise]; 2399 | } 2400 | /** sets the position to calculate noise value of */ 2401 | setPos(pos) { 2402 | this.setUniform("uPos", pos); 2403 | this.pos = pos; 2404 | } 2405 | } 2406 | exports.PerlinExpr = PerlinExpr; 2407 | /** 2408 | * creates a perlin noise expression; values range from -1 to 1 but they tend 2409 | * to be grayer than the [[simplex]] implementation 2410 | * @param pos position 2411 | */ 2412 | function perlin(pos) { 2413 | return new PerlinExpr(pos); 2414 | } 2415 | exports.perlin = perlin; 2416 | /** 2417 | * take any function from a position to a float, and repeatedly sum calls to it 2418 | * with doubling frequency and halving amplitude (works well with [[simplex]] 2419 | * and [[perlin]]) 2420 | * @param pos position 2421 | * @param octaves how many layers deep to make the fractal 2422 | * @param func the function to fractalize 2423 | */ 2424 | function fractalize(pos, octaves, func) { 2425 | if (octaves < 0) 2426 | throw new Error("octaves can't be < 0"); 2427 | const recurse = (pos, size, level) => { 2428 | if (level <= 0) 2429 | return expr_1.pfloat(0); 2430 | return opexpr_1.op(func(opexpr_1.op(pos, "/", size * 2)), "+", recurse(pos, size / 2, level - 1)); 2431 | }; 2432 | return recurse(pos, 0.5, octaves); 2433 | } 2434 | exports.fractalize = fractalize; 2435 | 2436 | },{"../glslfunctions":61,"./expr":25,"./opexpr":43}],45:[function(require,module,exports){ 2437 | "use strict"; 2438 | Object.defineProperty(exports, "__esModule", { value: true }); 2439 | exports.pblur = exports.PowerBlurLoop = void 0; 2440 | const mergepass_1 = require("../mergepass"); 2441 | const blurexpr_1 = require("./blurexpr"); 2442 | const vecexprs_1 = require("./vecexprs"); 2443 | const expr_1 = require("./expr"); 2444 | const baseLog = (x, y) => Math.log(y) / Math.log(x); 2445 | // TODO consider getting rid of this, as it pretty much never looks good 2446 | /** power blur loop */ 2447 | class PowerBlurLoop extends mergepass_1.EffectLoop { 2448 | constructor(size) { 2449 | const side = blurexpr_1.gauss(expr_1.mut(vecexprs_1.pvec2(size, 0))); 2450 | const up = blurexpr_1.gauss(expr_1.mut(vecexprs_1.pvec2(0, size))); 2451 | const reps = Math.ceil(baseLog(2, size)); 2452 | super([side, up], { 2453 | num: reps + 1, 2454 | }); 2455 | this.size = size; 2456 | this.loopInfo.func = (i) => { 2457 | const distance = this.size / Math.pow(2, i); 2458 | up.setDirection(vecexprs_1.pvec2(0, distance)); 2459 | side.setDirection(vecexprs_1.pvec2(distance, 0)); 2460 | }; 2461 | } 2462 | /** sets the size of the radius */ 2463 | setSize(size) { 2464 | this.size = size; 2465 | this.loopInfo.num = Math.ceil(baseLog(2, size)); 2466 | } 2467 | } 2468 | exports.PowerBlurLoop = PowerBlurLoop; 2469 | /** 2470 | * fast approximate blur for large blur radius that might look good in some cases 2471 | * @param size the radius of the blur 2472 | */ 2473 | function pblur(size) { 2474 | return new PowerBlurLoop(size); 2475 | } 2476 | exports.pblur = pblur; 2477 | 2478 | },{"../mergepass":63,"./blurexpr":16,"./expr":25,"./vecexprs":59}],46:[function(require,module,exports){ 2479 | "use strict"; 2480 | Object.defineProperty(exports, "__esModule", { value: true }); 2481 | exports.random = exports.RandomExpr = void 0; 2482 | const glslfunctions_1 = require("../glslfunctions"); 2483 | const expr_1 = require("./expr"); 2484 | const normfragcoordexpr_1 = require("./normfragcoordexpr"); 2485 | /** psuedorandom number expression */ 2486 | class RandomExpr extends expr_1.ExprFloat { 2487 | constructor(seed = normfragcoordexpr_1.pos()) { 2488 | super(expr_1.tag `random(${seed})`, ["uSeed"]); 2489 | this.seed = seed; 2490 | this.externalFuncs = [glslfunctions_1.glslFuncs.random]; 2491 | } 2492 | /** sets the seed (vary this over time to get a moving effect) */ 2493 | setSeed(seed) { 2494 | this.setUniform("uSeed", seed); 2495 | this.seed = seed; 2496 | } 2497 | } 2498 | exports.RandomExpr = RandomExpr; 2499 | /** 2500 | * creates expression that evaluates to a pseudorandom number between 0 and 1 2501 | * @param seed vec2 to to seed the random number (defaults to the normalized 2502 | * frag coord) 2503 | */ 2504 | function random(seed) { 2505 | return new RandomExpr(seed); 2506 | } 2507 | exports.random = random; 2508 | 2509 | },{"../glslfunctions":61,"./expr":25,"./normfragcoordexpr":41}],47:[function(require,module,exports){ 2510 | "use strict"; 2511 | Object.defineProperty(exports, "__esModule", { value: true }); 2512 | exports.region = void 0; 2513 | const mergepass_1 = require("../mergepass"); 2514 | const expr_1 = require("./expr"); 2515 | const getcompexpr_1 = require("./getcompexpr"); 2516 | const normfragcoordexpr_1 = require("./normfragcoordexpr"); 2517 | const opexpr_1 = require("./opexpr"); 2518 | const ternaryexpr_1 = require("./ternaryexpr"); 2519 | const fragcolorexpr_1 = require("./fragcolorexpr"); 2520 | // form: x1, y1, x2, y2 2521 | function createDifferenceFloats(floats) { 2522 | const axes = "xy"; 2523 | const differences = []; 2524 | if (floats.length !== 4) { 2525 | throw new Error("incorrect amount of points specified for region"); 2526 | } 2527 | for (let i = 0; i < 2; i++) { 2528 | differences.push(opexpr_1.op(getcompexpr_1.getcomp(normfragcoordexpr_1.pos(), axes[i]), "-", floats[i])); 2529 | } 2530 | for (let i = 2; i < floats.length; i++) { 2531 | differences.push(opexpr_1.op(floats[i], "-", getcompexpr_1.getcomp(normfragcoordexpr_1.pos(), axes[i - 2]))); 2532 | } 2533 | return differences; 2534 | } 2535 | /** 2536 | * restrict an effect to a region of the screen 2537 | * @param space top left, top right, bottom left, bottom right corners of the 2538 | * region, or just a number if you wish to sample from a channel as the region 2539 | * @param success expression for being inside the region 2540 | * @param failure expression for being outside the region 2541 | * @param not whether to invert the region 2542 | */ 2543 | function region(space, success, failure, not = false) { 2544 | const floats = Array.isArray(space) 2545 | ? space.map((f) => expr_1.wrapInValue(f)) 2546 | : typeof space === "number" 2547 | ? expr_1.wrapInValue(space) 2548 | : space; 2549 | if (failure instanceof mergepass_1.EffectLoop) { 2550 | if (!(success instanceof mergepass_1.EffectLoop)) { 2551 | [success, failure] = [failure, success]; // swap the order 2552 | not = !not; // invert the region 2553 | } 2554 | } 2555 | if (success instanceof mergepass_1.EffectLoop) { 2556 | if (!(failure instanceof mergepass_1.EffectLoop)) { 2557 | return success.regionWrap(floats, failure, true, not); 2558 | } 2559 | // double loop, so we have to do separately 2560 | return mergepass_1.loop([ 2561 | success.regionWrap(floats, fragcolorexpr_1.fcolor(), false, not), 2562 | failure.regionWrap(floats, fragcolorexpr_1.fcolor(), true, !not), 2563 | ]); 2564 | } 2565 | return ternaryexpr_1.ternary(Array.isArray(floats) ? createDifferenceFloats(floats) : floats, success.brandExprWithRegion(floats), failure.brandExprWithRegion(floats), not); 2566 | } 2567 | exports.region = region; 2568 | 2569 | },{"../mergepass":63,"./expr":25,"./fragcolorexpr":26,"./getcompexpr":30,"./normfragcoordexpr":41,"./opexpr":43,"./ternaryexpr":55}],48:[function(require,module,exports){ 2570 | "use strict"; 2571 | Object.defineProperty(exports, "__esModule", { value: true }); 2572 | exports.resolution = exports.ResolutionExpr = void 0; 2573 | const expr_1 = require("./expr"); 2574 | /** resolution expression */ 2575 | class ResolutionExpr extends expr_1.ExprVec2 { 2576 | constructor() { 2577 | super(expr_1.tag `uResolution`, []); 2578 | } 2579 | } 2580 | exports.ResolutionExpr = ResolutionExpr; 2581 | /** creates an expression that evaluates to a vector representing the resolution */ 2582 | function resolution() { 2583 | return new ResolutionExpr(); 2584 | } 2585 | exports.resolution = resolution; 2586 | 2587 | },{"./expr":25}],49:[function(require,module,exports){ 2588 | "use strict"; 2589 | Object.defineProperty(exports, "__esModule", { value: true }); 2590 | exports.rgb2hsv = exports.RGBToHSVExpr = void 0; 2591 | const expr_1 = require("./expr"); 2592 | const glslfunctions_1 = require("../glslfunctions"); 2593 | /** RGB to HSV expression */ 2594 | class RGBToHSVExpr extends expr_1.ExprVec4 { 2595 | constructor(color) { 2596 | super(expr_1.tag `rgb2hsv(${color})`, ["uRGBCol"]); 2597 | this.color = color; 2598 | this.externalFuncs = [glslfunctions_1.glslFuncs.rgb2hsv]; 2599 | } 2600 | /** sets the color to convert */ 2601 | setColor(color) { 2602 | this.setUniform("uRGBCol", color); 2603 | this.color = color; 2604 | } 2605 | } 2606 | exports.RGBToHSVExpr = RGBToHSVExpr; 2607 | /** 2608 | * creates an expression that converts a color (with an alpha component) from 2609 | * rgb to hsv 2610 | * @param col the rgba color to convert to hsva 2611 | */ 2612 | function rgb2hsv(col) { 2613 | return new RGBToHSVExpr(col); 2614 | } 2615 | exports.rgb2hsv = rgb2hsv; 2616 | 2617 | },{"../glslfunctions":61,"./expr":25}],50:[function(require,module,exports){ 2618 | "use strict"; 2619 | Object.defineProperty(exports, "__esModule", { value: true }); 2620 | exports.rotate = exports.RotateExpr = void 0; 2621 | const glslfunctions_1 = require("../glslfunctions"); 2622 | const expr_1 = require("./expr"); 2623 | /** rotate expression */ 2624 | class RotateExpr extends expr_1.ExprVec2 { 2625 | constructor(vec, angle) { 2626 | super(expr_1.tag `rotate2d(${vec}, ${angle})`, ["uVec", "uAngle"]); 2627 | this.vec = vec; 2628 | this.angle = angle; 2629 | this.externalFuncs = [glslfunctions_1.glslFuncs.rotate2d]; 2630 | } 2631 | /** set the vector to rotate */ 2632 | setVec(vec) { 2633 | this.setUniform("uVec" + this.id, vec); 2634 | this.vec = vec; 2635 | } 2636 | /** set the angle to rotate by */ 2637 | setAngle(angle) { 2638 | this.setUniform("uAngle" + this.id, angle); 2639 | this.angle = expr_1.wrapInValue(angle); 2640 | } 2641 | } 2642 | exports.RotateExpr = RotateExpr; 2643 | /** 2644 | * creates an expression that rotates a vector by a given angle 2645 | * @param vec the vector to rotate 2646 | * @param angle radians to rotate vector by 2647 | */ 2648 | function rotate(vec, angle) { 2649 | return new RotateExpr(vec, expr_1.wrapInValue(angle)); 2650 | } 2651 | exports.rotate = rotate; 2652 | 2653 | },{"../glslfunctions":61,"./expr":25}],51:[function(require,module,exports){ 2654 | "use strict"; 2655 | Object.defineProperty(exports, "__esModule", { value: true }); 2656 | exports.input = exports.SceneSampleExpr = void 0; 2657 | const expr_1 = require("./expr"); 2658 | const normfragcoordexpr_1 = require("./normfragcoordexpr"); 2659 | /** scene sample expression */ 2660 | class SceneSampleExpr extends expr_1.ExprVec4 { 2661 | constructor(coord = normfragcoordexpr_1.pos()) { 2662 | super(expr_1.tag `texture2D(uSceneSampler, ${coord})`, ["uCoord"]); 2663 | this.coord = coord; 2664 | this.needs.sceneBuffer = true; 2665 | } 2666 | /** sets coordinate where scene is being sampled from */ 2667 | setCoord(coord) { 2668 | this.setUniform("uCoord", coord); 2669 | this.coord = coord; 2670 | } 2671 | } 2672 | exports.SceneSampleExpr = SceneSampleExpr; 2673 | /** 2674 | * creates an expression that samples the original scene 2675 | * @param vec where to sample the original scene texture (defaults to the 2676 | * normalized frag coord, but change this if you want to transform the 2677 | * coordinate space of the original image) 2678 | */ 2679 | function input(vec) { 2680 | return new SceneSampleExpr(vec); 2681 | } 2682 | exports.input = input; 2683 | 2684 | },{"./expr":25,"./normfragcoordexpr":41}],52:[function(require,module,exports){ 2685 | "use strict"; 2686 | Object.defineProperty(exports, "__esModule", { value: true }); 2687 | exports.SetColorExpr = void 0; 2688 | const expr_1 = require("./expr"); 2689 | /** 2690 | * set fragment color expression (not needed for the user; used internally for 2691 | * wrapping any kind of [[Vec4]] in an [[ExprVec4]]) 2692 | */ 2693 | class SetColorExpr extends expr_1.ExprVec4 { 2694 | constructor(vec) { 2695 | super(expr_1.tag `(${vec})`, ["uVal"]); 2696 | this.vec = vec; 2697 | } 2698 | } 2699 | exports.SetColorExpr = SetColorExpr; 2700 | 2701 | },{"./expr":25}],53:[function(require,module,exports){ 2702 | "use strict"; 2703 | Object.defineProperty(exports, "__esModule", { value: true }); 2704 | exports.simplex = exports.SimplexNoise = void 0; 2705 | const glslfunctions_1 = require("../glslfunctions"); 2706 | const expr_1 = require("./expr"); 2707 | /** simplex noise expression */ 2708 | class SimplexNoise extends expr_1.ExprFloat { 2709 | constructor(pos) { 2710 | super(expr_1.tag `simplexnoise(${pos})`, ["uPos"]); 2711 | this.pos = pos; 2712 | this.externalFuncs = [glslfunctions_1.glslFuncs.simplexhelpers, glslfunctions_1.glslFuncs.simplexnoise]; 2713 | } 2714 | setPos(pos) { 2715 | this.setUniform("uPos", pos); 2716 | this.pos = pos; 2717 | } 2718 | } 2719 | exports.SimplexNoise = SimplexNoise; 2720 | /** 2721 | * creates a simplex noise expression; values range from -1 to 1 2722 | * @param pos position 2723 | */ 2724 | function simplex(pos) { 2725 | return new SimplexNoise(pos); 2726 | } 2727 | exports.simplex = simplex; 2728 | 2729 | },{"../glslfunctions":61,"./expr":25}],54:[function(require,module,exports){ 2730 | "use strict"; 2731 | Object.defineProperty(exports, "__esModule", { value: true }); 2732 | exports.sobel = exports.SobelExpr = void 0; 2733 | const glslfunctions_1 = require("../glslfunctions"); 2734 | const expr_1 = require("./expr"); 2735 | /** Sobel edge detection expression */ 2736 | class SobelExpr extends expr_1.ExprVec4 { 2737 | constructor(samplerNum) { 2738 | super(expr_1.tag `sobel()`, []); 2739 | this.externalFuncs = [glslfunctions_1.glslFuncs.sobel]; 2740 | this.brandExprWithChannel(0, samplerNum); 2741 | } 2742 | } 2743 | exports.SobelExpr = SobelExpr; 2744 | /** 2745 | * creates a Sobel edge detection expression that outputs the raw result; for 2746 | * more highly processed edge detection expressions, see [[edgecolor]] or 2747 | * [[edge]] 2748 | * @param samplerNum where to sample from 2749 | */ 2750 | function sobel(samplerNum) { 2751 | return new SobelExpr(samplerNum); 2752 | } 2753 | exports.sobel = sobel; 2754 | 2755 | },{"../glslfunctions":61,"./expr":25}],55:[function(require,module,exports){ 2756 | "use strict"; 2757 | Object.defineProperty(exports, "__esModule", { value: true }); 2758 | exports.ternary = exports.TernaryExpr = void 0; 2759 | const expr_1 = require("./expr"); 2760 | function genTernarySourceList(floats, success, failure, not) { 2761 | const sourceList = { 2762 | sections: [`(${not ? "!" : ""}(`], 2763 | values: [], 2764 | }; 2765 | let counter = 0; 2766 | // generate the boolean expression 2767 | if (floats !== null) { 2768 | for (const f of floats) { 2769 | counter++; 2770 | const last = counter === floats.length; 2771 | sourceList.values.push(f); 2772 | sourceList.sections.push(` > 0.${last ? ") ? " : " && "}`); 2773 | } 2774 | } 2775 | else { 2776 | sourceList.sections[0] += "uCount == 0) ? "; 2777 | } 2778 | // generate the success expression and colon 2779 | sourceList.values.push(success); 2780 | sourceList.sections.push(" : "); 2781 | // generate the failure expression 2782 | sourceList.values.push(failure); 2783 | sourceList.sections.push(")"); 2784 | return sourceList; 2785 | } 2786 | class TernaryExpr extends expr_1.Operator { 2787 | constructor(floats, success, failure, not) { 2788 | super(success, genTernarySourceList(floats, success, failure, not), [ 2789 | ...(floats !== null 2790 | ? Array.from(floats, (val, index) => "uFloat" + index) 2791 | : []), 2792 | "uSuccess", 2793 | "uFailure", 2794 | ]); 2795 | this.success = success; 2796 | this.failure = failure; 2797 | this.needs.passCount = floats === null; 2798 | } 2799 | } 2800 | exports.TernaryExpr = TernaryExpr; 2801 | /** 2802 | * creates a ternary expression; the boolean expression is if all the floats 2803 | * given are greater than 0 2804 | * @param floats if all these floats (or the single float) are above 0, then 2805 | * evaluates to success expression 2806 | * @param success 2807 | * @param failure 2808 | * @param not whether to invert the ternary 2809 | */ 2810 | function ternary(floats, success, failure, not = false) { 2811 | // TODO make this type safe (ran into a type error here) 2812 | // wrap single float in array if need be 2813 | if (!Array.isArray(floats) && floats !== null) 2814 | floats = [floats].map((f) => expr_1.wrapInValue(f)); 2815 | // TODO get rid of this cast 2816 | return new TernaryExpr(floats, expr_1.wrapInValue(success), expr_1.wrapInValue(failure), not); 2817 | } 2818 | exports.ternary = ternary; 2819 | 2820 | },{"./expr":25}],56:[function(require,module,exports){ 2821 | "use strict"; 2822 | Object.defineProperty(exports, "__esModule", { value: true }); 2823 | exports.time = exports.TimeExpr = void 0; 2824 | const expr_1 = require("./expr"); 2825 | /** time expression */ 2826 | class TimeExpr extends expr_1.ExprFloat { 2827 | constructor() { 2828 | super(expr_1.tag `uTime`, []); 2829 | this.needs.timeUniform = true; 2830 | } 2831 | } 2832 | exports.TimeExpr = TimeExpr; 2833 | /** creates a time expression that evaluates to the current time */ 2834 | function time() { 2835 | return new TimeExpr(); 2836 | } 2837 | exports.time = time; 2838 | 2839 | },{"./expr":25}],57:[function(require,module,exports){ 2840 | "use strict"; 2841 | Object.defineProperty(exports, "__esModule", { value: true }); 2842 | exports.translate = exports.TranslateExpr = void 0; 2843 | const expr_1 = require("./expr"); 2844 | // really just adding two vecs together, but it might be confusing that there's 2845 | // rotate but no translate, so this is included. also it could make some 2846 | // operations more readable 2847 | /** sets the translate expression */ 2848 | class TranslateExpr extends expr_1.ExprVec2 { 2849 | constructor(vec, pos) { 2850 | super(expr_1.tag `(${vec} + ${pos})`, ["uVec", "uPos"]); 2851 | this.vec = vec; 2852 | this.pos = pos; 2853 | } 2854 | /** sets the starting position */ 2855 | setVec(vec) { 2856 | this.setUniform("uVec" + this.id, vec); 2857 | this.vec = vec; 2858 | } 2859 | /** sets how far the vector will be translated */ 2860 | setPos(pos) { 2861 | this.setUniform("uPos" + this.id, pos); 2862 | this.pos = pos; 2863 | } 2864 | } 2865 | exports.TranslateExpr = TranslateExpr; 2866 | /** translates the position of a vector by another vector */ 2867 | function translate(vec, pos) { 2868 | return new TranslateExpr(vec, pos); 2869 | } 2870 | exports.translate = translate; 2871 | 2872 | },{"./expr":25}],58:[function(require,module,exports){ 2873 | "use strict"; 2874 | Object.defineProperty(exports, "__esModule", { value: true }); 2875 | exports.truedepth = exports.TrueDepthExpr = void 0; 2876 | const expr_1 = require("./expr"); 2877 | const glslfunctions_1 = require("../glslfunctions"); 2878 | /** true depth expression */ 2879 | class TrueDepthExpr extends expr_1.ExprFloat { 2880 | constructor(depth) { 2881 | super(expr_1.tag `truedepth(${depth})`, ["uDist"]); 2882 | this.depth = depth; 2883 | this.externalFuncs = [glslfunctions_1.glslFuncs.truedepth]; 2884 | } 2885 | /** sets the distance to convert to the true depth */ 2886 | setDist(depth) { 2887 | this.setUniform("uDist", depth); 2888 | this.depth = expr_1.wrapInValue(depth); 2889 | } 2890 | } 2891 | exports.TrueDepthExpr = TrueDepthExpr; 2892 | /** calculates the linear depth from inverse depth value `1 / distance` */ 2893 | function truedepth(depth) { 2894 | return new TrueDepthExpr(expr_1.wrapInValue(depth)); 2895 | } 2896 | exports.truedepth = truedepth; 2897 | 2898 | },{"../glslfunctions":61,"./expr":25}],59:[function(require,module,exports){ 2899 | "use strict"; 2900 | Object.defineProperty(exports, "__esModule", { value: true }); 2901 | exports.pvec4 = exports.pvec3 = exports.pvec2 = exports.vec4 = exports.vec3 = exports.vec2 = void 0; 2902 | const expr_1 = require("./expr"); 2903 | /** @ignore */ 2904 | function vecSourceList(...components) { 2905 | const sections = ["vec" + components.length + "("]; 2906 | for (let i = 0; i < components.length - 1; i++) { 2907 | sections.push(", "); 2908 | } 2909 | const defaultNames = []; 2910 | for (let i = 0; i < components.length; i++) { 2911 | defaultNames.push("uComp" + i); 2912 | } 2913 | sections.push(")"); 2914 | return [{ sections: sections, values: components }, defaultNames]; 2915 | } 2916 | // expression vector shorthands 2917 | /** creates a basic vec2 expression */ 2918 | function vec2(comp1, comp2) { 2919 | return new expr_1.BasicVec2(...vecSourceList(...[comp1, comp2].map((c) => expr_1.wrapInValue(c)))); 2920 | } 2921 | exports.vec2 = vec2; 2922 | /** creates a basic vec3 expression */ 2923 | function vec3(comp1, comp2, comp3) { 2924 | return new expr_1.BasicVec3(...vecSourceList(...[comp1, comp2, comp3].map((c) => expr_1.wrapInValue(c)))); 2925 | } 2926 | exports.vec3 = vec3; 2927 | /** creates a basic vec4 expression */ 2928 | function vec4(comp1, comp2, comp3, comp4) { 2929 | return new expr_1.BasicVec4(...vecSourceList(...[comp1, comp2, comp3, comp4].map((c) => expr_1.wrapInValue(c)))); 2930 | } 2931 | exports.vec4 = vec4; 2932 | // primitive vector shorthands 2933 | /** creates a primitive vec2 expression */ 2934 | function pvec2(comp1, comp2) { 2935 | return new expr_1.PrimitiveVec2([comp1, comp2]); 2936 | } 2937 | exports.pvec2 = pvec2; 2938 | /** creates a primitive vec3 expression */ 2939 | function pvec3(comp1, comp2, comp3) { 2940 | return new expr_1.PrimitiveVec3([comp1, comp2, comp3]); 2941 | } 2942 | exports.pvec3 = pvec3; 2943 | /** creates a primitive vec4 expression */ 2944 | function pvec4(comp1, comp2, comp3, comp4) { 2945 | return new expr_1.PrimitiveVec4([comp1, comp2, comp3, comp4]); 2946 | } 2947 | exports.pvec4 = pvec4; 2948 | 2949 | },{"./expr":25}],60:[function(require,module,exports){ 2950 | "use strict"; 2951 | Object.defineProperty(exports, "__esModule", { value: true }); 2952 | 2953 | },{}],61:[function(require,module,exports){ 2954 | "use strict"; 2955 | Object.defineProperty(exports, "__esModule", { value: true }); 2956 | exports.glslFuncs = void 0; 2957 | // adapted from The Book of Shaders 2958 | /** glsl source code for external functions */ 2959 | exports.glslFuncs = { 2960 | // TODO bad to calculate single pixel width every time; maybe it can be a need 2961 | texture2D_region: `vec4 texture2D_region( 2962 | float r_x_min, 2963 | float r_y_min, 2964 | float r_x_max, 2965 | float r_y_max, 2966 | sampler2D sampler, 2967 | vec2 uv 2968 | ) { 2969 | vec2 d = vec2(1., 1.) / uResolution; // pixel width 2970 | return texture2D(sampler, clamp(uv, vec2(r_x_min + d.x, r_y_min + d.x), vec2(r_x_max - d.y, r_y_max - d.y))); 2971 | }`, 2972 | // TODO replace with a better one 2973 | // adapted from The Book of Shaders 2974 | random: `float random(vec2 st) { 2975 | return fract(sin(dot(st.xy / 99., vec2(12.9898, 78.233))) * 43758.5453123); 2976 | }`, 2977 | // adapted from The Book of Shaders 2978 | random2: `vec2 random2(vec2 st) { 2979 | st = vec2(dot(st,vec2(127.1,311.7)), dot(st,vec2(269.5,183.3))); 2980 | return -1.0 + 2.0*fract(sin(st)*43758.5453123); 2981 | }`, 2982 | rotate2d: `vec2 rotate2d(vec2 v, float angle) { 2983 | return mat2(cos(angle), -sin(angle), sin(angle), cos(angle)) * v; 2984 | }`, 2985 | // adapted from The Book of Shaders 2986 | hsv2rgb: `vec4 hsv2rgb(vec4 co){ 2987 | vec3 c = co.xyz; 2988 | vec3 rgb = clamp(abs(mod( 2989 | c.x * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0); 2990 | rgb = rgb * rgb * (3.0 - 2.0 * rgb); 2991 | vec3 hsv = c.z * mix(vec3(1.0), rgb, c.y); 2992 | return vec4(hsv.x, hsv.y, hsv.z, co.a); 2993 | }`, 2994 | // adapted from The Book of Shaders 2995 | rgb2hsv: `vec4 rgb2hsv(vec4 co){ 2996 | vec3 c = co.rgb; 2997 | vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); 2998 | vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); 2999 | vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); 3000 | float d = q.x - min(q.w, q.y); 3001 | float e = 1.0e-10; 3002 | return vec4(abs(q.z + (q.w - q.y) / (6.0 * d + e)), 3003 | d / (q.x + e), 3004 | q.x, co.a); 3005 | }`, 3006 | // all gaussian blurs adapted from: 3007 | // https://github.com/Jam3/glsl-fast-gaussian-blur/blob/master/5.glsl 3008 | gauss5: `vec4 gauss5(vec2 dir) { 3009 | vec2 uv = gl_FragCoord.xy / uResolution; 3010 | vec4 col = vec4(0.0); 3011 | vec2 off1 = vec2(1.3333333333333333) * dir; 3012 | col += texture2D(uSampler, uv) * 0.29411764705882354; 3013 | col += texture2D(uSampler, uv + (off1 / uResolution)) * 0.35294117647058826; 3014 | col += texture2D(uSampler, uv - (off1 / uResolution)) * 0.35294117647058826; 3015 | return col; 3016 | }`, 3017 | gauss9: `vec4 gauss9(vec2 dir) { 3018 | vec2 uv = gl_FragCoord.xy / uResolution; 3019 | vec4 col = vec4(0.0); 3020 | vec2 off1 = vec2(1.3846153846) * dir; 3021 | vec2 off2 = vec2(3.2307692308) * dir; 3022 | col += texture2D(uSampler, uv) * 0.2270270270; 3023 | col += texture2D(uSampler, uv + (off1 / uResolution)) * 0.3162162162; 3024 | col += texture2D(uSampler, uv - (off1 / uResolution)) * 0.3162162162; 3025 | col += texture2D(uSampler, uv + (off2 / uResolution)) * 0.0702702703; 3026 | col += texture2D(uSampler, uv - (off2 / uResolution)) * 0.0702702703; 3027 | return col; 3028 | }`, 3029 | gauss13: `vec4 gauss13(vec2 dir) { 3030 | vec2 uv = gl_FragCoord.xy / uResolution; 3031 | vec4 col = vec4(0.0); 3032 | vec2 off1 = vec2(1.411764705882353) * dir; 3033 | vec2 off2 = vec2(3.2941176470588234) * dir; 3034 | vec2 off3 = vec2(5.176470588235294) * dir; 3035 | col += texture2D(uSampler, uv) * 0.1964825501511404; 3036 | col += texture2D(uSampler, uv + (off1 / uResolution)) * 0.2969069646728344; 3037 | col += texture2D(uSampler, uv - (off1 / uResolution)) * 0.2969069646728344; 3038 | col += texture2D(uSampler, uv + (off2 / uResolution)) * 0.09447039785044732; 3039 | col += texture2D(uSampler, uv - (off2 / uResolution)) * 0.09447039785044732; 3040 | col += texture2D(uSampler, uv + (off3 / uResolution)) * 0.010381362401148057; 3041 | col += texture2D(uSampler, uv - (off3 / uResolution)) * 0.010381362401148057; 3042 | return col; 3043 | }`, 3044 | contrast: `vec4 contrast(float val, vec4 col) { 3045 | col.rgb /= col.a; 3046 | col.rgb = ((col.rgb - 0.5) * val) + 0.5; 3047 | col.rgb *= col.a; 3048 | return col; 3049 | }`, 3050 | brightness: `vec4 brightness(float val, vec4 col) { 3051 | col.rgb /= col.a; 3052 | col.rgb += val; 3053 | col.rgb *= col.a; 3054 | return col; 3055 | }`, 3056 | // adapted from https://www.shadertoy.com/view/ls3GWS which was adapted from 3057 | // http://www.geeks3d.com/20110405/fxaa-fast-approximate-anti-aliasing-demo-glsl-opengl-test-radeon-geforce/3/ 3058 | // original algorithm created by Timothy Lottes 3059 | fxaa: `vec4 fxaa() { 3060 | float FXAA_SPAN_MAX = 8.0; 3061 | float FXAA_REDUCE_MUL = 1.0 / FXAA_SPAN_MAX; 3062 | float FXAA_REDUCE_MIN = 1.0 / 128.0; 3063 | float FXAA_SUBPIX_SHIFT = 1.0 / 4.0; 3064 | 3065 | vec2 rcpFrame = 1. / uResolution.xy; 3066 | vec2 t_uv = gl_FragCoord.xy / uResolution.xy; 3067 | vec4 uv = vec4(t_uv, t_uv - (rcpFrame * (0.5 + FXAA_SUBPIX_SHIFT))); 3068 | 3069 | vec3 rgbNW = texture2D(uSampler, uv.zw).xyz; 3070 | vec3 rgbNE = texture2D(uSampler, uv.zw + vec2(1,0) * rcpFrame.xy).xyz; 3071 | vec3 rgbSW = texture2D(uSampler, uv.zw + vec2(0,1) * rcpFrame.xy).xyz; 3072 | vec3 rgbSE = texture2D(uSampler, uv.zw + vec2(1,1) * rcpFrame.xy).xyz; 3073 | vec4 rgbMfull = texture2D(uSampler, uv.xy); 3074 | vec3 rgbM = rgbMfull.xyz; 3075 | float alpha = rgbMfull.a; 3076 | 3077 | vec3 luma = vec3(0.299, 0.587, 0.114); 3078 | float lumaNW = dot(rgbNW, luma); 3079 | float lumaNE = dot(rgbNE, luma); 3080 | float lumaSW = dot(rgbSW, luma); 3081 | float lumaSE = dot(rgbSE, luma); 3082 | float lumaM = dot(rgbM, luma); 3083 | 3084 | float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); 3085 | float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); 3086 | 3087 | vec2 dir; 3088 | dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); 3089 | dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); 3090 | 3091 | float dirReduce = max( 3092 | (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); 3093 | float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce); 3094 | 3095 | dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), 3096 | max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), 3097 | dir * rcpDirMin)) * rcpFrame.xy; 3098 | 3099 | vec3 rgbA = (1.0 / 2.0) * ( 3100 | texture2D(uSampler, uv.xy + dir * (1.0 / 3.0 - 0.5)).xyz + 3101 | texture2D(uSampler, uv.xy + dir * (2.0 / 3.0 - 0.5)).xyz); 3102 | vec3 rgbB = rgbA * (1.0 / 2.0) + (1.0 / 4.0) * ( 3103 | texture2D(uSampler, uv.xy + dir * (0.0 / 3.0 - 0.5)).xyz + 3104 | texture2D(uSampler, uv.xy + dir * (3.0 / 3.0 - 0.5)).xyz); 3105 | 3106 | float lumaB = dot(rgbB, luma); 3107 | 3108 | if (lumaB < lumaMin || lumaB > lumaMax) { 3109 | return vec4(rgbA.r, rgbA.g, rgbA.b, alpha); 3110 | } 3111 | 3112 | return vec4(rgbB.r, rgbB.g, rgbB.b, alpha); 3113 | }`, 3114 | // normal curve is a = 0 and b = 1 3115 | gaussian: `float gaussian(float x, float a, float b) { 3116 | float e = 2.71828; 3117 | return pow(e, -pow(x - a, 2.) / b); 3118 | }`, 3119 | // for calculating the true distance from 0 to 1 depth buffer 3120 | // the small delta is to prevent division by zero, which is undefined behavior 3121 | truedepth: `float truedepth(float i) { 3122 | i = max(i, 0.00000001); 3123 | return (1. - i) / i; 3124 | }`, 3125 | // based off of https://fabiensanglard.net/lightScattering/index.php 3126 | godrays: `vec4 godrays( 3127 | vec4 col, 3128 | float exposure, 3129 | float decay, 3130 | float density, 3131 | float weight, 3132 | vec2 lightPos, 3133 | float threshold, 3134 | vec4 newColor 3135 | ) { 3136 | vec2 texCoord = gl_FragCoord.xy / uResolution; 3137 | vec2 deltaTexCoord = texCoord - lightPos; 3138 | 3139 | const int NUM_SAMPLES = 100; 3140 | deltaTexCoord *= 1. / float(NUM_SAMPLES) * density; 3141 | float illuminationDecay = 1.0; 3142 | 3143 | for (int i=0; i < NUM_SAMPLES; i++) { 3144 | texCoord -= deltaTexCoord; 3145 | vec4 sample = texture2D(uSampler, texCoord); 3146 | //uncomment sample = depth2occlusion(sample, newColor, threshold); 3147 | sample *= illuminationDecay * weight; 3148 | col += sample; 3149 | illuminationDecay *= decay; 3150 | } 3151 | return col * exposure; 3152 | }`, 3153 | depth2occlusion: `vec4 depth2occlusion(vec4 depthCol, vec4 newCol, float threshold) { 3154 | float red = 1. - ceil(depthCol.r - threshold); 3155 | return vec4(newCol.rgb * red, 1.0); 3156 | }`, 3157 | // adapted from The Book of Shaders, which was adapted from Inigo Quilez 3158 | // from this example: https://www.shadertoy.com/view/XdXGW8 3159 | gradientnoise: `float gradientnoise(vec2 st) { 3160 | vec2 i = floor(st); 3161 | vec2 f = fract(st); 3162 | 3163 | vec2 u = f * f * (3.0 - 2.0 * f); 3164 | 3165 | return mix(mix(dot(random2(i + vec2(0.0,0.0)), f - vec2(0.0, 0.0)), 3166 | dot(random2(i + vec2(1.0,0.0)), f - vec2(1.0, 0.0)), u.x), 3167 | mix(dot(random2(i + vec2(0.0,1.0)), f - vec2(0.0, 1.0)), 3168 | dot(random2(i + vec2(1.0,1.0)), f - vec2(1.0, 1.0)), u.x), u.y); 3169 | }`, 3170 | // adapted from The Book of Shaders 3171 | // https://thebookofshaders.com/edit.php#11/2d-snoise-clear.frag 3172 | // this was adapted from this fast implementation 3173 | // https://github.com/ashima/webgl-noise 3174 | // simplex noise invented by Ken Perlin 3175 | simplexnoise: `float simplexnoise(vec2 v) { 3176 | // Precompute values for skewed triangular grid 3177 | const vec4 C = vec4(0.211324865405187, 3178 | // (3.0-sqrt(3.0))/6.0 3179 | 0.366025403784439, 3180 | // 0.5*(sqrt(3.0)-1.0) 3181 | -0.577350269189626, 3182 | // -1.0 + 2.0 * C.x 3183 | 0.024390243902439); 3184 | // 1.0 / 41.0 3185 | 3186 | // First corner (x0) 3187 | vec2 i = floor(v + dot(v, C.yy)); 3188 | vec2 x0 = v - i + dot(i, C.xx); 3189 | 3190 | // Other two corners (x1, x2) 3191 | vec2 i1 = vec2(0.0); 3192 | i1 = (x0.x > x0.y)? vec2(1.0, 0.0):vec2(0.0, 1.0); 3193 | vec2 x1 = x0.xy + C.xx - i1; 3194 | vec2 x2 = x0.xy + C.zz; 3195 | 3196 | // Do some permutations to avoid 3197 | // truncation effects in permutation 3198 | i = mod289_2(i); 3199 | vec3 p = permute( 3200 | permute( i.y + vec3(0.0, i1.y, 1.0)) 3201 | + i.x + vec3(0.0, i1.x, 1.0 )); 3202 | 3203 | vec3 m = max(0.5 - vec3( 3204 | dot(x0,x0), 3205 | dot(x1,x1), 3206 | dot(x2,x2) 3207 | ), 0.0); 3208 | 3209 | m = m*m ; 3210 | m = m*m ; 3211 | 3212 | // Gradients: 3213 | // 41 pts uniformly over a line, mapped onto a diamond 3214 | // The ring size 17*17 = 289 is close to a multiple 3215 | // of 41 (41*7 = 287) 3216 | 3217 | vec3 x = 2.0 * fract(p * C.www) - 1.0; 3218 | vec3 h = abs(x) - 0.5; 3219 | vec3 ox = floor(x + 0.5); 3220 | vec3 a0 = x - ox; 3221 | 3222 | // Normalise gradients implicitly by scaling m 3223 | // Approximation of: m *= inversesqrt(a0*a0 + h*h); 3224 | m *= 1.79284291400159 - 0.85373472095314 * (a0*a0+h*h); 3225 | 3226 | // Compute final noise value at P 3227 | vec3 g = vec3(0.0); 3228 | g.x = a0.x * x0.x + h.x * x0.y; 3229 | g.yz = a0.yz * vec2(x1.x,x2.x) + h.yz * vec2(x1.y,x2.y); 3230 | return 130.0 * dot(m, g); 3231 | }`, 3232 | // only useful for simplex noise 3233 | simplexhelpers: `vec3 mod289_3(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } 3234 | vec2 mod289_2(vec2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } 3235 | vec3 permute(vec3 x) { return mod289_3(((x*34.0)+1.0)*x); }`, 3236 | // sobel adapted from https://gist.github.com/Hebali/6ebfc66106459aacee6a9fac029d0115 3237 | sobel: `vec4 sobel() { 3238 | vec2 uv = gl_FragCoord.xy / uResolution; 3239 | vec4 k[8]; 3240 | 3241 | float w = 1. / uResolution.x; 3242 | float h = 1. / uResolution.y; 3243 | 3244 | k[0] = texture2D(uSampler, uv + vec2(-w, -h)); 3245 | k[1] = texture2D(uSampler, uv + vec2(0., -h)); 3246 | k[2] = texture2D(uSampler, uv + vec2(w, -h)); 3247 | k[3] = texture2D(uSampler, uv + vec2(-w, 0.)); 3248 | 3249 | k[4] = texture2D(uSampler, uv + vec2(w, 0.)); 3250 | k[5] = texture2D(uSampler, uv + vec2(-w, h)); 3251 | k[6] = texture2D(uSampler, uv + vec2(0., h)); 3252 | k[7] = texture2D(uSampler, uv + vec2(w, h)); 3253 | 3254 | vec4 edge_h = k[2] + (2. * k[4]) + k[7] - (k[0] + (2. * k[3]) + k[5]); 3255 | vec4 edge_v = k[0] + (2. * k[1]) + k[2] - (k[5] + (2. * k[6]) + k[7]); 3256 | vec4 sob = sqrt(edge_h * edge_h + edge_v * edge_v); 3257 | 3258 | return vec4(1. - sob.rgb, 1.); 3259 | }`, 3260 | // inlining a similar function will substitute in the full expression for 3261 | // every component, so it's more efficient to have a function 3262 | monochrome: `vec4 monochrome(vec4 col) { 3263 | return vec4(vec3((col.r + col.g + col.b) / 3.), col.a); 3264 | }`, 3265 | invert: `vec4 invert(vec4 col) { 3266 | return vec4(vec3(1., 1., 1.) - col.rgb, col.a); 3267 | }`, 3268 | channel: `vec4 channel(vec2 uv, sampler2D sampler) { 3269 | return texture2D(sampler, uv); 3270 | }`, 3271 | }; 3272 | 3273 | },{}],62:[function(require,module,exports){ 3274 | "use strict"; 3275 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3276 | if (k2 === undefined) k2 = k; 3277 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 3278 | }) : (function(o, m, k, k2) { 3279 | if (k2 === undefined) k2 = k; 3280 | o[k2] = m[k]; 3281 | })); 3282 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 3283 | for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); 3284 | }; 3285 | Object.defineProperty(exports, "__esModule", { value: true }); 3286 | __exportStar(require("./mergepass"), exports); 3287 | __exportStar(require("./exprtypes"), exports); 3288 | __exportStar(require("./glslfunctions"), exports); 3289 | __exportStar(require("./settings"), exports); 3290 | __exportStar(require("./exprs/blurexpr"), exports); 3291 | __exportStar(require("./exprs/fragcolorexpr"), exports); 3292 | __exportStar(require("./exprs/vecexprs"), exports); 3293 | __exportStar(require("./exprs/opexpr"), exports); 3294 | __exportStar(require("./exprs/powerblur"), exports); 3295 | __exportStar(require("./exprs/blur2dloop"), exports); 3296 | __exportStar(require("./exprs/lenexpr"), exports); 3297 | __exportStar(require("./exprs/normexpr"), exports); 3298 | __exportStar(require("./exprs/fragcoordexpr"), exports); 3299 | __exportStar(require("./exprs/normfragcoordexpr"), exports); 3300 | __exportStar(require("./exprs/normcenterfragcoordexpr"), exports); 3301 | __exportStar(require("./exprs/scenesampleexpr"), exports); 3302 | __exportStar(require("./exprs/brightnessexpr"), exports); 3303 | __exportStar(require("./exprs/contrastexpr"), exports); 3304 | __exportStar(require("./exprs/grainexpr"), exports); 3305 | __exportStar(require("./exprs/getcompexpr"), exports); 3306 | __exportStar(require("./exprs/changecompexpr"), exports); 3307 | __exportStar(require("./exprs/rgbtohsvexpr"), exports); 3308 | __exportStar(require("./exprs/hsvtorgbexpr"), exports); 3309 | __exportStar(require("./exprs/timeexpr"), exports); 3310 | __exportStar(require("./exprs/arity1"), exports); 3311 | __exportStar(require("./exprs/arity2"), exports); 3312 | __exportStar(require("./exprs/fxaaexpr"), exports); 3313 | __exportStar(require("./exprs/channelsampleexpr"), exports); 3314 | __exportStar(require("./exprs/dofloop"), exports); 3315 | __exportStar(require("./exprs/truedepthexpr"), exports); 3316 | __exportStar(require("./exprs/godraysexpr"), exports); 3317 | __exportStar(require("./exprs/depthtoocclusionexpr"), exports); 3318 | __exportStar(require("./exprs/resolutionexpr"), exports); 3319 | __exportStar(require("./exprs/mouseexpr"), exports); 3320 | __exportStar(require("./exprs/rotateexpr"), exports); 3321 | __exportStar(require("./exprs/translateexpr"), exports); 3322 | __exportStar(require("./exprs/normmouseexpr"), exports); 3323 | __exportStar(require("./exprs/perlinexpr"), exports); 3324 | __exportStar(require("./exprs/simplexexpr"), exports); 3325 | __exportStar(require("./exprs/motionblurloop"), exports); 3326 | __exportStar(require("./exprs/randomexpr"), exports); 3327 | __exportStar(require("./exprs/sobelexpr"), exports); 3328 | __exportStar(require("./exprs/bloomloop"), exports); 3329 | __exportStar(require("./exprs/monochromeexpr"), exports); 3330 | __exportStar(require("./exprs/invertexpr"), exports); 3331 | __exportStar(require("./exprs/edgeexpr"), exports); 3332 | __exportStar(require("./exprs/edgecolorexpr"), exports); 3333 | __exportStar(require("./exprs/ternaryexpr"), exports); 3334 | __exportStar(require("./exprs/regiondecorator"), exports); 3335 | __exportStar(require("./exprs/expr"), exports); 3336 | 3337 | },{"./exprs/arity1":12,"./exprs/arity2":13,"./exprs/bloomloop":14,"./exprs/blur2dloop":15,"./exprs/blurexpr":16,"./exprs/brightnessexpr":17,"./exprs/changecompexpr":18,"./exprs/channelsampleexpr":19,"./exprs/contrastexpr":20,"./exprs/depthtoocclusionexpr":21,"./exprs/dofloop":22,"./exprs/edgecolorexpr":23,"./exprs/edgeexpr":24,"./exprs/expr":25,"./exprs/fragcolorexpr":26,"./exprs/fragcoordexpr":27,"./exprs/fxaaexpr":28,"./exprs/getcompexpr":30,"./exprs/godraysexpr":31,"./exprs/grainexpr":32,"./exprs/hsvtorgbexpr":33,"./exprs/invertexpr":34,"./exprs/lenexpr":35,"./exprs/monochromeexpr":36,"./exprs/motionblurloop":37,"./exprs/mouseexpr":38,"./exprs/normcenterfragcoordexpr":39,"./exprs/normexpr":40,"./exprs/normfragcoordexpr":41,"./exprs/normmouseexpr":42,"./exprs/opexpr":43,"./exprs/perlinexpr":44,"./exprs/powerblur":45,"./exprs/randomexpr":46,"./exprs/regiondecorator":47,"./exprs/resolutionexpr":48,"./exprs/rgbtohsvexpr":49,"./exprs/rotateexpr":50,"./exprs/scenesampleexpr":51,"./exprs/simplexexpr":53,"./exprs/sobelexpr":54,"./exprs/ternaryexpr":55,"./exprs/timeexpr":56,"./exprs/translateexpr":57,"./exprs/truedepthexpr":58,"./exprs/vecexprs":59,"./exprtypes":60,"./glslfunctions":61,"./mergepass":63,"./settings":64}],63:[function(require,module,exports){ 3338 | "use strict"; 3339 | Object.defineProperty(exports, "__esModule", { value: true }); 3340 | exports.sendTexture = exports.makeTexture = exports.Merger = exports.loop = exports.EffectLoop = exports.EffectDictionary = void 0; 3341 | const codebuilder_1 = require("./codebuilder"); 3342 | const expr_1 = require("./exprs/expr"); 3343 | const fragcolorexpr_1 = require("./exprs/fragcolorexpr"); 3344 | const regiondecorator_1 = require("./exprs/regiondecorator"); 3345 | const scenesampleexpr_1 = require("./exprs/scenesampleexpr"); 3346 | const setcolorexpr_1 = require("./exprs/setcolorexpr"); 3347 | const ternaryexpr_1 = require("./exprs/ternaryexpr"); 3348 | const settings_1 = require("./settings"); 3349 | const webglprogramloop_1 = require("./webglprogramloop"); 3350 | function wrapInSetColors(effects) { 3351 | return effects.map((e) => e instanceof expr_1.ExprVec4 || e instanceof EffectLoop ? e : new setcolorexpr_1.SetColorExpr(e)); 3352 | } 3353 | // should be function of loop? 3354 | function processEffectMap(eMap) { 3355 | const result = {}; 3356 | for (const name in eMap) { 3357 | const val = eMap[name]; 3358 | result[name] = wrapInSetColors(val); 3359 | } 3360 | return result; 3361 | } 3362 | class EffectDictionary { 3363 | constructor(effectMap) { 3364 | this.effectMap = processEffectMap(effectMap); 3365 | } 3366 | toProgramMap(gl, vShader, uniformLocs, fShaders) { 3367 | const programMap = {}; 3368 | let needs = { 3369 | neighborSample: false, 3370 | centerSample: false, 3371 | sceneBuffer: false, 3372 | timeUniform: false, 3373 | mouseUniform: false, 3374 | passCount: false, 3375 | extraBuffers: new Set(), 3376 | }; 3377 | for (const name in this.effectMap) { 3378 | const effects = this.effectMap[name]; 3379 | // wrap the given list of effects as a loop if need be 3380 | const effectLoop = new EffectLoop(effects, { num: 1 }); 3381 | if (effectLoop.effects.length === 0) { 3382 | throw new Error("list of effects was empty"); 3383 | } 3384 | const programLoop = effectLoop.genPrograms(gl, vShader, uniformLocs, fShaders); 3385 | // walk the tree to the final program 3386 | let atBottom = false; 3387 | let currProgramLoop = programLoop; 3388 | while (!atBottom) { 3389 | if (currProgramLoop.programElement instanceof webglprogramloop_1.WebGLProgramLeaf) { 3390 | // we traveled right and hit a program, so it must be the last 3391 | currProgramLoop.last = true; 3392 | atBottom = true; 3393 | } 3394 | else { 3395 | // set the current program loop to the last in the list 3396 | currProgramLoop = 3397 | currProgramLoop.programElement[currProgramLoop.programElement.length - 1]; 3398 | } 3399 | } 3400 | needs = webglprogramloop_1.updateNeeds(needs, programLoop.getTotalNeeds()); 3401 | programMap[name] = programLoop; 3402 | } 3403 | return { programMap, needs }; 3404 | } 3405 | } 3406 | exports.EffectDictionary = EffectDictionary; 3407 | /** effect loop, which can loop over other effects or effect loops */ 3408 | class EffectLoop { 3409 | constructor(effects, loopInfo) { 3410 | this.effects = wrapInSetColors(effects); 3411 | this.loopInfo = loopInfo; 3412 | } 3413 | /** @ignore */ 3414 | getSampleNum(mult = 1, sliceStart = 0, sliceEnd = this.effects.length) { 3415 | mult *= this.loopInfo.num; 3416 | let acc = 0; 3417 | const sliced = this.effects.slice(sliceStart, sliceEnd); 3418 | for (const e of sliced) { 3419 | acc += e.getSampleNum(mult); 3420 | } 3421 | return acc; 3422 | } 3423 | /** 3424 | * @ignore 3425 | * places effects into loops broken up by sampling effects 3426 | */ 3427 | regroup() { 3428 | let sampleCount = 0; 3429 | /** number of samples in all previous */ 3430 | let prevSampleCount = 0; 3431 | let prevEffects = []; 3432 | const regroupedEffects = []; 3433 | let prevTarget; 3434 | let currTarget; 3435 | let mustBreakCounter = 0; 3436 | const breakOff = () => { 3437 | mustBreakCounter--; 3438 | if (prevEffects.length > 0) { 3439 | // break off all previous effects into their own loop 3440 | if (prevEffects.length === 1) { 3441 | // this is to prevent wrapping in another effect loop 3442 | regroupedEffects.push(prevEffects[0]); 3443 | } 3444 | else { 3445 | regroupedEffects.push(new EffectLoop(prevEffects, { num: 1 })); 3446 | } 3447 | sampleCount -= prevSampleCount; 3448 | prevEffects = []; 3449 | } 3450 | }; 3451 | for (const e of this.effects) { 3452 | const sampleNum = e.getSampleNum(); 3453 | prevSampleCount = sampleCount; 3454 | sampleCount += sampleNum; 3455 | if (e instanceof EffectLoop) { 3456 | currTarget = e.loopInfo.target; 3457 | if (e.hasTargetSwitch()) { 3458 | mustBreakCounter = 2; 3459 | } 3460 | } 3461 | else { 3462 | // if it's not a loop it's assumed the target is that of outer loop 3463 | currTarget = this.loopInfo.target; 3464 | } 3465 | if (sampleCount > 0 || 3466 | currTarget !== prevTarget || 3467 | mustBreakCounter > 0) { 3468 | breakOff(); 3469 | } 3470 | prevEffects.push(e); 3471 | prevTarget = currTarget; 3472 | } 3473 | // push on all the straggling effects after the grouping is done 3474 | breakOff(); 3475 | return regroupedEffects; 3476 | } 3477 | genPrograms(gl, vShader, uniformLocs, shaders) { 3478 | // validate 3479 | const fullSampleNum = this.getSampleNum() / this.loopInfo.num; 3480 | const firstSampleNum = this.getSampleNum(undefined, 0, 1) / this.loopInfo.num; 3481 | const restSampleNum = this.getSampleNum(undefined, 1) / this.loopInfo.num; 3482 | if (!this.hasTargetSwitch() && 3483 | (fullSampleNum === 0 || (firstSampleNum === 1 && restSampleNum === 0))) { 3484 | const codeBuilder = new codebuilder_1.CodeBuilder(this); 3485 | const program = codeBuilder.compileProgram(gl, vShader, uniformLocs, shaders); 3486 | return program; 3487 | } 3488 | // otherwise, regroup and try again on regrouped loops 3489 | this.effects = this.regroup(); 3490 | return new webglprogramloop_1.WebGLProgramLoop(this.effects.map((e) => e.genPrograms(gl, vShader, uniformLocs, shaders)), this.loopInfo, gl); 3491 | } 3492 | /** 3493 | * changes the render target of an effect loop (-1 targest the scene texture; 3494 | * this is used internally) 3495 | */ 3496 | target(num) { 3497 | this.loopInfo.target = num; 3498 | return this; 3499 | } 3500 | /** @ignore */ 3501 | hasTargetSwitch() { 3502 | for (const e of this.effects) { 3503 | if (e instanceof EffectLoop) { 3504 | if (e.loopInfo.target !== this.loopInfo.target || e.hasTargetSwitch()) 3505 | return true; 3506 | } 3507 | } 3508 | return false; 3509 | } 3510 | /** @ignore */ 3511 | regionWrap(space, failure, finalPath = true, not) { 3512 | this.effects = this.effects.map((e, index) => 3513 | // loops that aren't all the way to the right can't terminate the count ternery 3514 | // don't wrap fcolors in a ternery (it's redundant) 3515 | e instanceof EffectLoop 3516 | ? e.regionWrap(space, failure, index === this.effects.length - 1, not) 3517 | : new setcolorexpr_1.SetColorExpr(regiondecorator_1.region(space, e.brandExprWithRegion(space), index === this.effects.length - 1 && finalPath 3518 | ? !(failure instanceof fragcolorexpr_1.FragColorExpr) 3519 | ? ternaryexpr_1.ternary(null, failure, fragcolorexpr_1.fcolor()) 3520 | : failure 3521 | : fragcolorexpr_1.fcolor(), not))); 3522 | return this; 3523 | } 3524 | } 3525 | exports.EffectLoop = EffectLoop; 3526 | /** creates an effect loop */ 3527 | function loop(effects, rep = 1) { 3528 | return new EffectLoop(effects, { num: rep }); 3529 | } 3530 | exports.loop = loop; 3531 | /** @ignore */ 3532 | const V_SOURCE = `attribute vec2 aPosition; 3533 | void main() { 3534 | gl_Position = vec4(aPosition, 0.0, 1.0); 3535 | }\n`; 3536 | /** class that can merge effects */ 3537 | class Merger { 3538 | /** 3539 | * constructs the object that runs the effects 3540 | * @param effects list of effects that define the final effect 3541 | * @param source the source image or texture 3542 | * @param gl the target rendering context 3543 | * @param options additional options for the texture 3544 | */ 3545 | constructor(effects, source, gl, options) { 3546 | this.uniformLocs = {}; 3547 | /** additional channels */ 3548 | this.channels = []; 3549 | this.fShaders = []; 3550 | this.textureMode = source instanceof WebGLTexture; 3551 | // set channels if provided with channels 3552 | if ((options === null || options === void 0 ? void 0 : options.channels) !== undefined) 3553 | this.channels = options === null || options === void 0 ? void 0 : options.channels; 3554 | if (!(effects instanceof EffectDictionary)) { 3555 | effects = new EffectDictionary({ default: effects }); 3556 | } 3557 | // add the copy to scene texture if in texture mode 3558 | if (this.textureMode) { 3559 | if (settings_1.settings.verbosity > 1) { 3560 | console.log("we are in texture mode!"); 3561 | } 3562 | for (const name in effects.effectMap) { 3563 | const list = effects.effectMap[name]; 3564 | list.unshift(loop([scenesampleexpr_1.input()]).target(-1)); 3565 | } 3566 | } 3567 | this.source = source; 3568 | this.gl = gl; 3569 | this.options = options; 3570 | // set the viewport 3571 | this.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight); 3572 | // set up the vertex buffer 3573 | const vertexBuffer = this.gl.createBuffer(); 3574 | if (vertexBuffer === null) { 3575 | throw new Error("problem creating vertex buffer"); 3576 | } 3577 | this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer); 3578 | const vertexArray = [-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]; 3579 | const triangles = new Float32Array(vertexArray); 3580 | this.gl.bufferData(this.gl.ARRAY_BUFFER, triangles, this.gl.STATIC_DRAW); 3581 | // save the vertex buffer reference just so we can delete it later 3582 | this.vertexBuffer = vertexBuffer; 3583 | // compile the simple vertex shader (2 big triangles) 3584 | const vShader = this.gl.createShader(this.gl.VERTEX_SHADER); 3585 | if (vShader === null) { 3586 | throw new Error("problem creating the vertex shader"); 3587 | } 3588 | // save the vertex shader reference just so we can delete it later 3589 | this.vShader = vShader; 3590 | this.gl.shaderSource(vShader, V_SOURCE); 3591 | this.gl.compileShader(vShader); 3592 | // make textures 3593 | this.tex = { 3594 | // make the front texture the source if we're given a texture instead of 3595 | // an image 3596 | back: { 3597 | name: "orig_back", 3598 | tex: source instanceof WebGLTexture 3599 | ? source 3600 | : makeTexture(this.gl, this.options), 3601 | }, 3602 | front: { name: "orig_front", tex: makeTexture(this.gl, this.options) }, 3603 | scene: undefined, 3604 | bufTextures: [], 3605 | }; 3606 | // create the framebuffer 3607 | const framebuffer = gl.createFramebuffer(); 3608 | if (framebuffer === null) { 3609 | throw new Error("problem creating the framebuffer"); 3610 | } 3611 | this.framebuffer = framebuffer; 3612 | const { programMap, needs } = effects.toProgramMap(this.gl, this.vShader, this.uniformLocs, this.fShaders); 3613 | this.programMap = programMap; 3614 | if (needs.sceneBuffer || this.textureMode) { 3615 | // we always create a scene texture if we're in texture mode 3616 | this.tex.scene = { 3617 | name: "scene", 3618 | tex: makeTexture(this.gl, this.options), 3619 | }; 3620 | } 3621 | if (programMap["default"] === undefined) { 3622 | throw new Error("no default program"); 3623 | } 3624 | this.programLoop = programMap["default"]; 3625 | // create x amount of empty textures based on buffers needed 3626 | const channelsNeeded = Math.max(...needs.extraBuffers) + 1; 3627 | const channelsSupplied = this.channels.length; 3628 | if (channelsNeeded > channelsSupplied) { 3629 | throw new Error("not enough channels supplied for this effect"); 3630 | } 3631 | for (let i = 0; i < this.channels.length; i++) { 3632 | const texOrImage = this.channels[i]; 3633 | if (!(texOrImage instanceof WebGLTexture)) { 3634 | // create a new texture; we will update this with the image source every draw 3635 | const texture = makeTexture(this.gl, this.options); 3636 | this.tex.bufTextures.push({ name: "tex_channel_" + i, tex: texture }); 3637 | } 3638 | else { 3639 | // this is already a texture; the user will handle updating this 3640 | this.tex.bufTextures.push({ 3641 | name: "img_channel_" + i, 3642 | tex: texOrImage, 3643 | }); 3644 | } 3645 | } 3646 | if (settings_1.settings.verbosity > 0) { 3647 | console.log(effects); 3648 | console.log(this.programMap); 3649 | } 3650 | } 3651 | /** 3652 | * use the source and channels to draw effect to target context; mouse 3653 | * position (as with all positions) are stored from the bottom left corner as 3654 | * this is how texture data is stored 3655 | * @param timeVal number to set the time uniform to (supply this if you plan to 3656 | * use [[time]]) 3657 | * @param mouseX the x position of the mouse (supply this if you plan to use 3658 | * [[mouse]] or [[nmouse]]) 3659 | * @param mouseY the y position of the mouse (supply this if you plan to use 3660 | * [[mouse]] or [[nmouse]]) 3661 | */ 3662 | draw(timeVal = 0, mouseX = 0, mouseY = 0) { 3663 | this.gl.activeTexture(this.gl.TEXTURE0 + settings_1.settings.offset); 3664 | this.gl.bindTexture(this.gl.TEXTURE_2D, this.tex.back.tex); 3665 | sendTexture(this.gl, this.source); 3666 | // TODO only do unbinding and rebinding in texture mode 3667 | // TODO see if we need to unbind 3668 | this.gl.bindTexture(this.gl.TEXTURE_2D, null); 3669 | // bind the scene buffer 3670 | if (this.programLoop.getTotalNeeds().sceneBuffer && 3671 | this.tex.scene !== undefined) { 3672 | this.gl.activeTexture(this.gl.TEXTURE1 + settings_1.settings.offset); 3673 | this.gl.bindTexture(this.gl.TEXTURE_2D, this.tex.scene.tex); 3674 | sendTexture(this.gl, this.source); 3675 | // TODO see if we need to unbind 3676 | this.gl.bindTexture(this.gl.TEXTURE_2D, null); 3677 | } 3678 | // bind the additional buffers 3679 | let counter = 0; 3680 | for (const b of this.channels) { 3681 | // TODO check for texture limit 3682 | this.gl.activeTexture(this.gl.TEXTURE2 + counter + settings_1.settings.offset); 3683 | this.gl.bindTexture(this.gl.TEXTURE_2D, this.tex.bufTextures[counter].tex); 3684 | sendTexture(this.gl, b); 3685 | // TODO see if we need to unbind (this gets rid of the error) 3686 | this.gl.bindTexture(this.gl.TEXTURE_2D, null); 3687 | counter++; 3688 | } 3689 | this.programLoop.run(this.gl, this.tex, this.framebuffer, this.uniformLocs, this.programLoop.last, { timeVal: timeVal, mouseX: mouseX, mouseY: mouseY }); 3690 | } 3691 | /** 3692 | * delete all resources created by construction of this [[Merger]]; use right before 3693 | * intentionally losing a reference to this merger object. this is useful if you want 3694 | * to construct another [[Merger]] to use new effects 3695 | */ 3696 | delete() { 3697 | // TODO do we have to do something with VertexAttribArray? 3698 | // call bind with null on all textures 3699 | for (let i = 0; i < 2 + this.tex.bufTextures.length; i++) { 3700 | // this gets rid of final texture, scene texture and channels 3701 | this.gl.activeTexture(this.gl.TEXTURE0 + i + settings_1.settings.offset); 3702 | this.gl.bindTexture(this.gl.TEXTURE_2D, null); 3703 | } 3704 | // call bind with null on all vertex buffers (just 1) 3705 | this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null); 3706 | // call bind with null on all frame buffers (just 1) 3707 | // (this might be redundant because this happens at end of draw call) 3708 | this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null); 3709 | // delete all programs 3710 | this.programLoop.delete(this.gl); 3711 | // delete all textures 3712 | this.gl.deleteTexture(this.tex.front.tex); 3713 | this.gl.deleteTexture(this.tex.back.tex); 3714 | for (const c of this.tex.bufTextures) { 3715 | this.gl.deleteTexture(c.tex); 3716 | } 3717 | // delete all vertex buffers (just 1) 3718 | this.gl.deleteBuffer(this.vertexBuffer); 3719 | // delete all frame buffers (just 1) 3720 | this.gl.deleteFramebuffer(this.framebuffer); 3721 | // delete all vertex shaders (just 1) 3722 | this.gl.deleteShader(this.vShader); 3723 | // delete all fragment shaders 3724 | for (const f of this.fShaders) { 3725 | this.gl.deleteShader(f); 3726 | } 3727 | } 3728 | /** 3729 | * changes the current program loop 3730 | * @param str key in the program map 3731 | */ 3732 | changeProgram(str) { 3733 | if (this.programMap[str] === undefined) { 3734 | throw new Error(`program "${str}" doesn't exist on this merger`); 3735 | } 3736 | this.programLoop = this.programMap[str]; 3737 | } 3738 | } 3739 | exports.Merger = Merger; 3740 | /** creates a texture given a context and options */ 3741 | function makeTexture(gl, options) { 3742 | const texture = gl.createTexture(); 3743 | if (texture === null) { 3744 | throw new Error("problem creating texture"); 3745 | } 3746 | // flip the order of the pixels, or else it displays upside down 3747 | gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); 3748 | // bind the texture after creating it 3749 | gl.bindTexture(gl.TEXTURE_2D, texture); 3750 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.drawingBufferWidth, gl.drawingBufferHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 3751 | const filterMode = (f) => f === undefined || f === "linear" ? gl.LINEAR : gl.NEAREST; 3752 | // how to map texture element 3753 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filterMode(options === null || options === void 0 ? void 0 : options.minFilterMode)); 3754 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filterMode(options === null || options === void 0 ? void 0 : options.maxFilterMode)); 3755 | if ((options === null || options === void 0 ? void 0 : options.edgeMode) !== "wrap") { 3756 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 3757 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 3758 | } 3759 | return texture; 3760 | } 3761 | exports.makeTexture = makeTexture; 3762 | /** copies onto texture */ 3763 | function sendTexture(gl, src) { 3764 | // if you are using textures instead of images, the user is responsible for 3765 | // updating that texture, so just return 3766 | if (src instanceof WebGLTexture || src === null) 3767 | return; 3768 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, src); 3769 | } 3770 | exports.sendTexture = sendTexture; 3771 | 3772 | },{"./codebuilder":11,"./exprs/expr":25,"./exprs/fragcolorexpr":26,"./exprs/regiondecorator":47,"./exprs/scenesampleexpr":51,"./exprs/setcolorexpr":52,"./exprs/ternaryexpr":55,"./settings":64,"./webglprogramloop":66}],64:[function(require,module,exports){ 3773 | "use strict"; 3774 | Object.defineProperty(exports, "__esModule", { value: true }); 3775 | exports.settings = void 0; 3776 | exports.settings = { 3777 | /** 3778 | * set to 1 if you want reasonable logging for debugging, such as the 3779 | * generated GLSL code and program tree. set to 100 if you want texture debug 3780 | * info (you probably don't want to do this, as it logs many lines every 3781 | * frame!) 3782 | */ 3783 | verbosity: 0, 3784 | /** texture offset */ 3785 | offset: 0, 3786 | }; 3787 | 3788 | },{}],65:[function(require,module,exports){ 3789 | "use strict"; 3790 | Object.defineProperty(exports, "__esModule", { value: true }); 3791 | exports.brandWithRegion = exports.brandWithChannel = exports.captureAndAppend = void 0; 3792 | const glslfunctions_1 = require("./glslfunctions"); 3793 | /** @ignore */ 3794 | function captureAndAppend(str, reg, suffix) { 3795 | const matches = str.match(reg); 3796 | if (matches === null) 3797 | throw new Error("no match in the given string"); 3798 | return str.replace(reg, matches[0] + suffix); 3799 | } 3800 | exports.captureAndAppend = captureAndAppend; 3801 | /** @ignore */ 3802 | function nameExtractor(sourceLists, extra) { 3803 | const origFuncName = sourceLists.sections[0]; 3804 | const ending = origFuncName[origFuncName.length - 1] === ")" ? ")" : ""; 3805 | const newFuncName = origFuncName.substr(0, origFuncName.length - 1 - ~~(ending === ")")) + 3806 | extra + 3807 | "(" + 3808 | ending; 3809 | return { origFuncName, newFuncName, ending }; 3810 | } 3811 | /** @ignore */ 3812 | function brandWithChannel(sourceLists, funcs, needs, funcIndex, samplerNum) { 3813 | samplerNum === undefined || samplerNum === -1 3814 | ? (needs.neighborSample = true) 3815 | : (needs.extraBuffers = new Set([samplerNum])); 3816 | if (samplerNum === undefined || samplerNum === -1) 3817 | return; 3818 | const { origFuncName, newFuncName, ending } = nameExtractor(sourceLists, samplerNum !== undefined ? "_" + samplerNum : ""); 3819 | sourceLists.sections[0] = sourceLists.sections[0] 3820 | .split(origFuncName) 3821 | .join(newFuncName); 3822 | funcs[funcIndex] = funcs[funcIndex] 3823 | .split(origFuncName) 3824 | .join(newFuncName) 3825 | .split("uSampler") 3826 | .join("uBufferSampler" + samplerNum); 3827 | } 3828 | exports.brandWithChannel = brandWithChannel; 3829 | /** @ignore */ 3830 | function brandWithRegion(expr, funcIndex, space) { 3831 | // if it's not a rectangle region we can't do anything so just return 3832 | if (!Array.isArray(space)) 3833 | return; 3834 | const sourceLists = expr.sourceLists; 3835 | const funcs = expr.externalFuncs; 3836 | const needs = expr.needs; 3837 | if (expr.regionBranded || 3838 | (!needs.neighborSample && needs.extraBuffers.size === 0)) 3839 | return; 3840 | const { origFuncName, newFuncName, ending } = nameExtractor(sourceLists, "_region"); 3841 | const openFuncName = newFuncName.substr(0, newFuncName.length - ~~(ending === ")")); 3842 | const newFuncDeclaration = openFuncName + 3843 | "float r_x_min, float r_y_min, float r_x_max, float r_y_max" + 3844 | (ending === ")" ? ")" : ", "); 3845 | const origTextureName = "texture2D("; 3846 | const newTextureName = "texture2D_region(r_x_min, r_y_min, r_x_max, r_y_max, "; 3847 | // replace name in the external function and `texture2D` and sampler 3848 | // (assumes the sampling function is the first external function) 3849 | funcs[funcIndex] = funcs[funcIndex] 3850 | .split(origFuncName) 3851 | .join(newFuncDeclaration) 3852 | .split(origTextureName) 3853 | .join(newTextureName); 3854 | // shift the original name off the list 3855 | sourceLists.sections.shift(); 3856 | // add the close paren if we're opening up a function with 0 args 3857 | if (ending === ")") 3858 | sourceLists.sections.unshift(")"); 3859 | // add commas (one less if it is a 0 arg function call) 3860 | for (let i = 0; i < 4 - ~~(ending === ")"); i++) { 3861 | sourceLists.sections.unshift(", "); 3862 | } 3863 | // add the new name to the beginning of the list 3864 | sourceLists.sections.unshift(newFuncName.substr(0, newFuncName.length - ~~(ending === ")"))); 3865 | // add values from region data 3866 | sourceLists.values.unshift(...space); 3867 | // put the texture access wrapper at the beginning 3868 | funcs.unshift(glslfunctions_1.glslFuncs.texture2D_region); 3869 | expr.regionBranded = true; 3870 | } 3871 | exports.brandWithRegion = brandWithRegion; 3872 | 3873 | },{"./glslfunctions":61}],66:[function(require,module,exports){ 3874 | "use strict"; 3875 | Object.defineProperty(exports, "__esModule", { value: true }); 3876 | exports.WebGLProgramLoop = exports.WebGLProgramLeaf = exports.updateNeeds = void 0; 3877 | const settings_1 = require("./settings"); 3878 | // update me on change to needs 3879 | function updateNeeds(acc, curr) { 3880 | return { 3881 | neighborSample: acc.neighborSample || curr.neighborSample, 3882 | centerSample: acc.centerSample || curr.centerSample, 3883 | sceneBuffer: acc.sceneBuffer || curr.sceneBuffer, 3884 | timeUniform: acc.timeUniform || curr.timeUniform, 3885 | mouseUniform: acc.mouseUniform || curr.mouseUniform, 3886 | passCount: acc.passCount || curr.passCount, 3887 | extraBuffers: new Set([...acc.extraBuffers, ...curr.extraBuffers]), 3888 | }; 3889 | } 3890 | exports.updateNeeds = updateNeeds; 3891 | class WebGLProgramLeaf { 3892 | constructor(program, totalNeeds, effects) { 3893 | this.program = program; 3894 | this.totalNeeds = totalNeeds; 3895 | this.effects = effects; 3896 | } 3897 | } 3898 | exports.WebGLProgramLeaf = WebGLProgramLeaf; 3899 | /** @ignore */ 3900 | function getLoc(programElement, gl, name) { 3901 | gl.useProgram(programElement.program); 3902 | const loc = gl.getUniformLocation(programElement.program, name); 3903 | if (loc === null) { 3904 | throw new Error("could not get the " + name + " uniform location"); 3905 | } 3906 | return loc; 3907 | } 3908 | /** recursive data structure of compiled programs */ 3909 | class WebGLProgramLoop { 3910 | constructor(programElement, loopInfo, gl) { 3911 | //effects: Expr[]; 3912 | this.last = false; 3913 | this.counter = 0; 3914 | this.programElement = programElement; 3915 | this.loopInfo = loopInfo; 3916 | if (this.programElement instanceof WebGLProgramLeaf) { 3917 | if (gl === undefined) { 3918 | throw new Error("program element is a program but context is undefined"); 3919 | } 3920 | if (this.programElement.totalNeeds.timeUniform) { 3921 | this.timeLoc = getLoc(this.programElement, gl, "uTime"); 3922 | } 3923 | if (this.programElement.totalNeeds.mouseUniform) { 3924 | this.mouseLoc = getLoc(this.programElement, gl, "uMouse"); 3925 | } 3926 | if (this.programElement.totalNeeds.passCount) { 3927 | this.countLoc = getLoc(this.programElement, gl, "uCount"); 3928 | } 3929 | } 3930 | } 3931 | /** get all needs from all programs */ 3932 | getTotalNeeds() { 3933 | // go through needs of program loop 3934 | if (!(this.programElement instanceof WebGLProgramLeaf)) { 3935 | const allNeeds = []; 3936 | for (const p of this.programElement) { 3937 | allNeeds.push(p.getTotalNeeds()); 3938 | } 3939 | return allNeeds.reduce(updateNeeds); 3940 | } 3941 | return this.programElement.totalNeeds; 3942 | } 3943 | /** 3944 | * recursively uses all programs in the loop, binding the appropriate 3945 | * textures and setting the appropriate uniforms; the user should only have 3946 | * to call [[draw]] on [[Merger]] and never this function directly 3947 | */ 3948 | run(gl, tex, framebuffer, uniformLocs, last, defaultUniforms, outerLoop) { 3949 | let savedTexture; 3950 | if (this.loopInfo.target !== undefined && 3951 | // if there is a target switch: 3952 | (outerLoop === null || outerLoop === void 0 ? void 0 : outerLoop.loopInfo.target) !== this.loopInfo.target) { 3953 | // swap out the back texture for the channel texture if this loop has 3954 | // an alternate render target 3955 | savedTexture = tex.back; 3956 | if (this.loopInfo.target !== -1) { 3957 | tex.back = tex.bufTextures[this.loopInfo.target]; 3958 | } 3959 | else { 3960 | if (tex.scene === undefined) { 3961 | throw new Error("tried to target -1 but scene texture was undefined"); 3962 | } 3963 | tex.back = tex.scene; 3964 | } 3965 | tex.bufTextures[this.loopInfo.target] = savedTexture; 3966 | if (settings_1.settings.verbosity > 99) 3967 | console.log("saved texture: " + savedTexture.name); 3968 | } 3969 | // setup for program leaf 3970 | if (this.programElement instanceof WebGLProgramLeaf) { 3971 | // bind the scene texture if needed 3972 | if (this.programElement.totalNeeds.sceneBuffer) { 3973 | if (tex.scene === undefined) { 3974 | throw new Error("needs scene buffer, but scene texture is somehow undefined"); 3975 | } 3976 | gl.activeTexture(gl.TEXTURE1 + settings_1.settings.offset); 3977 | if (this.loopInfo.target === -1) { 3978 | gl.bindTexture(gl.TEXTURE_2D, savedTexture.tex); 3979 | } 3980 | else { 3981 | gl.bindTexture(gl.TEXTURE_2D, tex.scene.tex); 3982 | } 3983 | } 3984 | // bind all extra channel textures if needed 3985 | for (const n of this.programElement.totalNeeds.extraBuffers) { 3986 | gl.activeTexture(gl.TEXTURE2 + n + settings_1.settings.offset); 3987 | gl.bindTexture(gl.TEXTURE_2D, tex.bufTextures[n].tex); 3988 | } 3989 | // use the current program 3990 | gl.useProgram(this.programElement.program); 3991 | // apply all uniforms 3992 | for (const effect of this.programElement.effects) { 3993 | effect.applyUniforms(gl, uniformLocs); 3994 | } 3995 | // set time uniform if needed 3996 | if (this.programElement.totalNeeds.timeUniform) { 3997 | if (this.timeLoc === undefined || 3998 | defaultUniforms.timeVal === undefined) { 3999 | throw new Error("time or location is undefined"); 4000 | } 4001 | gl.uniform1f(this.timeLoc, defaultUniforms.timeVal); 4002 | } 4003 | // set mouse uniforms if needed 4004 | if (this.programElement.totalNeeds.mouseUniform) { 4005 | if (this.mouseLoc === undefined || 4006 | defaultUniforms.mouseX === undefined || 4007 | defaultUniforms.mouseY === undefined) { 4008 | throw new Error("mouse uniform or location is undefined"); 4009 | } 4010 | gl.uniform2f(this.mouseLoc, defaultUniforms.mouseX, defaultUniforms.mouseY); 4011 | } 4012 | // set count uniform if needed 4013 | if (this.programElement.totalNeeds.passCount && outerLoop !== undefined) { 4014 | if (this.countLoc === undefined) { 4015 | throw new Error("count location is undefined"); 4016 | } 4017 | if (outerLoop !== undefined) { 4018 | gl.uniform1i(this.countLoc, outerLoop.counter); 4019 | } 4020 | this.counter++; 4021 | const mod = outerLoop === undefined ? 1 : outerLoop.loopInfo.num; 4022 | this.counter %= mod; 4023 | } 4024 | } 4025 | for (let i = 0; i < this.loopInfo.num; i++) { 4026 | const newLast = i === this.loopInfo.num - 1; 4027 | if (this.programElement instanceof WebGLProgramLeaf) { 4028 | if (newLast && last && this.last) { 4029 | // we are on the final pass of the final loop, so draw screen by 4030 | // setting to the default framebuffer 4031 | gl.bindFramebuffer(gl.FRAMEBUFFER, null); 4032 | } 4033 | else { 4034 | // we have to bounce between two textures 4035 | gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); 4036 | // use the framebuffer to write to front texture 4037 | gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex.front.tex, 0); 4038 | } 4039 | // allows us to read from `texBack` 4040 | // default sampler is 0, so `uSampler` uniform will always sample from texture 0 4041 | gl.activeTexture(gl.TEXTURE0 + settings_1.settings.offset); 4042 | gl.bindTexture(gl.TEXTURE_2D, tex.back.tex); 4043 | // use our last program as the draw program 4044 | gl.drawArrays(gl.TRIANGLES, 0, 6); 4045 | if (settings_1.settings.verbosity > 99) { 4046 | console.log("intermediate back", tex.back.name); 4047 | console.log("intermediate front", tex.front.name); 4048 | } 4049 | // swap back and front 4050 | [tex.back, tex.front] = [tex.front, tex.back]; 4051 | // deactivate and unbind all the channel textures needed 4052 | for (const n of this.programElement.totalNeeds.extraBuffers) { 4053 | gl.activeTexture(gl.TEXTURE2 + n + settings_1.settings.offset); 4054 | gl.bindTexture(gl.TEXTURE_2D, null); 4055 | } 4056 | gl.activeTexture(gl.TEXTURE1 + settings_1.settings.offset); 4057 | gl.bindTexture(gl.TEXTURE_2D, null); 4058 | } 4059 | else { 4060 | if (this.loopInfo.func !== undefined) { 4061 | this.loopInfo.func(i); 4062 | } 4063 | for (const p of this.programElement) { 4064 | p.run(gl, tex, framebuffer, uniformLocs, newLast, defaultUniforms, this // this is now the outer loop 4065 | ); 4066 | } 4067 | } 4068 | } 4069 | // swap the textures back if we were temporarily using a channel texture 4070 | if (savedTexture !== undefined) { 4071 | const target = this.loopInfo.target; 4072 | if (settings_1.settings.verbosity > 99) { 4073 | console.log("pre final back", tex.back.name); 4074 | console.log("pre final front", tex.front.name); 4075 | } 4076 | // back texture is really the front texture because it was just swapped 4077 | if (this.loopInfo.target !== -1) { 4078 | tex.bufTextures[target] = tex.back; 4079 | } 4080 | else { 4081 | if (tex.scene === undefined) { 4082 | throw new Error("tried to replace -1 but scene texture was undefined"); 4083 | } 4084 | tex.scene = tex.back; 4085 | } 4086 | tex.back = savedTexture; 4087 | if (settings_1.settings.verbosity > 99) { 4088 | console.log("post final back", tex.back.name); 4089 | console.log("post final front", tex.front.name); 4090 | console.log("channel texture", tex.bufTextures[target].name); 4091 | } 4092 | } 4093 | } 4094 | delete(gl) { 4095 | if (this.programElement instanceof WebGLProgramLeaf) { 4096 | gl.deleteProgram(this.programElement.program); 4097 | } 4098 | else { 4099 | for (const p of this.programElement) { 4100 | p.delete(gl); 4101 | } 4102 | } 4103 | } 4104 | } 4105 | exports.WebGLProgramLoop = WebGLProgramLoop; 4106 | 4107 | },{"./settings":64}]},{},[9]); 4108 | // @ts-nocheck 4109 | { 4110 | const addToProto = (pr, name, add) => { 4111 | if (p5.prototype.hasOwnProperty(name)) { 4112 | throw new Error("p5 already has this: " + name); 4113 | } 4114 | pr[name] = add; 4115 | }; 4116 | 4117 | const pr = p5.prototype; 4118 | // this avoids collisions with names in p5 and changes to camelCase 4119 | addToProto(pr, "foggyRays", MP.foggyrays); 4120 | addToProto(pr, "vignette", MP.vignette); 4121 | addToProto(pr, "blurAndTrace", MP.blurandtrace); 4122 | addToProto(pr, "lightBands", MP.lightbands); 4123 | addToProto(pr, "noiseDisplacement", MP.noisedisplacement); 4124 | addToProto(pr, "oldFilm", MP.oldfilm); 4125 | addToProto(pr, "kaleidoscope", MP.kaleidoscope); 4126 | addToProto(pr, "effectLoop", MP.loop); 4127 | addToProto(pr, "gauss", MP.gauss); 4128 | addToProto(pr, "fColor", MP.fcolor); 4129 | addToProto(pr, "vec2", MP.vec2); 4130 | addToProto(pr, "vec3", MP.vec3); 4131 | addToProto(pr, "vec4", MP.vec4); 4132 | addToProto(pr, "pVec2", MP.pvec2); 4133 | addToProto(pr, "pVec3", MP.pvec3); 4134 | addToProto(pr, "pVec4", MP.pvec4); 4135 | addToProto(pr, "op", MP.op); 4136 | addToProto(pr, "blur2d", MP.blur2d); 4137 | addToProto(pr, "len", MP.len); 4138 | addToProto(pr, "normalize", MP.norm); 4139 | addToProto(pr, "pixel", MP.pixel); 4140 | addToProto(pr, "pos", MP.pos); 4141 | addToProto(pr, "center", MP.center); 4142 | addToProto(pr, "input", MP.input); 4143 | addToProto(pr, "bright", MP.brightness); 4144 | addToProto(pr, "contrast", MP.contrast); 4145 | addToProto(pr, "grain", MP.grain); 4146 | addToProto(pr, "getComp", MP.getcomp); 4147 | addToProto(pr, "get2Comp", MP.get2comp); 4148 | addToProto(pr, "get3Comp", MP.get3comp); 4149 | addToProto(pr, "get4Comp", MP.get4comp); 4150 | addToProto(pr, "changeComp", MP.changecomp); 4151 | addToProto(pr, "rgbToHsv", MP.rgb2hsv); 4152 | addToProto(pr, "hsvToRgb", MP.hsv2rgb); 4153 | addToProto(pr, "time", MP.time); 4154 | addToProto(pr, "a1", MP.a1); 4155 | addToProto(pr, "a2", MP.a2); 4156 | addToProto(pr, "fxaa", MP.fxaa); 4157 | addToProto(pr, "channel", MP.channel); 4158 | addToProto(pr, "depthOfField", MP.dof); 4159 | addToProto(pr, "trueDepth", MP.truedepth); 4160 | addToProto(pr, "godrays", MP.godrays); 4161 | addToProto(pr, "depthToOcclusion", MP.depth2occlusion); 4162 | addToProto(pr, "resolution", MP.resolution); 4163 | addToProto(pr, "mouse", MP.mouse); 4164 | addToProto(pr, "rotate2d", MP.rotate); 4165 | addToProto(pr, "translate2d", MP.translate); 4166 | addToProto(pr, "nMouse", MP.nmouse); 4167 | addToProto(pr, "perlin", MP.perlin); 4168 | addToProto(pr, "simplex", MP.simplex); 4169 | addToProto(pr, "motionBlur", MP.motionblur); 4170 | addToProto(pr, "randomFloat", MP.random); 4171 | addToProto(pr, "sobel", MP.sobel); 4172 | addToProto(pr, "bloom", MP.bloom); 4173 | addToProto(pr, "monochrome", MP.monochrome); 4174 | addToProto(pr, "invert", MP.invert); 4175 | addToProto(pr, "edge", MP.edge); 4176 | addToProto(pr, "edgeColor", MP.edgecolor); 4177 | addToProto(pr, "ternary", MP.ternary); 4178 | addToProto(pr, "region", MP.region); 4179 | addToProto(pr, "cFloat", MP.cfloat); 4180 | addToProto(pr, "cVec2", MP.cvec2); 4181 | addToProto(pr, "cVec3", MP.cvec3); 4182 | addToProto(pr, "cVec4", MP.cvec4); 4183 | addToProto(pr, "mut", MP.mut); 4184 | addToProto(pr, "basicFloat", MP.float); 4185 | addToProto(pr, "pFloat", MP.pfloat); 4186 | addToProto(pr, "tag", MP.tag); 4187 | addToProto(pr, "celShade", MP.celshade); 4188 | 4189 | addToProto(pr, "__info", { 4190 | replaced: false, 4191 | orig: null, 4192 | canvas: null, 4193 | gl: null, 4194 | verbosity: 0, 4195 | startTime: 0, 4196 | mousePos: { x: 0, y: 0 }, 4197 | effects: [], 4198 | channels: [], 4199 | }); 4200 | 4201 | console.log(pr.__info); 4202 | 4203 | addToProto(pr, "addEffects", function () { 4204 | pr.__info.effects.push(...arguments); 4205 | }); 4206 | 4207 | addToProto(pr, "addChannels", function () { 4208 | pr.__info.channels.push(...arguments); 4209 | }); 4210 | 4211 | const info = p5.prototype.__info; 4212 | 4213 | function mpInit() { 4214 | if (info.verbosity > 0) console.log("mp init"); 4215 | } 4216 | 4217 | function mpPre() { 4218 | if (info.replaced || !info.effects) return; 4219 | if (info.verbosity > 0) console.log("mp pre x1"); 4220 | 4221 | info.startTime = new Date().getTime(); 4222 | 4223 | info.orig = document.getElementById("defaultCanvas0"); 4224 | 4225 | if (!info.orig) throw new Error("mergepass couldn't get the p5 canvas"); 4226 | const parent = info.orig.parentElement; 4227 | parent.style.position = "relative"; 4228 | 4229 | info.canvas = document.createElement("canvas"); 4230 | 4231 | info.canvas.width = info.orig.width; 4232 | info.canvas.height = info.orig.height; 4233 | info.canvas.style.width = info.orig.style.width; 4234 | info.canvas.style.height = info.orig.style.height; 4235 | 4236 | info.gl = info.canvas.getContext("webgl2"); 4237 | if (!info.gl) throw new Error("mergepass couldn't get the webgl2 context"); 4238 | 4239 | parent.appendChild(info.canvas); 4240 | 4241 | info.merger = new MP.Merger(pr.__info.effects, info.orig, info.gl, { 4242 | channels: pr.__info.channels, 4243 | }); 4244 | 4245 | const align = (c, z) => { 4246 | c.style.position = "absolute"; 4247 | c.style.left = 0; 4248 | c.style.top = 0; 4249 | c.style.zIndex = z; 4250 | }; 4251 | 4252 | align(info.canvas, 0); 4253 | align(info.orig, 1); 4254 | 4255 | info.orig.style.visibility = "hidden"; 4256 | 4257 | info.canvas.addEventListener("mousemove", (e) => { 4258 | const rect = info.orig.getBoundingClientRect(); 4259 | info.mousePos.x = 4260 | (info.canvas.width * (e.clientX - rect.left)) / rect.width; 4261 | info.mousePos.y = 4262 | (info.canvas.height * (rect.height - (e.clientY - rect.top))) / 4263 | rect.height; 4264 | }); 4265 | 4266 | info.replaced = true; 4267 | } 4268 | 4269 | function mpPost() { 4270 | if (info.verbosity > 1) console.log("mp post"); 4271 | if (!info.effects) return; 4272 | const time = info.startTime - new Date().getTime(); 4273 | info.merger.draw(time / 1000, info.mousePos.x, info.mousePos.y); 4274 | } 4275 | 4276 | p5.prototype.registerMethod("pre", mpPre); 4277 | p5.prototype.registerMethod("init", mpInit); 4278 | p5.prototype.registerMethod("post", mpPost); 4279 | } 4280 | --------------------------------------------------------------------------------