@xdadda/mini-gl
Version:
webgl image editing library with filters and effects
1,228 lines (1,141 loc) • 46 kB
JavaScript
function j(e, o) {
const { gl: t, img: r } = e;
o = o || { translateX: 0, translateY: 0, angle: 0, scale: 0, flipv: 0, fliph: 0 };
let { translateX: n, translateY: a, angle: l, scale: c, flipv: u, fliph: h } = o;
c += 1;
let s = [c, c];
const f = [
Math.round(t.canvas.width * n * 100) / 100,
Math.round(t.canvas.height * a * 100) / 100
], v = `#version 300 es
in vec2 vertex;
uniform mat3 matrix;
out vec2 texCoord;
void main() {
texCoord = vertex;
gl_Position = vec4((matrix * vec3(vertex, 1)).xy, 0, 1);
}
`, i = `#version 300 es
precision highp float;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
void main() {
outColor = texture(_texture, vec2(texCoord.x, texCoord.y));
}
`;
if (t.canvas.width === e.height) {
const C = r.width / r.height;
s[0] *= C, s[1] /= C;
}
const g = T.projection(t.canvas.width, t.canvas.height), x = T.translation(f[0], f[1]), d = T.rotation(-l * Math.PI / 180), m = T.scaling(s[0] * (-h || 1), s[1] * (-u || 1));
let p = [1, 0, 0, 0, 1, 0, 0, 0, 1];
p = T.multiply(p, g), p = T.multiply(p, x), p = T.multiply(p, T.translation(t.canvas.width / 2, t.canvas.height / 2)), p = T.multiply(p, d), p = T.multiply(p, m), p = T.multiply(p, T.translation(-t.canvas.width / 2, -t.canvas.height / 2)), p = T.multiply(p, T.scaling(t.canvas.width, t.canvas.height)), e._.$matrix = e._.$matrix || new b(t, v, i), e.runFilter(e._.$matrix, { matrix: p });
}
var T = {
projection: function(o, t) {
return [
2 / o,
0,
0,
0,
2 / t,
0,
-1,
-1,
1
];
},
translation: function(o, t) {
return [
1,
0,
0,
0,
1,
0,
o,
t,
1
];
},
rotation: function(o) {
var t = Math.cos(o), r = Math.sin(o);
return [
t,
-r,
0,
r,
t,
0,
0,
0,
1
];
},
scaling: function(o, t) {
return [
o,
0,
0,
0,
t,
0,
0,
0,
1
];
},
multiply: function(o, t) {
var r = o[0], n = o[0 * 3 + 1], a = o[0 * 3 + 2], l = o[1 * 3 + 0], c = o[1 * 3 + 1], u = o[1 * 3 + 2], h = o[2 * 3 + 0], s = o[2 * 3 + 1], f = o[2 * 3 + 2], v = t[0 * 3 + 0], i = t[0 * 3 + 1], g = t[0 * 3 + 2], x = t[1 * 3 + 0], d = t[1 * 3 + 1], m = t[1 * 3 + 2], p = t[2 * 3 + 0], C = t[2 * 3 + 1], y = t[2 * 3 + 2];
return [
v * r + i * l + g * h,
v * n + i * c + g * s,
v * a + i * u + g * f,
x * r + d * l + m * h,
x * n + d * c + m * s,
x * a + d * u + m * f,
p * r + C * l + y * h,
p * n + C * c + y * s,
p * a + C * u + y * f
];
}
};
function V(e, o, t) {
const { gl: r } = e;
t += 1;
const n = `
vec3 fromLinear(vec3 linearRGB) {
bvec3 cutoff = lessThan(linearRGB.rgb, vec3(0.0031308));
vec3 higher = vec3(1.055)*pow(linearRGB.rgb, vec3(1.0/2.4)) - vec3(0.055);
vec3 lower = linearRGB.rgb * vec3(12.92);
return vec3(mix(higher, lower, cutoff));
}
vec3 toLinear(vec3 sRGB) {
bvec3 cutoff = lessThan(sRGB.rgb, vec3(0.04045));
vec3 higher = pow((sRGB.rgb + vec3(0.055))/vec3(1.055), vec3(2.4));
vec3 lower = sRGB.rgb/vec3(12.92);
return vec3(mix(higher, lower, cutoff));
}`;
if (o.type === "1") {
const a = `#version 300 es
precision highp float;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
uniform sampler2D map;
uniform float filterStrength;
${n}
vec4 lut(vec4 color) {
vec3 texel = color.rgb;
texel = fromLinear(texel);
float size = 33.0;
float sliceSize = 1.0 / size;
float slicePixelSize = sliceSize / size;
float sliceInnerSize = slicePixelSize * (size - 1.0);
float xOffset = 0.5 * sliceSize + texel.x * (1.0 - sliceSize);
float yOffset = 0.5 * slicePixelSize + texel.y * sliceInnerSize;
float zOffset = texel.z * (size - 1.0);
float zSlice0 = floor(zOffset);
float zSlice1 = zSlice0 + 1.0;
float s0 = yOffset + (zSlice0 * sliceSize);
float s1 = yOffset + (zSlice1 * sliceSize);
vec4 slice0Color = texture(map, vec2(xOffset, s0));
vec4 slice1Color = texture(map, vec2(xOffset, s1));
texel = mix(slice0Color, slice1Color, zOffset - zSlice0).rgb;
texel = toLinear(texel);
return vec4(texel, color.a);
}
void main() {
vec4 color = texture(_texture, texCoord);
outColor = color * (1.0 - filterStrength) + lut(color) * filterStrength;
}
`;
e._.$insta1 = e._.$insta1 || new b(r, null, a), e._.$instatxt1 = e._.$instatxt1 || new E(r), e._.$instatxt1.loadImage(o.map1, r.RGBA), e._.$instatxt1.use(1), e.runFilter(e._.$insta1, { filterStrength: t ?? 1, map: { unit: 1 } });
} else if (o.type === "2") {
const a = `#version 300 es
precision highp float;
precision highp int;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
uniform sampler2D map;
uniform sampler2D map2;
uniform float filterStrength;
${n}
vec4 lut(vec4 color) {
vec3 texel = color.rgb;
texel = fromLinear(texel);
texel.r = texture(map, vec2(texel.r, 0.5)).r;
texel.g = texture(map, vec2(texel.g, 0.5)).g;
texel.b = texture(map, vec2(texel.b, 0.5)).b;
float luma = dot(vec3(0.2126, 0.7152, 0.0722), texel);
float shadowCoeff = 0.35 * max(0.0, 1.0 - luma);
texel = mix(texel, max(vec3(0.0), 2.0 * texel - 1.0), shadowCoeff);
texel = mix(texel, vec3(luma), -0.3);
texel.r = texture(map2, vec2(texel.r, 0.5)).r;
texel.g = texture(map2, vec2(texel.g, 0.5)).g;
texel.b = texture(map2, vec2(texel.b, 0.5)).b;
texel = toLinear(texel);
return vec4(texel, color.a);
}
void main() {
vec4 color = texture(_texture, texCoord);
color = color * (1.0 - filterStrength) + lut(color) * filterStrength;
outColor = color;
}
`;
e._.$insta2 = e._.$insta2 || new b(r, null, a), e._.$instatxt1 = e._.$instatxt1 || new E(r), e._.$instatxt2 = e._.$instatxt2 || new E(r), e._.$instatxt1.loadImage(o.map1, r.RGBA), e._.$instatxt2.loadImage(o.map2, r.RGBA), e._.$instatxt1.use(1), e._.$instatxt2.use(2), e.runFilter(e._.$insta2, { filterStrength: t ?? 1, map: { unit: 1 }, map2: { unit: 2 } });
} else if (o.type === "3") {
const a = `#version 300 es
precision highp float;
precision highp int;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
uniform sampler2D map;
uniform sampler2D mapLgg;
uniform float filterStrength;
${n}
vec4 lut(vec4 color) {
vec3 texel = color.rgb;
texel = fromLinear(texel);
texel = min(texel * 1.1343, vec3(1.0));
texel.r = texture(map, vec2(texel.r, 0.5)).r;
texel.g = texture(map, vec2(texel.g, 0.5)).g;
texel.b = texture(map, vec2(texel.b, 0.5)).b;
vec3 shadowColor = vec3(0.956862, 0.0, 0.83529);
float luma = dot(vec3(0.309, 0.609, 0.082), texel);
vec3 shadowBlend = 2.0 * shadowColor * texel;
float shadowAmount = 0.6 * max(0.0, (1.0 - 4.0 * luma));
texel = mix(texel, shadowBlend, shadowAmount);
vec3 lgg;
lgg.r = texture(mapLgg, vec2(texel.r, 0.5)).r;
lgg.g = texture(mapLgg, vec2(texel.g, 0.5)).g;
lgg.b = texture(mapLgg, vec2(texel.b, 0.5)).b;
texel = mix(texel, lgg, min(1.0, 0.8 + luma));
texel = toLinear(texel);
return vec4(texel, color.a);
}
void main() {
vec4 color = texture(_texture, texCoord);
outColor = color * (1.0 - filterStrength) + lut(color) * filterStrength;
}
`;
e._.$insta3 = e._.$insta3 || new b(r, null, a), e._.$instatxt1 = e._.$instatxt1 || new E(r, 0, 0, r.RGBA, r.UNSIGNED_BYTE), e._.$instatxt1.loadImage(o.map1, r.RGBA), e._.$instatxt2 = e._.$instatxt2 || new E(r, 0, 0, r.RGBA, r.UNSIGNED_BYTE), e._.$instatxt2.loadImage(o.map2, r.RGBA), e._.$instatxt1.use(1), e._.$instatxt2.use(2), e.runFilter(e._.$insta3, { filterStrength: t ?? 1, map: { unit: 1 }, mapLgg: { unit: 2 } });
} else if (o.type === "4") {
const a = `#version 300 es
precision highp float;
precision highp int;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
uniform sampler2D map;
uniform sampler2D map2;
uniform float filterStrength;
${n}
vec4 lut(vec4 color) {
vec3 texel = color.rgb;
texel = fromLinear(texel);
texel.r = texture(map, vec2(texel.r, 0.5)).r;
texel.g = texture(map, vec2(texel.g, 0.5)).g;
texel.b = texture(map, vec2(texel.b, 0.5)).b;
vec3 desat = vec3(dot(vec3(0.7, 0.2, 0.1), texel));
texel = mix(texel, desat, 0.79);
texel = vec3(min(1.0, 1.2 * dot(vec3(0.2, 0.7, 0.1), texel)));
texel.r = texture(map2, vec2(texel.r, 0.5)).r;
texel.g = texture(map2, vec2(texel.g, 0.5)).g;
texel.b = texture(map2, vec2(texel.b, 0.5)).b;
texel = toLinear(texel);
return vec4(texel, color.a);
}
void main() {
vec4 color = texture(_texture, texCoord);
outColor = color * (1.0 - filterStrength) + lut(color) * filterStrength;
}
`;
e._.$insta4 = e._.$insta4 || new b(r, null, a), e._.$instatxt1 = e._.$instatxt1 || new E(r, 0, 0, r.RGBA, r.UNSIGNED_BYTE), e._.$instatxt1.loadImage(o.map1, r.RGBA), e._.$instatxt2 = e._.$instatxt2 || new E(r, 0, 0, r.RGBA, r.UNSIGNED_BYTE), e._.$instatxt2.loadImage(o.map2, r.RGBA), e._.$instatxt1.use(1), e._.$instatxt2.use(2), e.runFilter(e._.$insta4, { filterStrength: t ?? 1, map: { unit: 1 }, map2: { unit: 2 } });
} else if (o.type === "MTX") {
const a = `#version 300 es
precision highp float;
precision highp int;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
uniform float filterStrength;
uniform mat4 uColorMatrix;
uniform vec4 uColorOffset;
vec4 applyColorMatrix(vec4 c, mat4 m, vec4 o) {
vec4 res = (c * m) + (o * c.a);
res = clamp(res, 0.0, 1.0);
return res;
}
void main() {
vec4 color = texture(_texture, texCoord);
color = applyColorMatrix(color, uColorMatrix, uColorOffset);
outColor = color;
}
`;
let l = {
//[r,g,b,a,w]
identity: [
[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0]
],
polaroid: [
[1 + 0.438 * t, -0.062 * t, -0.062 * t, 0, 0],
[-0.122 * t, 1 + 0.378 * t, -0.122 * t, 0, 0],
[-0.016 * t, -0.016 * t, 1 + 0.483 * t, 0, 0],
[0, 0, 0, 1, 0]
],
kodachrome: [
[(1 + 0.1285582396593525 * t) * ((t / 2 + 1) / 2 + 0.5), -0.3967382283601348 * t, -0.03992559172921793 * t, 0, 0.06372958762196503 * t],
[-0.16404339962244616 * t, (1 + 0.0835251566291304 * t) * ((t / 2 + 1) / 2 + 0.5), -0.05498805115633132 * t, 0, 0.024732407896706204 * t],
[-0.16786010706155763 * t, -0.5603416277695248 * t, (1 + 0.6014850761964943 * t) * ((t / 2 + 1) / 2 + 0.5), 0, 0.03562982807460946 * t],
[0, 0, 0, 1, 0]
],
browni: [
[(1 - 0.4002976502 * t) * ((t / 1.5 + 1) / 2 + 0.5), 0.34553243048391263 * t, -0.2708298674538042 * t, 0, 0.09486385711201746 * t],
[-0.037703249837783157 * t, (1 - 0.1390422412 * t) * ((t / 1.5 + 1) / 2 + 0.5), 0.15059552388459913 * t, 0, -0.07393682996638255 * t],
[0.24113635128153335 * t, -0.07441037908422492 * t, (1 - 0.5502781794 * t) * ((t / 1.5 + 1) / 2 + 0.5), 0, -0.015124150555182566 * t],
[0, 0, 0, 1, 0]
],
vintage: [
[(1 - 0.3720654364 * t) * ((t / 1.5 + 1) / 2 + 0.5), 0.3202183420819367 * t, -0.03965408211312453 * t, 0, 0.009651285835294123 * t],
[0.02578397704808868 * t, (1 - 0.3558811356 * t) * ((t / 1.5 + 1) / 2 + 0.5), 0.03259127616149294 * t, 0, 0.007462829176470591 * t],
[0.0466055556782719 * t, -0.0851232987247891 * t, (1 - 0.4758351981 * t) * ((t / 1.5 + 1) / 2 + 0.5), 0, 0.005159190588235296 * t],
[0, 0, 0, 1, 0]
]
}, c = l.identity, u = [0, 0, 0, 0];
t && (c = Y(c, l[o.mtx], 4)), t && (u = [0, 1, 2, 3].map((f) => u[f] + l[o.mtx][f][4])), e._.$insta5 = e._.$insta5 || new b(r, null, a);
const h = c.flat(), s = u;
e.runFilter(e._.$insta5, { uColorMatrix: h, uColorOffset: s });
}
}
function Y(e, o, t = 3) {
let r = [];
for (var n = 0; n < t; n++) {
r.push([]);
for (var a = 0; a < t; a++) {
r[n].push(0);
for (var l = 0; l < t; l++)
e[n] && o[l] && (r[n][a] += e[n][l] * o[l][a]);
}
}
return r;
}
function N(e) {
var o = e.length;
this.xa = [], this.ya = [], this.u = [], this.y2 = [], e.sort(function(c, u) {
return c[0] - u[0];
});
for (var t = 0; t < o; t++)
this.xa.push(e[t][0]), this.ya.push(e[t][1]);
this.u[0] = 0, this.y2[0] = 0;
for (var t = 1; t < o - 1; ++t) {
var r = this.xa[t + 1] - this.xa[t - 1], n = (this.xa[t] - this.xa[t - 1]) / r, a = n * this.y2[t - 1] + 2;
this.y2[t] = (n - 1) / a;
var l = (this.ya[t + 1] - this.ya[t]) / (this.xa[t + 1] - this.xa[t]) - (this.ya[t] - this.ya[t - 1]) / (this.xa[t] - this.xa[t - 1]);
this.u[t] = (6 * l / r - n * this.u[t - 1]) / a;
}
this.y2[o - 1] = 0;
for (var t = o - 2; t >= 0; --t)
this.y2[t] = this.y2[t] * this.y2[t + 1] + this.u[t];
}
N.prototype.at = function(e) {
for (var o = this.ya.length, t = 0, r = o - 1; r - t > 1; ) {
var n = r + t >> 1;
this.xa[n] > e ? r = n : t = n;
}
var a = this.xa[r] - this.xa[t], l = (this.xa[r] - e) / a, c = (e - this.xa[t]) / a;
return l * this.ya[t] + c * this.ya[r] + ((l * l * l - l) * this.y2[t] + (c * c * c - c) * this.y2[r]) * (a * a) / 6;
};
function L(e) {
for (var o = new N(e), t = [], r = 0; r < 256; r++)
t.push(K(0, Math.floor(o.at(r / 255) * 256), 255));
return t;
}
function K(e, o, t) {
return Math.max(e, Math.min(o, t));
}
function Z(e, a) {
if (a.every((h) => h === null)) return;
a[0] || (a[0] = [[0, 0], [1, 1]]);
let t = a[1] || a[0], r = a[2] || a[0], n = a[3] || a[0];
if (t = L(t), r = L(r), n = L(n), t.length !== 256 || r.length !== 256 || n.length !== 256) return console.error("curves: input unknown");
for (var a = [], l = 0; l < 256; l++)
a.splice(a.length, 0, t[l], r[l], n[l], 255);
const c = `#version 300 es
precision highp float;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
uniform sampler2D curvemap;
void main() {
vec4 color = texture(_texture, texCoord);
color.r = texture(curvemap, vec2(color.r)).r;
color.g = texture(curvemap, vec2(color.g)).g;
color.b = texture(curvemap, vec2(color.b)).b;
outColor = color;
}
`, { gl: u } = e;
e._.$curvestexture = e._.$curvestexture || new E(u), e._.$curvestexture.initFromBytes(256, 1, a, u.RGBA), e._.$curvestexture.use(2), e._.$curves = e._.$curves || new b(u, null, c), e.runFilter(e._.$curves, { curvemap: { unit: 2 } });
}
function H(e, o, t, r) {
const n = `#version 300 es
precision highp float;
in vec2 texCoord;
uniform sampler2D _texture;
uniform vec2 uResolution;
uniform mat3 matrix;
uniform bool useTextureSpace;
out vec4 outColor;
void main() {
vec2 coord = texCoord * uResolution;
if (useTextureSpace) coord = coord / uResolution * 2.0 - 1.0;
vec3 warp = matrix * vec3(coord, 1.0);
coord = warp.xy / warp.z;
if (useTextureSpace) coord = (coord * 0.5 + 0.5) * uResolution;
vec4 color = texture(_texture, coord / uResolution);
vec2 clampedCoord = clamp(coord, vec2(0.0), uResolution);
if (coord != clampedCoord) {
//color.a *= max(0.0, 1.0 - length(coord - clampedCoord));
color.a = 0.;
}
outColor = color;
}
`, { gl: a, img: l } = e;
if (e._.$warp = e._.$warp || new b(a, null, n), o = Array.prototype.concat.apply([], o), o.length == 4)
o = [
o[0],
o[1],
0,
o[2],
o[3],
0,
0,
0,
1
];
else if (o.length != 9)
throw "can only warp with 2x2 or 3x3 matrix";
const c = [a.canvas.width, a.canvas.height];
e.runFilter(e._.$warp, {
matrix: t ? X(o) : o,
uResolution: c,
useTextureSpace: r | 0
});
}
function W(e, o, t, r, n) {
o = o.flat(), t = t.flat();
var a = U.apply(null, t), l = U.apply(null, o), c = q(X(a), l);
return H(e, c, r, n);
}
function U(e, o, t, r, n, a, l, c) {
var u = t - n, h = r - a, s = l - n, f = c - a, v = e - t + n - l, i = o - r + a - c, g = u * f - s * h, x = (v * f - s * i) / g, d = (u * i - v * h) / g;
return [
t - e + x * t,
r - o + x * r,
x,
l - e + d * l,
c - o + d * c,
d,
e,
o,
1
];
}
function X(e) {
var o = e[0], t = e[1], r = e[2], n = e[3], a = e[4], l = e[5], c = e[6], u = e[7], h = e[8], s = o * a * h - o * l * u - t * n * h + t * l * c + r * n * u - r * a * c;
return [
(a * h - l * u) / s,
(r * u - t * h) / s,
(t * l - r * a) / s,
(l * c - n * h) / s,
(o * h - r * c) / s,
(r * n - o * l) / s,
(n * u - a * c) / s,
(t * c - o * u) / s,
(o * a - t * n) / s
];
}
function q(e, o) {
return [
e[0] * o[0] + e[1] * o[3] + e[2] * o[6],
e[0] * o[1] + e[1] * o[4] + e[2] * o[7],
e[0] * o[2] + e[1] * o[5] + e[2] * o[8],
e[3] * o[0] + e[4] * o[3] + e[5] * o[6],
e[3] * o[1] + e[4] * o[4] + e[5] * o[7],
e[3] * o[2] + e[4] * o[5] + e[5] * o[8],
e[6] * o[0] + e[7] * o[3] + e[8] * o[6],
e[6] * o[1] + e[7] * o[4] + e[8] * o[7],
e[6] * o[2] + e[7] * o[5] + e[8] * o[8]
];
}
function Q(e, o, t) {
const { gl: r } = e, n = `#version 300 es
precision highp float;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
uniform sampler2D map;
uniform float filterStrength;
vec4 fromLinear(vec4 linearRGB) {
bvec3 cutoff = lessThan(linearRGB.rgb, vec3(0.0031308));
vec3 higher = vec3(1.055)*pow(linearRGB.rgb, vec3(1.0/2.4)) - vec3(0.055);
vec3 lower = linearRGB.rgb * vec3(12.92);
return vec4(mix(higher, lower, cutoff), linearRGB.a);
}
vec4 toLinear(vec4 sRGB) {
bvec3 cutoff = lessThan(sRGB.rgb, vec3(0.04045));
vec3 higher = pow((sRGB.rgb + vec3(0.055))/vec3(1.055), vec3(2.4));
vec3 lower = sRGB.rgb/vec3(12.92);
return vec4(mix(higher, lower, cutoff), sRGB.a);
}
void main(){
vec4 color = texture(_texture, texCoord);
vec4 texc = texture(map, texCoord);
color = toLinear(color);
texc = toLinear(texc);
color = mix(color, texc, filterStrength);
color = fromLinear(color);
outColor = color;
}`;
e._.$blend = e._.$blend || new b(r, null, n), e._.$blendtxt = e._.$blendtxt || new E(r), e._.$blendtxt.loadImage(o), e._.$blendtxt.use(1), e.runFilter(e._.$blend, { filterStrength: t ?? 1, map: { unit: 1 } });
}
function J(e, o) {
const t = `#version 300 es
//Bokeh disc. by David Hoskins.
//https://www.shadertoy.com/view/4d2Xzw
precision highp float;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
uniform float bokehstrength;
uniform float bokehlensin;
uniform float bokehlensout;
uniform float centerX;
uniform float centerY;
#define GOLDEN_ANGLE 2.39996323
#define ITERATIONS 512
const mat2 rot = mat2(cos(GOLDEN_ANGLE), sin(GOLDEN_ANGLE), -sin(GOLDEN_ANGLE), cos(GOLDEN_ANGLE));
vec3 Bokeh(sampler2D tex, vec2 uv, float radius)
{
vec3 acc = vec3(0), div = acc;
float r = 1.;
vec2 vangle = vec2(0.0,radius*.01 / sqrt(float(ITERATIONS)));
for (int j = 0; j < ITERATIONS; j++)
{
// the approx increase in the scale of sqrt(0, 1, 2, 3...)
r += 1. / r;
vangle = rot * vangle;
vec3 col = texture(tex, uv + (r-1.) * vangle).xyz; /// ... Sample the image
//col = col * col *1.8; // ... Contrast it for better highlights - leave this out elsewhere.
vec3 bokeh = pow(col, vec3(4));
acc += col * bokeh;
div += bokeh;
}
return acc / div;
}
void main() {
vec4 color = texture(_texture, texCoord);
vec4 bcolor = vec4(Bokeh(_texture, texCoord, bokehstrength), 1.);
//vignette used to control alpha
//to blur inside circle smoothstep(lensin, lensout, dist)
//to blur outside circle smoothstep(lensout, lensin, dist)
float dist = distance(texCoord.xy, vec2(centerX,centerY));
float vigfin = pow(1.-smoothstep(max(0.001,bokehlensout), bokehlensin, dist),2.);
outColor = mix( color, bcolor, vigfin);
}
`, { gl: r } = e;
let { bokehstrength: n = 0.5, bokehlensin: a = 0, bokehlensout: l = 0.5, centerX: c = 0, centerY: u = 0 } = o || {};
e._.$lensblur = e._.$lensblur || new b(r, null, t), e.runFilter(e._.$lensblur, { bokehstrength: n, bokehlensin: a, bokehlensout: l, centerX: c, centerY: u });
}
function ee(e, o) {
const t = `#version 300 es
//https://www.shadertoy.com/view/XdfGDH
precision highp float;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
uniform vec2 uResolution;
uniform float gaussianstrength;
uniform float gaussianlensin;
uniform float gaussianlensout;
uniform float centerX;
uniform float centerY;
float normpdf(in float x, in float sigma)
{
return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma;
}
void main() {
vec4 color = texture(_texture, texCoord);
//declare stuff
const int mSize = 11;
const int kSize = (mSize-1)/2;
float kernel[mSize];
vec3 final_colour = vec3(0.0);
//create the 1-D kernel
float sigma = 7.0*gaussianstrength;
float Z = 0.0;
for (int j = 0; j <= kSize; ++j)
{
kernel[kSize+j] = kernel[kSize-j] = normpdf(float(j), sigma);
}
//get the normalization factor (as the gaussian has been clamped)
for (int j = 0; j < mSize; ++j)
{
Z += kernel[j];
}
//read out the texels
for (int i=-kSize; i <= kSize; ++i)
{
for (int j=-kSize; j <= kSize; ++j)
{
final_colour += kernel[kSize+j]*kernel[kSize+i]*texture(_texture, (texCoord.xy+vec2(float(i),float(j))/uResolution)).rgb;
}
}
//vignette used to control alpha
//to blur inside circle smoothstep(lensin, lensout, dist)
//to blur outside circle smoothstep(lensout, lensin, dist)
float dist = distance(texCoord.xy, vec2(centerX,centerY));
float vigfin = pow(1.-smoothstep(max(0.001,gaussianlensout), gaussianlensin, dist),2.);
outColor = mix( color, vec4(final_colour/(Z*Z), 1.0), vigfin);
}
`, { gl: r } = e;
let { gaussianstrength: n = 0.5, gaussianlensin: a = 0, gaussianlensout: l = 0.5, centerX: c = 0, centerY: u = 0 } = o || {};
const h = [r.canvas.width, r.canvas.height];
e._.$gaussianblur = e._.$gaussianblur || new b(r, null, t), e.runFilter(e._.$gaussianblur, { gaussianstrength: n, gaussianlensin: a, gaussianlensout: l, centerX: c, centerY: u, uResolution: h });
}
function te(e, o) {
const t = `#version 300 es
precision highp float;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
uniform vec2 uTextureSize;
uniform mat4 uColorMatrix;
uniform vec4 uColorOffset;
uniform float uClarityKernel[9];
uniform float uClarityKernelWeight;
uniform float uColorGamma;
uniform float uVibrance;
uniform float uColorVignette;
uniform vec2 uVignettePos;
uniform float vibrance;
vec4 applyGamma(vec4 c, float g) {
c.r = pow(c.r, g);
c.g = pow(c.g, g);
c.b = pow(c.b, g);
return c;
}
vec4 applyVibrance(vec4 c, float v){
float max = max(c.r, max(c.g, c.b));
float avg = (c.r + c.g + c.b) / 3.0;
float amt = (abs(max - avg) * 2.0) * -v;
c.r += max != c.r ? (max - c.r) * amt : 0.00;
c.g += max != c.g ? (max - c.g) * amt : 0.00;
c.b += max != c.b ? (max - c.b) * amt : 0.00;
return c;
}
vec4 applyColorMatrix(vec4 c, mat4 m, vec4 o) {
vec4 res = (c * m) + (o * c.a);
res = clamp(res, 0.0, 1.0);
return res;
}
vec4 applyConvolutionMatrix(vec4 c, float k0, float k1, float k2, float k3, float k4, float k5, float k6, float k7, float k8, float w) {
vec2 pixel = vec2(1) / uTextureSize;
vec4 colorSum = texture(_texture, texCoord - pixel) * k0 + texture(_texture, texCoord + pixel * vec2(0.0, -1.0)) * k1 + texture(_texture, texCoord + pixel * vec2(1.0, -1.0)) * k2 + texture(_texture, texCoord + pixel * vec2(-1.0, 0.0)) * k3 + texture(_texture, texCoord) * k4 + texture(_texture, texCoord + pixel * vec2(1.0, 0.0)) * k5 + texture(_texture, texCoord + pixel * vec2(-1.0, 1.0)) * k6 + texture(_texture, texCoord + pixel * vec2(0.0, 1.0)) * k7 + texture(_texture, texCoord + pixel) * k8;
vec4 color = vec4(clamp((colorSum / w), 0.0, 1.0).rgb, c.a);
return color;
}
vec4 applyVignette2(vec4 c, vec2 pos, float v, vec2 upos){
#define inner .20
#define outer 1.1
#define curvature .65
vec2 curve = pow(abs(pos),vec2(1./curvature));
float edge = pow(length(curve),curvature);
float scale = 1.-abs(upos.x);
float vignette = 1.-v*smoothstep(inner*scale,outer*scale,edge);
vec4 color = vec4(c.rgb *= vignette , c.a);
return color;
}
vec4 vignette3(vec4 c, vec2 pos, float radius)
{
float ambientlight = 0.14;
float circle = length(pos) - radius;
float v = 1.0 - smoothstep(0.0, 0.4f, circle) + ambientlight;
return vec4(c.rgb*v,c.a);
}
void main() {
vec4 color = texture(_texture, texCoord);
if (uClarityKernelWeight != -1.0) {
color = applyConvolutionMatrix(color, uClarityKernel[0], uClarityKernel[1], uClarityKernel[2], uClarityKernel[3], uClarityKernel[4], uClarityKernel[5], uClarityKernel[6], uClarityKernel[7], uClarityKernel[8], uClarityKernelWeight);
}
color = applyGamma(color, uColorGamma);
color = applyVibrance(color, uVibrance);
color = applyColorMatrix(color, uColorMatrix, uColorOffset);
if (uColorVignette != 0.0) {
vec2 pos = texCoord.xy*2.-1. - uVignettePos;
//color = vignette3(color, pos, uColorVignette);
color = applyVignette2(color, pos, uColorVignette, uVignettePos);
}
outColor = color;
}
`, { gl: r } = e;
let n = [0, 0], { brightness: a = 0, contrast: l = 0, saturation: c = 0, exposure: u = 0, temperature: h = 0, gamma: s = 0, clarity: f = 0, vibrance: v = 0, vignette: i = 0, tint: g = 0, sepia: x = 0 } = o;
a = a / 4, l = (l + 1) / 2 + 0.5, c = c + 1, u = ((u > 0 ? u * 3 : u * 1.5) + 1) / 2 + 0.5, s += 1, h *= 2, g *= 2;
let d = {
//[r,g,b,a,w]
//brightness t (0-2)
brightness: [
[1, 0, 0, 0, a],
[0, 1, 0, 0, a],
[0, 0, 1, 0, a],
[0, 0, 0, 1, 0]
],
//constrast t (0-2)
contrast: [
[l, 0, 0, 0, 0.5 * (1 - l)],
[0, l, 0, 0, 0.5 * (1 - l)],
[0, 0, l, 0, 0.5 * (1 - l)],
[0, 0, 0, 1, 0]
],
//saturation (0-2)
saturation: [
[0.213 + 0.787 * c, 0.715 - 0.715 * c, 0.072 - 0.072 * c, 0, 0],
[0.213 - 0.213 * c, 0.715 + 0.285 * c, 0.072 - 0.072 * c, 0, 0],
[0.213 - 0.213 * c, 0.715 - 0.715 * c, 0.072 + 0.928 * c, 0, 0],
[0, 0, 0, 1, 0]
],
//exposure (0-2)
exposure: [
[u, 0, 0, 0, 0],
[0, u, 0, 0, 0],
[0, 0, u, 0, 0],
[0, 0, 0, 1, 0]
],
//temperature (-1 +1)
temperature: h > 0 ? [
[1 + 0.1 * h, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1 + 0.1 * -h, 0, 0],
[0, 0, 0, 1, 0]
] : [
[1 + 0.15 * h, 0, 0, 0, 0],
[0, 1 + 0.05 * h, 0, 0, 0],
[0, 0, 1 + 0.15 * -h, 0, 0],
[0, 0, 0, 1, 0]
],
//tint
tint: [
[1, 0, 0, 0, 0],
[0, 1 + 0.1 * g, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0]
],
//sepia
sepia: [
[1 - 0.607 * x, 0.769 * x, 0.189 * x, 0, 0],
[0.349 * x, 1 - 0.314 * x, 0.168 * x, 0, 0],
[0.272 * x, 0.534 * x, 1 - 0.869 * x, 0, 0],
[0, 0, 0, 1, 0]
],
/*
//same as saturation!
gray: [
[1-.7874*g,.7152*g,.0722*g,0,0],
[.2126*g,1-.2848*g,.0722*g,0,0],
[.2126*g,.7152*g,1-.9278*g,0,0],
[0,0,0,1,0],
],
*/
identity: [
[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0]
]
}, m = d.identity, p = [0, 0, 0, 0];
m = B(m, d.brightness, 4), p = [0, 1, 2, 3].map((S) => p[S] + d.brightness[S][4]), m = B(m, d.contrast, 4), p = [0, 1, 2, 3].map((S) => p[S] + d.contrast[S][4]), m = B(m, d.saturation, 4), m = B(m, d.exposure, 4), m = B(m, d.temperature, 4), m = B(m, d.tint, 4), m = B(m, d.sepia, 4);
let C = f >= 0 ? [
0,
-1 * f,
0,
-1 * f,
1 + 4 * f,
-1 * f,
0,
-1 * f,
0
] : [
-1 * f,
-2 * f,
-1 * f,
-2 * f,
1 + -3 * f,
-2 * f,
-1 * f,
-2 * f,
-1 * f
], y = C.reduce((S, A) => S + A, 0);
y = y <= 0 ? 1 : y, C = [C];
const z = m.flat(), D = p, I = [r.canvas.width, r.canvas.height], M = v, F = i, _ = C, w = y, R = n;
e._.$adj = e._.$adj || new b(r, null, t), e.runFilter(e._.$adj, { uColorMatrix: z, uColorOffset: D, uColorGamma: 1 / s, uClarityKernel: _, uClarityKernelWeight: w, uTextureSize: I, uVibrance: M, uColorVignette: F, uVignettePos: R });
}
function re(e, o, t) {
const r = `#version 300 es
precision highp float;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
uniform float shadows;
uniform float highlights;
const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721);
void main() {
vec4 color = texture(_texture, texCoord);
float luminance = dot(color.rgb, luminanceWeighting);
float shadow = clamp((pow(luminance, 1.0/shadows) + (-0.76)*pow(luminance, 2.0/shadows)) - luminance, 0.0, 1.0);
float highlight = clamp((1.0 - (pow(1.0-luminance, 1.0/(2.0-highlights)) + (-0.8)*pow(1.0-luminance, 2.0/(2.0-highlights)))) - luminance, -1.0, 0.0);
vec3 result = vec3(0.0, 0.0, 0.0) + (luminance + shadow + highlight) * ((color.rgb - vec3(0.0, 0.0, 0.0))/luminance );
// blend toward white if highlights is more than 1
float contrastedLuminance = ((luminance - 0.5) * 1.5) + 0.5;
float whiteInterp = contrastedLuminance*contrastedLuminance*contrastedLuminance;
float whiteTarget = clamp(highlights, 0.0, 2.0) - 1.0;
result = mix(result, vec3(1.0), whiteInterp*whiteTarget);
// blend toward black if shadows is less than 1
float invContrastedLuminance = 1.0 - contrastedLuminance;
float blackInterp = invContrastedLuminance*invContrastedLuminance*invContrastedLuminance;
float blackTarget = 1.0 - clamp(shadows, 0.0, 1.0);
result = mix(result, vec3(0.0), blackInterp*blackTarget);
outColor = vec4(result, color.a);
}
`, { gl: n } = e;
e._.$sg = e._.$sg || new b(n, null, r), e.runFilter(e._.$sg, { highlights: o + 1, shadows: t / 2 + 1 });
}
function oe(e, o) {
const t = `#version 300 es
precision highp float;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
uniform vec2 uResolution;
uniform float filterStrength;
vec4 BlurColor (in vec2 Coord, in sampler2D Tex, in float MipBias)
{
vec2 TexelSize = MipBias/uResolution.xy;
vec4 Color = texture(Tex, Coord, MipBias);
Color += texture(Tex, Coord + vec2(TexelSize.x,0.0), MipBias);
Color += texture(Tex, Coord + vec2(-TexelSize.x,0.0), MipBias);
Color += texture(Tex, Coord + vec2(0.0,TexelSize.y), MipBias);
Color += texture(Tex, Coord + vec2(0.0,-TexelSize.y), MipBias);
Color += texture(Tex, Coord + vec2(TexelSize.x,TexelSize.y), MipBias);
Color += texture(Tex, Coord + vec2(-TexelSize.x,TexelSize.y), MipBias);
Color += texture(Tex, Coord + vec2(TexelSize.x,-TexelSize.y), MipBias);
Color += texture(Tex, Coord + vec2(-TexelSize.x,-TexelSize.y), MipBias);
return Color/9.0;
}
void main() {
float Threshold = 0.4;
float Intensity = filterStrength*1.0;
float BlurSize = 3.0 * Intensity;
vec4 color = texture(_texture, texCoord);
vec4 Highlight = clamp(BlurColor(texCoord.xy, _texture, BlurSize)-Threshold,0.0,1.0)*1.0/(1.0-Threshold);
outColor = 1.0-(1.0-color)*(1.0-Highlight*Intensity); //Screen Blend Mode
}
`, { gl: r } = e, n = [r.canvas.width, r.canvas.height];
e._.$bloom = e._.$bloom || new b(r, null, t), e.runFilter(e._.$bloom, { filterStrength: o, uResolution: n });
}
function ae(e, o) {
const t = `#version 300 es
precision highp float;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
uniform vec2 uResolution;
uniform float filterStrength;
#define SIGMA 10.0
#define BSIGMA 0.1
#define MSIZE 15
float normpdf(in float x, in float sigma)
{
return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma;
}
float normpdf3(in vec3 v, in float sigma)
{
return 0.39894*exp(-0.5*dot(v,v)/(sigma*sigma))/sigma;
}
vec4 applyFilter(vec4 c, sampler2D _texture, vec2 texCoord) {
const int kSize = (MSIZE-1)/2;
float kernel[MSIZE] = float[MSIZE](0.031225216, 0.033322271, 0.035206333, 0.036826804, 0.038138565, 0.039104044, 0.039695028, 0.039894000, 0.039695028, 0.039104044, 0.038138565, 0.036826804, 0.035206333, 0.033322271, 0.031225216);
vec3 final_colour = vec3(0.0);
vec3 cc;
float factor;
float Z = 0.0;
float bZ = 1.0/normpdf(0.0, BSIGMA);
for (int i=-kSize; i <= kSize; ++i)
{
for (int j=-kSize; j <= kSize; ++j)
{
cc = texture(_texture, (texCoord.xy+vec2(float(i),float(j))/uResolution)).rgb;
factor = normpdf3(cc-c.rgb, BSIGMA)*bZ*kernel[kSize+j]*kernel[kSize+i];
Z += factor;
final_colour += factor*cc;
}
}
return vec4(final_colour/Z, 1.0);
}
void main() {
vec4 color = texture(_texture, texCoord);
color = color * (1.0 - filterStrength) + applyFilter(color, _texture, texCoord) * filterStrength;
outColor = color;
}
`, { gl: r } = e, n = [r.canvas.width, r.canvas.height];
e._.$noise = e._.$noise || new b(r, null, t), e.runFilter(e._.$noise, { filterStrength: o, uResolution: n });
}
function B(e, o, t = 3) {
let r = [];
for (var n = 0; n < t; n++) {
r.push([]);
for (var a = 0; a < t; a++) {
r[n].push(0);
for (var l = 0; l < t; l++)
e[n] && o[l] && (r[n][a] += e[n][l] * o[l][a]);
}
}
return r;
}
const P = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
filterAdjustments: te,
filterBlend: Q,
filterBloom: oe,
filterBlurBokeh: J,
filterBlurGaussian: ee,
filterCurves: Z,
filterHighlightsShadows: re,
filterInsta: V,
filterMatrix: j,
filterNoise: ae,
filterPerspective: W
}, Symbol.toStringTag, { value: "Module" }));
function le(e, o, t) {
let r = e.getContext("webgl2", { antialias: !1, premultipliedAlpha: !0 });
if (!r) return console.error("webgl2 not supported!");
t === "display-p3" ? (r.drawingBufferColorSpace = "display-p3", r.unpackColorSpace = "display-p3") : (r.drawingBufferColorSpace = "srgb", r.unpackColorSpace = "srgb");
const n = {
width: 0,
height: 0,
gl: r,
img: o,
destroy: f,
loadImage: g,
paintCanvas: x,
crop: z,
resetCrop: D,
resize: m,
resetResize: p,
captureImage: I,
readPixels: M,
runFilter: i,
setupFiltersTextures: s,
_: {}
//for filters' storage
};
r.canvas.width = n.width = o.width, r.canvas.height = n.height = o.height;
const a = new E(r);
a.loadImage(o);
const l = new b(r), c = new b(r, null, ne);
let u, h = 0;
function s() {
u?.length && u.forEach((w) => w.destroy()), u = [];
for (var _ = 0; _ < 2; ++_) {
const w = new E(r, r.canvas.width, r.canvas.height);
u.push(w);
}
}
s();
function f() {
u?.length && u.forEach((_) => _.destroy()), C && C.destroy(), a.destroy(), delete n.img_cropped;
}
let v;
function i(_, w) {
w && _.uniforms(w), v && v.use(), u[h % 2].drawTo(), _.drawRect(), v = u[h % 2], h++;
}
function g() {
C ? v = C : v = a, i(l, null);
}
function x() {
v && v.use(), r.bindFramebuffer(r.FRAMEBUFFER, null), c.drawRect();
}
let d = { width: 0, height: 0 };
function m(_, w) {
r.canvas.width = n.width = d.width = _, r.canvas.height = n.height = d.height = w, s();
}
function p() {
d.width && (d.width = d.height = 0, r.canvas.width = n.width = y.width || o.width, r.canvas.height = n.height = y.height || o.height, s());
}
let C, y = { width: 0, height: 0 };
function z({ left: _, top: w, width: R, height: S }) {
const A = R * S * 4, $ = new Uint8Array(A);
i(l, {}), r.readPixels(_, w, R, S, r.RGBA, r.UNSIGNED_BYTE, $);
const G = r.unpackColorSpace, k = new ImageData(new Uint8ClampedArray($.buffer), R, S, { colorSpace: G });
C = new E(r), C.loadImage(k), r.canvas.width = n.width = y.width = R, r.canvas.height = n.height = y.height = S, s(), n.img_cropped = O(k, G);
}
function D() {
C && (C.destroy(), C = null, y.width = y.height = 0, r.canvas.width = n.width = d.width || o.width, r.canvas.height = n.height = d.height || o.height, delete n.img_cropped, s());
}
function I(_, w) {
i(l, {});
const { width: R, height: S } = r.canvas, A = R * S * 4, $ = new Uint8Array(A);
r.readPixels(0, 0, R, S, r.RGBA, r.UNSIGNED_BYTE, $);
const G = r.unpackColorSpace, k = new ImageData(new Uint8ClampedArray($.buffer), R, S, { colorSpace: G });
return O(k, G, _, w);
}
function M() {
i(l, {});
const { width: _, height: w } = r.canvas, R = _ * w * 4, S = new Uint8Array(R);
return r.readPixels(0, 0, _, w, r.RGBA, r.UNSIGNED_BYTE, S), S;
}
function F(_) {
return function(...w) {
_(n, ...w);
};
}
return Object.keys(P).forEach((_) => n[_] = F(P[_])), n;
}
const ne = `#version 300 es
precision highp float;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
vec4 fromLinear(vec4 linearRGB) {
bvec3 cutoff = lessThan(linearRGB.rgb, vec3(0.0031308));
vec3 higher = vec3(1.055)*pow(linearRGB.rgb, vec3(1.0/2.4)) - vec3(0.055);
vec3 lower = linearRGB.rgb * vec3(12.92);
return vec4(mix(higher, lower, cutoff), linearRGB.a);
}
void main() {
vec4 color = texture(_texture, vec2(texCoord.x, 1.0 - texCoord.y));
//outColor = color;
outColor = fromLinear(color);
}`;
function b(e, o, t) {
const r = `#version 300 es
in vec2 vertex;
out vec2 texCoord;
void main() {
texCoord = vertex;
gl_Position = vec4(vertex * 2.0 - 1.0, 0.0, 1.0);
}
`, n = `#version 300 es
precision highp float;
in vec2 texCoord;
uniform sampler2D _texture;
out vec4 outColor;
void main() {
outColor = texture(_texture, texCoord);
}
`, a = e.createProgram();
let l;
e.attachShader(a, h(e, e.VERTEX_SHADER, o || r)), e.attachShader(a, h(e, e.FRAGMENT_SHADER, t || n)), e.linkProgram(a);
function c(s = !0, f, v, i, g) {
const x = e.getParameter(e.VIEWPORT);
f = f !== void 0 ? (f - x[0]) / x[2] : 0, v = v !== void 0 ? (v - x[1]) / x[3] : 0, i = i !== void 0 ? (i - x[0]) / x[2] : 1, g = g !== void 0 ? (g - x[1]) / x[3] : 1, e.useProgram(a), e.vertexBuffer = e.vertexBuffer || e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, e.vertexBuffer), e.bufferData(
e.ARRAY_BUFFER,
new Float32Array([f, v, f, g, i, v, i, g]),
e.STATIC_DRAW
), l || (l = e.getAttribLocation(a, "vertex"), e.enableVertexAttribArray(l)), e.vertexAttribPointer(l, 2, e.FLOAT, !1, 0, 0), s && (e.clearColor(0, 0, 0, 0), e.clear(e.COLOR_BUFFER_BIT | e.GL_DEPTH_BUFFER_BIT)), e.drawArrays(e.TRIANGLE_STRIP, 0, 4);
}
function u(s = {}) {
e.useProgram(a);
for (let f in s) {
const v = e.getUniformLocation(a, f);
if (v === null) continue;
let i = s[f];
if (Array.isArray(i))
switch (i.length) {
case 1: {
Array.isArray(i[0]) && (i = i[0]), e.uniform1fv(v, new Float32Array(i));
break;
}
case 2:
e.uniform2fv(v, new Float32Array(i));
break;
case 3:
e.uniform3fv(v, new Float32Array(i));
break;
case 4:
e.uniform4fv(v, new Float32Array(i));
break;
case 9:
e.uniformMatrix3fv(v, !1, new Float32Array(i));
break;
case 16:
e.uniformMatrix4fv(v, !1, new Float32Array(i));
break;
default:
throw `dont't know how to load uniform "` + f + '" of length ' + i.length;
}
else if (i?.unit)
e.uniform1i(v, i.unit);
else if (typeof i == "number")
e.uniform1f(v, i);
else
throw 'attempted to set uniform "' + f + '" to invalid value ' + (i || "undefined").toString();
}
}
function h(s, f, v) {
var i = s.createShader(f);
if (s.shaderSource(i, v), s.compileShader(i), !s.getShaderParameter(i, s.COMPILE_STATUS))
throw "compile error: " + s.getShaderInfoLog(i);
return i;
}
return { drawRect: c, uniforms: u };
}
function E(e, o, t) {
let r = o, n = t, a = e.createTexture();
e.bindTexture(e.TEXTURE_2D, a), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.LINEAR), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.LINEAR), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE);
const l = e.SRGB8_ALPHA8;
o && t && e.texImage2D(e.TEXTURE_2D, 0, l, o, t, 0, e.RGBA, e.UNSIGNED_BYTE, null);
function c(v = 0) {
if (!a) return console.error("texture has been destroyed");
e.activeTexture(e.TEXTURE0 + v), e.bindTexture(e.TEXTURE_2D, a);
}
function u() {
e.deleteTexture(a), a = null;
}
function h() {
if (!a) return console.error("texture has been destroyed");
if (e.framebuffer = e.framebuffer || e.createFramebuffer(), e.bindFramebuffer(e.FRAMEBUFFER, e.framebuffer), e.framebufferTexture2D(e.FRAMEBUFFER, e.COLOR_ATTACHMENT0, e.TEXTURE_2D, a, 0), e.checkFramebufferStatus(e.FRAMEBUFFER) !== e.FRAMEBUFFER_COMPLETE)
throw new Error("incomplete framebuffer");
e.viewport(0, 0, r, n);
}
function s(v, i) {
if (!a) return console.error("texture has been destroyed");
r = v.width, n = v.height, e.bindTexture(e.TEXTURE_2D, a);
let g = i || e.SRGB8_ALPHA8;
e.texImage2D(e.TEXTURE_2D, 0, g, e.RGBA, e.UNSIGNED_BYTE, v);
}
function f(v, i, g, x) {
r = v, n = i, e.bindTexture(e.TEXTURE_2D, a);
let d = x || e.SRGB8_ALPHA8;
e.texImage2D(e.TEXTURE_2D, 0, d, v, i, 0, e.RGBA, e.UNSIGNED_BYTE, new Uint8Array(g));
}
return { use: c, destroy: u, drawTo: h, loadImage: s, initFromBytes: f };
}
function O(e, o, t, r) {
const n = document.createElement("canvas");
var a = n.getContext("2d", { colorSpace: o });
n.width = e.width, n.height = e.height, a.putImageData(e, 0, 0);
var l = new Image();
return l.src = n.toDataURL(t, r), l;
}
export {
b as Shader,
N as Spline,
E as Texture,
le as minigl
};