UNPKG

webgl-dsl

Version:

Thin functional WebGL wrapper with strong typed GLSL DSL

1,651 lines (1,650 loc) 42.8 kB
const $ = /* @__PURE__ */ (() => { let n = 0; return function() { return n++; }; })(); var p = /* @__PURE__ */ ((n) => (n.Scalar = "float", n.Vector2 = "vec2", n.Matrix2 = "mat2", n.Vector3 = "vec3", n.Matrix3 = "mat3", n.Vector4 = "vec4", n.Matrix4 = "mat4", n.Boolean = "bool", n.Sampler = "sampler2D", n))(p || {}), de = /* @__PURE__ */ ((n) => (n.High = "highp", n.Medium = "mediump", n.Low = "lowp", n))(de || {}); ((n) => { function e(i) { switch (i) { case "bool": case "float": case "sampler2D": return 1; case "vec2": case "mat2": return 2; case "vec3": case "mat3": return 3; case "vec4": case "mat4": return 4; } } n.size = e; function r(i) { switch (i) { case 2: return "vec2"; case 3: return "vec3"; case 4: return "vec4"; } } n.vector = r; function a(i) { switch (i) { case 1: return "float"; case 2: return "vec2"; case 3: return "vec3"; case 4: return "vec4"; } } n.numeric = a; function t(i) { return i === "vec2" || i === "vec3" || i === "vec4"; } n.isVector = t; function s(i) { return i === "mat2" || i === "mat3" || i === "mat4"; } n.isMatrix = s; })(p || (p = {})); class x { constructor(e = /* @__PURE__ */ new Map()) { this.cache = e, this.global = "", this.local = ""; } once(e, r) { if (this.cache.has(e)) return this.cache.get(e); { const a = r(); return this.cache.set(e, a), a; } } getGlobal() { return this.global; } addGlobal(e) { return this.global += e, this; } getLocal() { return this.local; } addLocal(e) { return this.local += e, this; } child() { return new x(this.cache); } } const fe = "==+-*/<><=>=!&&||", o = class o { constructor(e) { this.getValue = e; } static call(e, r, a) { const t = fe.indexOf(e) !== -1, s = r.map((i) => typeof i == "number" ? v(i) : i); return r.length === 2 && t ? new o((i) => { const l = s.map((h) => h.getValue(i)); return { type: a(l.map((h) => h.type)), content: `((${l[0].content}) ${e} (${l[1].content}))` }; }) : new o((i) => { const l = s.map((h) => h.getValue(i)); return { type: a(l.map((h) => h.type)), content: `${e}(${l.map((h) => h.content).join(", ")})` }; }); } unary(e) { return o.call(e, [this], (r) => r[0]); } sin() { return this.unary("sin"); } cos() { return this.unary("cos"); } radians() { return this.unary("radians"); } degrees() { return this.unary("degrees"); } tan() { return this.unary("tan"); } asin() { return this.unary("asin"); } acos() { return this.unary("acos"); } exp() { return this.unary("exp"); } log() { return this.unary("log"); } exp2() { return this.unary("exp2"); } log2() { return this.unary("log2"); } sqrt() { return this.unary("sqrt"); } inversesqrt() { return this.unary("inversesqrt"); } abs() { return this.unary("abs"); } sign() { return this.unary("sign"); } floor() { return this.unary("floor"); } ceil() { return this.unary("ceil"); } fract() { return this.unary("fract"); } normalize() { return this.unary("normalize"); } round() { return this.add(0.5).floor(); } not() { return this.unary("!"); } atan(e) { return e === void 0 ? o.call( "atan", [this], ([r]) => r ) : o.call( "atan", [this, e], (r) => r[0] ); } pow(e) { const r = typeof e == "number" ? v(e) : e; return o.call("pow", [this, r], ([a]) => a); } mod(e) { const r = typeof e == "number" ? v(e) : e; return o.call("mod", [this, r], ([a]) => a); } min(e) { const r = typeof e == "number" ? v(e) : e; return o.call("min", [this, r], ([a]) => a); } max(e) { return o.call("max", [this, e], ([r]) => r); } mix(e, r) { return o.call("mix", [this, e, r], ([a]) => a); } clamp(e, r) { return o.call("clamp", [this, e, r], ([a]) => a); } smoothstep(e, r) { return o.call("smoothstep", [e, r, this], ([a]) => a); } length() { return o.call( "length", [this], () => "float" /* Scalar */ ); } /** * Distance to other point */ distance(e) { return o.call( "distance", [this, e], () => "float" /* Scalar */ ); } /** * Dot product */ dot(e) { return o.call( "dot", [this, e], () => "float" /* Scalar */ ); } reflect(e) { return o.call("reflect", [this, e], ([r]) => r); } refract(e, r) { return o.call("refract", [this, e, r], ([a]) => a); } /** * Get texture value at the specified point */ texture2D(e) { return o.call( "texture2D", [this, e], () => "vec4" /* Vector4 */ ); } /** * Addition */ add(e) { return o.call( "+", [this, e], ([r, a]) => r === "float" ? a : r ); } /** * Substraction */ sub(e) { return o.call( "-", [this, e], ([r, a]) => r === "float" ? a : r ); } /** * Division */ div(e) { return o.call( "/", [this, e], ([r, a]) => r === "float" ? a : r ); } /** * Multiplication operation */ mul(e) { return o.call("*", [this, e], ([r, a]) => r === "float" || r === a ? a : a === "float" || p.isVector(r) ? r : p.isVector(a) ? a : r); } bool(e, r) { return o.call( e, [this, r], () => "bool" /* Boolean */ ); } /** Less */ lt(e) { return this.bool("<", e); } /** Greater */ gt(e) { return this.bool(">", e); } /** Less or equal */ lte(e) { return this.bool("<=", e); } /** Greater or equal */ gte(e) { return this.bool(">=", e); } /** Equal */ eq(e) { return this.bool("==", e); } /** Not equal */ neq(e) { return this.bool("!=", e); } and(e) { return o.call( "&&", [this, e], () => "bool" /* Boolean */ ); } or(e) { return o.call( "||", [this, e], () => "bool" /* Boolean */ ); } /** * Save some expression into a variable */ mem(e) { const r = `mem${$()}`; return new o((a) => { const t = this.getValue(a); return a.once(r, () => { const s = t.type !== "bool"; a.addLocal( `${s ? `${e} ` : ""}${t.type} ${r} = ${t.content}; ` ); }), { type: t.type, content: r }; }); } /** * Save some expression with high quality into a variable */ memHQ() { return this.mem( "highp" /* High */ ); } /** * Save some expression with medium quality into a variable */ memMQ() { return this.mem( "mediump" /* Medium */ ); } /** * Save some expression with low quality into a variable */ memLQ() { return this.mem( "lowp" /* Low */ ); } /** * Conditional expression * @param precision Precision of the expression result * @param whenTrue True brunch of the condition * @param whenFalse False brunch of the condition */ cond(e, r, a) { const t = `cond${$()}`; let s = null; return new o((i) => (i.once(t, () => { const l = this.getValue(i), h = i.child(), c = r.getValue(h), d = i.child(), f = a.getValue(d); s = c.type, i.addGlobal(h.getGlobal()).addGlobal(d.getGlobal()), i.addLocal( `${c.type !== "bool" ? e + " " : ""}${c.type} ${t}; ` ).addLocal(`if (${l.content}) { `).addLocal(h.getLocal()).addLocal(`${t} = ${c.content}; `).addLocal(`} else { `).addLocal(d.getLocal()).addLocal(`${t} = ${f.content}; `).addLocal(`} `); }), { type: s, content: t })); } condHQ(e, r) { return this.cond("highp", e, r); } condMQ(e, r) { return this.cond("mediump", e, r); } condLQ(e, r) { return this.cond("lowp", e, r); } /** * Take one or more components from vector */ take(e, r, a, t) { return new o((s) => { const i = [e, r, a, t].filter( (h) => h !== void 0 ), l = this.getValue(s); return { type: i.length === 1 ? "float" : p.vector(i.length), content: `(${l.content}).${i.map((h) => "xyzw".charAt(h)).join("")}` }; }); } vec2() { return new o((e) => ({ type: "vec2", content: `vec2(${this.getValue(e).content})` })); } vec3() { return new o((e) => ({ type: "vec3", content: `vec3(${this.getValue(e).content})` })); } vec4() { return new o((e) => ({ type: "vec4", content: `vec4(${this.getValue(e).content})` })); } /** * Get the first component of vector */ x() { return this.take(0); } /** * Get the second component of vector */ y() { return this.take(1); } /** * Get the third component of vector */ z() { return this.take(2); } /** * Get the fourth component of vector */ w() { return this.take(3); } /** * Get the first component of vector */ r() { return this.take(0); } /** * Get the second component of vector */ g() { return this.take(1); } /** * Get the third component of vector */ b() { return this.take(2); } /** * Get the fourth component of vector */ a() { return this.take(3); } /** * Create vector as a concatenation of current value and argument */ cat(e) { return typeof e == "number" ? this.cat(o.val(e)) : new o((r) => { const a = this.getValue(r), t = e.getValue(r), s = p.numeric( p.size(a.type) + p.size(t.type) ); return { type: s, content: `${s}(${a.content}, ${t.content})` }; }); } /** * Wrap set of values into single GLSL value */ static val(...e) { if (e.length === 1) { if (typeof e[0] == "boolean") return new o(() => ({ type: "bool", content: e[0] ? "1" : "0" })); if (e[0] instanceof o) return e[0]; { const r = e[0].toString(); return new o(() => ({ type: "float", content: /[e\.]/.test(r) ? r : `${r}.0` })); } } else if (e.some((r) => typeof r == "number")) { const r = e.map((a) => o.val(a)); return o.val.apply(null, r); } else return e.reduce((r, a) => r.cat(a)); } }; o.PI = o.val(Math.PI); let A = o; var m; ((n) => { function e(l) { return Array.isArray(l) ? l[0] : l; } n.getType = e; function r(l) { return Array.isArray(l) ? l[1] : "highp"; } n.getPrecision = r; function a(l) { return Object.keys(l).reduce( (h, c) => (h[c] = e(l[c]), h), {} ); } n.withoutPrecision = a; function t(l, h) { const c = {}; return Object.keys(h).forEach((d) => { const f = h[d]; c[d] = new A((b) => (b.once(`types_map_value_${d}`, () => { b.addGlobal( `${l} ${n.getPrecision(f)} ${n.getType(f)} ${d}; ` ); }), { type: n.getType(f), content: d })); }), c; } n.values = t; function s(l) { let h = 0; for (const c in l) h += p.size(e(l[c])); return h; } n.stride = s; function i(l) { const h = s(l); return Object.keys(l).sort().reduce((c, d) => { const f = c.length ? c[c.length - 1] : null; return c.push({ name: d, stride: h, size: p.size(e(l[d])), offset: f ? f.offset + f.size : 0 }), c; }, []); } n.layout = i; })(m || (m = {})); function pe({ uniforms: n, attributes: e, varyings: r, instances: a, fragment: t, vertex: s }) { const i = m.values("uniform", n), l = m.values("attribute", { ...e, ...a || {} }), h = r ? m.values("varying", r) : {}, c = new x(); Object.keys(h).forEach((E) => { h[E].getValue(c); }); const d = s({ ...i, ...l }), f = Object.keys(d).map((E) => `${E} = ${d[E].getValue(c).content}; `).join(""), b = c.getGlobal() + `void main() { ` + c.getLocal() + f + `} `, O = new x(); Object.keys(h).forEach((E) => { h[E].getValue(c); }); const oe = t({ ...i, ...h, gl_FragCoord: new A(() => ({ type: "vec4", content: "gl_FragCoord" })), gl_PointCoord: new A(() => ({ type: "vec2", content: "gl_FragCoord" })), gl_FrontFacing: new A(() => ({ type: "bool", content: "gl_FrontFacing" })) }).gl_FragColor.getValue(O), ue = O.getGlobal() + `void main() { ` + O.getLocal() + `gl_FragColor = ${oe.content}; } `; return { vertex: b, fragment: ue, uniforms: m.withoutPrecision(n), attributes: m.withoutPrecision(e), instances: m.withoutPrecision(a || {}) }; } const v = A.val; class me { constructor(e, r, a) { this.gl = e, this.primitivesType = r, this.source = a, this.textureInstances = /* @__PURE__ */ new Map(), this.textureIndexes = /* @__PURE__ */ new Map(), this.program = e.program(a.vertex, a.fragment), this.attributes = e.arrayBuffer(), this.instances = e.arrayBuffer(), this.elements = e.elementsBuffer(), this.attributesStride = m.stride(a.attributes), this.attributesLayout = m.layout(a.attributes), this.instancesStride = m.stride(a.instances), this.instancesLayout = m.layout(a.instances), this.attributesLayout.forEach((t) => { this.program.setAttribute( t.name, this.attributes, t.stride, t.offset ); }), this.instancesLayout.forEach((t) => { this.program.setAttribute( t.name, this.instances, t.stride, t.offset ); }); for (const t in a.uniforms) m.getType(a.uniforms[t]) === p.Sampler && this.textureIndexes.set(t, this.textureIndexes.size); } prepareData(e, r, a) { const t = new Float32Array(e * a.length); return a.forEach((s, i) => { r.forEach((l) => { const h = s[l.name], c = e * i + l.offset; if (Array.isArray(h)) for (let d = 0; d < h.length; d++) t[c + d] = h[d]; else if (l.size === 1 && typeof h == "number") t[c] = h; else if (l.size === 2) { const { x: d, y: f } = h; t[c] = d, t[c + 1] = f; } else if (l.size === 3) { const { x: d, y: f, z: b } = h; t[c] = d, t[c + 1] = f, t[c + 2] = b; } else throw new Error( `Unsupported attribute '${l.name}' value: ${JSON.stringify(h)}` ); }); }), t; } setAttributes(e) { const r = this.prepareData( this.attributesStride, this.attributesLayout, e ); return this.attributes.setContent(r), this; } setInstances(e) { const r = this.prepareData( this.instancesStride, this.instancesLayout, e ); return this.instances.setContent(r), this; } setElements(e) { return this.elements.setContent(e), this; } setUniforms(e) { const r = this.source.uniforms; for (const a in e) { const t = e[a]; let s; if (typeof t == "number") s = [t]; else if (Array.isArray(t)) s = t; else if (t instanceof he) { const i = this.textureIndexes.get(a); this.textureInstances.set(i, t), s = [i]; } else if (r[a] === p.Vector2) { const { x: i, y: l } = t; s = [i, l]; } else if (r[a] === p.Vector3) { const { x: i, y: l, z: h } = t; s = [i, l, h]; } else throw new Error( `Invalid value for uniform '${a}', expected ${r[a]}` ); this.program.setUniform(a, s); } return this; } draw(e = this.instancesStride ? this.instances.length / this.instancesStride : null, r = this.attributesStride ? this.attributes.length / this.attributesStride : null, a = this.elements.length) { const t = this.gl; t.settings().program(this.program).enabledAttributes( Object.keys(this.program.attributes).map((s) => this.program.attributes[s]?.location).filter((s) => s != null) ).instancedAttributes( this.instancesLayout.map((s) => s.name).map((s) => this.program.attributes[s]?.location).filter((s) => s != null) ).textures( Array.from(this.textureInstances.entries()).reduce( (s, [i, l]) => (s[i] = l, s), new Array(16).fill(null) ) ).apply(() => { if (e !== null && a !== 0) t.settings().elementsBuffer(this.elements).apply(() => { t.drawsInstancedElements( this.primitivesType, a, e ); }); else if (e !== null && r !== null) t.drawInstancedArrays( this.primitivesType, r, e ); else if (a !== 0) t.settings().elementsBuffer(this.elements).apply(() => { t.drawsElements( this.primitivesType, a ); }); else if (r) t.drawArrays(this.primitivesType, r); else throw new Error("Invalid draw dataset"); }); } dispose() { this.program.dispose(), this.attributes.dispose(), this.instances.dispose(), this.elements.dispose(); } } function ge(n, e, r) { return new me( n, e, "vertex" in r && typeof r.vertex == "string" ? r : pe(r) ); } class Ae { constructor(e) { this.values = e; } dispose() { this.values.forEach((e) => e.dispose()); } } function ye(...n) { return new Ae(n); } function be(...n) { n.forEach((e) => e.dispose()); } function Ee(...n) { const e = []; try { for (let r = 0; r < n.length; r++) e.push(n[r](...e)); return e; } catch (r) { throw e.reverse().forEach((a) => a.dispose()), r; } } var B; ((n) => { n.join = ye, n.dispose = be, n.create = Ee; })(B || (B = {})); function we(n, e) { try { return e(n); } finally { n.dispose(); } } function Le(...n) { const e = n.length - 1, r = []; try { for (let a = 0; a < e; a++) r.push(n[a](...r)); return n[e](...r); } finally { r.reverse().forEach((a) => a.dispose()); } } const U = 256, P = 16384, ve = 0, Re = 1, xe = 2, Se = 3, Oe = 4, Te = 5, Ie = 6, Ne = 0, Ve = 1, Ce = 768, Me = 769, De = 770, $e = 771, Be = 772, Ue = 773, Pe = 774, _e = 775, Ge = 776, qe = 32774, ke = 32778, He = 32779, M = 34962, D = 34963, ze = 35040, We = 35044, Fe = 35048, je = 1028, Xe = 1029, Qe = 1032, _ = 2884, G = 3042, q = 2929, k = 3089, Ye = 0, Ze = 1280, Ke = 1281, Je = 1282, et = 1285, tt = 33901, R = 5121, H = 5123, T = 5126, te = 6406, re = 6407, ne = 6408, rt = 6409, nt = 6410, st = 35632, at = 35633, it = 35714, lt = 35718, ht = 35721, ct = 512, ot = 513, ut = 514, dt = 515, ft = 516, pt = 517, mt = 518, gt = 519, At = 9728, yt = 9729, z = 10240, W = 10241, bt = 10242, Et = 10243, g = 3553, wt = 33984, F = 33071, j = 35664, X = 35665, Q = 35666, Lt = 35670, Y = 35674, Z = 35675, K = 35676, vt = 35678, Rt = 35713, I = 36160, S = 36161, J = 33189, xt = 36064, St = 36096, Ot = 37440, Tt = 35904, It = 35907; var se = /* @__PURE__ */ ((n) => (n[n.Front = je] = "Front", n[n.Back = Xe] = "Back", n[n.FrontAndBack = Qe] = "FrontAndBack", n))(se || {}), N = /* @__PURE__ */ ((n) => (n[n.Add = qe] = "Add", n[n.Sub = ke] = "Sub", n[n.RSub = He] = "RSub", n[n.Min = 32775] = "Min", n[n.Max = 32776] = "Max", n))(N || {}), ae = /* @__PURE__ */ ((n) => (n[n.Never = ct] = "Never", n[n.Less = ot] = "Less", n[n.Equal = ut] = "Equal", n[n.LEqual = dt] = "LEqual", n[n.Greater = ft] = "Greater", n[n.NotEqual = pt] = "NotEqual", n[n.GEqual = mt] = "GEqual", n[n.Always = gt] = "Always", n))(ae || {}), w = /* @__PURE__ */ ((n) => (n[n.Zero = Ne] = "Zero", n[n.One = Ve] = "One", n[n.SrcColor = Ce] = "SrcColor", n[n.OneMinusSrcColor = Me] = "OneMinusSrcColor", n[n.DstColor = Pe] = "DstColor", n[n.OneMinusDstColor = _e] = "OneMinusDstColor", n[n.SrcAlpha = De] = "SrcAlpha", n[n.OneMinusSrcAlpha = $e] = "OneMinusSrcAlpha", n[n.DstAlpha = Be] = "DstAlpha", n[n.OneMinusDstAlpha = Ue] = "OneMinusDstAlpha", n[n.SrcAlphaSaturate = Ge] = "SrcAlphaSaturate", n))(w || {}), ie = /* @__PURE__ */ ((n) => (n[n.Nearest = At] = "Nearest", n[n.Linear = yt] = "Linear", n))(ie || {}), le = /* @__PURE__ */ ((n) => (n[n.Alpha = te] = "Alpha", n[n.Luminance = rt] = "Luminance", n[n.LuminanceAlpha = nt] = "LuminanceAlpha", n[n.Rgb = re] = "Rgb", n[n.Rgba = ne] = "Rgba", n[n.Srgb = Tt] = "Srgb", n[n.Srgba = It] = "Srgba", n))(le || {}), y = /* @__PURE__ */ ((n) => (n[n.Rgba = ne] = "Rgba", n[n.Rgb = re] = "Rgb", n[n.Alpha = te] = "Alpha", n))(y || {}); ((n) => { function e(r) { switch (r) { case n.Rgb: return 3; case n.Rgba: return 4; case n.Alpha: return 1; } } n.getChannelsCount = e; })(y || (y = {})); var V = /* @__PURE__ */ ((n) => (n[n.Vertex = at] = "Vertex", n[n.Fragment = st] = "Fragment", n))(V || {}), Nt = /* @__PURE__ */ ((n) => (n[n.NoError = Ye] = "NoError", n[n.InvalidEnum = Ze] = "InvalidEnum", n[n.InvalidValue = Ke] = "InvalidValue", n[n.InvalidOperation = Je] = "InvalidOperation", n[n.OutOfMemory = et] = "OutOfMemory", n))(Nt || {}), L = /* @__PURE__ */ ((n) => (n[n.Stream = ze] = "Stream", n[n.Static = We] = "Static", n[n.Dynamic = Fe] = "Dynamic", n))(L || {}), Vt = /* @__PURE__ */ ((n) => (n[n.Array = M] = "Array", n[n.Elements = D] = "Elements", n))(Vt || {}), Ct = /* @__PURE__ */ ((n) => (n[n.Points = ve] = "Points", n[n.Lines = Re] = "Lines", n[n.LineStrip = Se] = "LineStrip", n[n.LineLoop = xe] = "LineLoop", n[n.Triangles = Oe] = "Triangles", n[n.TriangleStrip = Te] = "TriangleStrip", n[n.TriangleFan = Ie] = "TriangleFan", n))(Ct || {}); class Pt { constructor(...e) { this.settingsCache = C.initial(); const [r, a] = e; typeof HTMLCanvasElement < "u" && r instanceof HTMLCanvasElement ? this.handle = r.getContext("webgl", a) : this.handle = r, this.instancedArraysExtension = this.handle.getExtension( "ANGLE_instanced_arrays" ), this.minMaxExtension = this.handle.getExtension("EXT_blend_minmax"), this.srgbExtension = this.handle.getExtension("EXT_sRGB"); } /** * Get the width of the drawing buffer. */ get width() { return this.handle.drawingBufferWidth; } /** * Get the height of the drawing buffer. */ get height() { return this.handle.drawingBufferHeight; } isContextLost() { return this.handle.isContextLost(); } getPointSizeRange() { return this.handle.getParameter(tt); } clearColorBuffer() { return this.handle.clear(P), this; } clearDepthBuffer() { return this.handle.clear(U), this; } /** * Clear color and depth buffer */ clearBuffers() { return this.handle.clear(P | U), this; } /** * Read pixels from a drawing buffer into an array buffer */ read(e = y.Rgba) { const { width: r, height: a } = this, t = new Uint8Array( r * a * y.getChannelsCount(e) ); return this.settings().viewport(0, 0, r, a).apply(() => { this.handle.readPixels( 0, 0, r, a, e, R, t ); }), t; } drawArrays(e, r) { return this.handle.drawArrays(e, 0, r), this; } drawsElements(e, r) { return this.handle.drawElements( e, r, H, 0 ), this; } drawInstancedArrays(e, r, a) { return this.instancedArraysExtension.drawArraysInstancedANGLE( e, 0, r, a ), this; } drawsInstancedElements(e, r, a) { return this.instancedArraysExtension.drawElementsInstancedANGLE( e, r, H, 0, a ), this; } /** * Create an empty settings object */ settings() { return new u(this, this.settingsCache); } /** * Create texture with specified parameters */ texture(e) { return new he(this, e); } /** * Create depth buffer with specified width and height * @param width Depth buffer width * @param height Depth buffer height */ renderBuffer(e, r) { return new Mt(this, e, r); } /** * Create a frame buffer that can be used as a render target. * @param texture The texture to attach to the frame buffer. * @param renderBuffer Depth buffer to attach to the frame buffer. */ frameBuffer(e, r) { return new ce(this, e, r); } arrayBuffer(e = null, r = L.Dynamic) { return new Dt(this, e, r); } elementsBuffer(e = null, r = L.Dynamic) { return new $t(this, e, r); } /** * Create a program with a specified vertex and fragment shader source */ program(e, r) { return Le( () => new ee(this, V.Vertex, e), () => new ee(this, V.Fragment, r), (a, t) => new Bt(this, a, t) ); } /** * The main function of this library, creates a command with specified parameters and shaders * @param primitivesType Type of primitives to draw * @param configOrSource Description of attributes, uniforms, varyings, and shaders */ command(e, r) { return ge(this, e, r); } hasSrgbExtension() { return !!this.srgbExtension; } getErrorCode() { return this.handle.getError(); } /** * Destroy WebGL context */ dispose() { const e = this.handle.getExtension("WEBGL_lose_context"); e && e.loseContext(); } } var C; ((n) => { n.initial = () => ({ blend: !1, viewport: [0, 0, 0, 0], scissorTest: !1, scissorBox: [0, 0, 0, 0], depthTest: !1, depthFunction: ae.Less, clearDepth: 1, lineWidth: 1, blendEquation: [N.Add, N.Add], blendFunction: [ w.One, w.Zero, w.One, w.Zero ], clearColor: [0, 0, 0, 0], activeTexture: 0, textures: /* @__PURE__ */ new Map(), arrayBuffer: null, elementsBuffer: null, program: null, enabledAttributes: /* @__PURE__ */ new Set(), instancedAttributes: /* @__PURE__ */ new Set(), renderBuffer: null, frameBuffer: null, cullFace: !1, cullFaceMode: se.Back }); })(C || (C = {})); class u { constructor(e, r, a = (t) => t()) { this.gl = e, this.cache = r, this.apply = a, this.blend = u.cached({ read: (t) => t.blend, write: (t, s) => { t.blend = s; }, equals: (t, s) => t === s, apply: (t, s) => { s ? t.handle.enable(G) : t.handle.disable(G); } }), this.cullFace = u.cached({ read: (t) => t.cullFace, write: (t, s) => { t.cullFace = s; }, equals: (t, s) => t === s, apply: (t, s) => { s ? t.handle.enable(_) : t.handle.disable(_); } }), this.cullFaceMode = u.cached({ read: (t) => t.cullFaceMode, write: (t, s) => { t.cullFaceMode = s; }, equals: (t, s) => t === s, apply: (t, s) => { t.handle.cullFace(s); } }), this.viewport = (() => { const t = u.cached({ read: (s) => s.viewport, write: (s, i) => { s.viewport = i; }, equals: (s, i) => s.every((l, h) => l === i[h]), apply: (s, [i, l, h, c]) => { s.handle.viewport(i, l, h, c); } }); return function(s, i, l, h) { return t.call(this, [s, i, l, h]); }; })(), this.scissorTest = u.cached({ read: (t) => t.scissorTest, write: (t, s) => { t.scissorTest = s; }, equals: (t, s) => t === s, apply: (t, s) => { s ? t.handle.enable(k) : t.handle.disable(k); } }), this.scissorBox = (() => { const t = u.cached({ read: (s) => s.scissorBox, write: (s, i) => { s.scissorBox = i; }, equals: (s, i) => s.every((l, h) => l === i[h]), apply: (s, [i, l, h, c]) => { s.handle.scissor(i, l, h, c); } }); return function(s, i, l, h) { return t.call(this, [s, i, l, h]); }; })(), this.depthTest = u.cached({ read: (t) => t.depthTest, write: (t, s) => { t.depthTest = s; }, equals: (t, s) => t === s, apply: (t, s) => { s ? t.handle.enable(q) : t.handle.disable(q); } }), this.clearDepth = u.cached({ read: (t) => t.clearDepth, write: (t, s) => { t.clearDepth = s; }, equals: (t, s) => t === s, apply: (t, s) => { t.handle.clearDepth(s); } }), this.lineWidth = u.cached({ read: (t) => t.lineWidth, write: (t, s) => { t.lineWidth = s; }, equals: (t, s) => t === s, apply: (t, s) => { t.handle.lineWidth(s); } }), this.blendEquation = (() => { const t = u.cached({ read: (s) => s.blendEquation, write: (s, i) => { s.blendEquation = i; }, equals: (s, i) => s.every((l, h) => l === i[h]), apply: (s, [i, l]) => { s.handle.blendEquationSeparate(i, l); } }); return function(s, i = s) { return t.call(this, [s, i]); }; })(), this.blendFunction = (() => { const t = u.cached({ read: (s) => s.blendFunction, write: (s, i) => { s.blendFunction = i; }, equals: (s, i) => s.every((l, h) => l === i[h]), apply: (s, [i, l, h, c]) => { s.handle.blendFuncSeparate(i, l, h, c); } }); return function(s, i, l = s, h = i) { return t.call(this, [s, i, l, h]); }; })(), this.depthFunction = u.cached({ read: (t) => t.depthFunction, write: (t, s) => { t.depthFunction = s; }, equals: (t, s) => t === s, apply: (t, s) => { t.handle.depthFunc(s); } }), this.clearColor = (() => { const t = u.cached({ read: (s) => s.clearColor, write: (s, i) => { s.clearColor = i; }, equals: (s, i) => s.every((l, h) => l === i[h]), apply: (s, [i, l, h, c]) => { s.handle.clearColor(i, l, h, c); } }); return function(s, i, l, h) { return t.call(this, [s, i, l, h]); }; })(), this.activeTexture = u.cached({ read: (t) => t.activeTexture, write: (t, s) => { t.activeTexture = s; }, equals: (t, s) => t === s, apply: (t, s) => { t.handle.activeTexture(wt + s); } }), this.texture = (() => { const t = new Array(16).fill(null).map((s, i) => u.cached({ read: (l) => l.textures.get(i) || null, write: (l, h) => { h ? l.textures.set(i, h) : l.textures.delete(i); }, equals: (l, h) => l === h, apply: (l, h) => { l.settings().activeTexture(i).apply(() => { l.handle.bindTexture( g, h?.handle || null ); }); } })); return function(s, i) { return t[s].call(this, i); }; })(), this.arrayBuffer = u.cached({ read: (t) => t.arrayBuffer, write: (t, s) => { t.arrayBuffer = s; }, equals: (t, s) => t === s, apply: (t, s) => { t.handle.bindBuffer(M, s?.handle ?? null); } }), this.elementsBuffer = u.cached({ read: (t) => t.elementsBuffer, write: (t, s) => { t.elementsBuffer = s; }, equals: (t, s) => t === s, apply: (t, s) => { t.handle.bindBuffer(D, s?.handle ?? null); } }), this.program = u.cached({ read: (t) => t.program, write: (t, s) => { t.program = s; }, equals: (t, s) => t === s, apply: (t, s) => { t.handle.useProgram(s ? s.handle : null); } }), this.renderBuffer = u.cached({ read: (t) => t.renderBuffer, write: (t, s) => { t.renderBuffer = s; }, equals: (t, s) => t === s, apply: (t, s) => { t.handle.bindRenderbuffer( S, s ? s.handle : null ); } }), this.frameBuffer = u.cached({ read: (t) => t.frameBuffer, write: (t, s) => { t.frameBuffer = s; }, equals: (t, s) => t === s, apply: (t, s) => { t.handle.bindFramebuffer(I, s ? s.handle : null); } }); } static cached({ read: e, write: r, equals: a, apply: t }) { return function(s) { return this.then( new u(this.gl, this.cache, (i) => { const l = e(this.cache); if (a(l, s)) return i(); try { return r(this.cache, s), t(this.gl, s), i(); } finally { r(this.cache, l), t(this.gl, l); } }) ); }; } then(e) { return new u(this.gl, this.cache, (r) => this.apply(() => e.apply(r))); } textures(e) { let r = this; for (let a = 0; a < 16; a++) r = r.texture( a, a >= e.length ? null : e[a] ); return r; } enabledAttributes(e) { return this.then( new u(this.gl, this.cache, (r) => { const a = this.gl.handle, t = this.cache.enabledAttributes, s = new Set(e); this.cache.enabledAttributes = s; const i = (l, h) => { l.forEach((c) => { h.has(c) || a.disableVertexAttribArray(c); }), h.forEach((c) => { l.has(c) || a.enableVertexAttribArray(c); }); }; try { return i(t, s), r(); } finally { i(s, t), this.cache.enabledAttributes = t; } }) ); } instancedAttributes(e) { return this.then( new u(this.gl, this.cache, (r) => { const a = this.gl.instancedArraysExtension, t = this.cache.instancedAttributes, s = new Set(e); this.cache.instancedAttributes = s; const i = (l, h) => { l.forEach((c) => { h.has(c) || a.vertexAttribDivisorANGLE(c, 0); }), h.forEach((c) => { l.has(c) || a.vertexAttribDivisorANGLE(c, 1); }); }; try { return i(t, s), r(); } finally { i(s, t), this.cache.instancedAttributes = t; } }) ); } renderTarget(e) { return new u(this.gl, this.cache, (r) => we(new ce(this.gl, e), (a) => this.gl.settings().frameBuffer(a).viewport(0, 0, e.width, e.height).apply(r))); } } class he { constructor(e, r) { this.gl = e, this.handle = e.handle.createTexture(), this.format = r.format || le.Rgba, this.filter = r.filter || ie.Nearest, "image" in r ? (this.width = r.image instanceof HTMLImageElement ? r.image.naturalWidth : r.image instanceof VideoFrame ? r.image.codedWidth : r.image.width, this.height = r.image instanceof HTMLImageElement ? r.image.naturalHeight : r.image instanceof VideoFrame ? r.image.codedHeight : r.image.height) : (this.width = r.width, this.height = r.height), e.settings().activeTexture(0).texture(0, this).apply(() => { e.handle.pixelStorei(Ot, 1), e.handle.texParameteri( g, z, this.filter ), e.handle.texParameteri( g, W, this.filter ), e.handle.texParameteri( g, bt, F ), e.handle.texParameteri( g, Et, F ), "image" in r ? e.handle.texImage2D( g, 0, this.format, this.format, R, r.image ) : e.handle.texImage2D( g, 0, this.format, this.width, this.height, 0, // border this.format, R, "data" in r ? r.data : null ); }); } /** * Read pixels from the texture into an array buffer */ read(e = y.Rgba) { const r = new Uint8Array( this.width * this.height * y.getChannelsCount(e) ); return this.gl.settings().renderTarget(this).viewport(0, 0, this.width, this.height).apply(() => { this.gl.handle.readPixels( 0, 0, this.width, this.height, e, R, r ); }), r; } setFilter(e) { this.gl.handle.texParameteri(g, z, e), this.gl.handle.texParameteri(g, W, e); } dispose() { this.gl.handle.deleteTexture(this.handle); } } class ce { constructor(e, r, a) { this.gl = e, this.colorBuffer = r, this.depthBuffer = a, this.handle = e.handle.createFramebuffer(), e.settings().frameBuffer(this).apply(() => { e.handle.framebufferTexture2D( I, xt, g, r.handle, 0 ), a && e.handle.framebufferRenderbuffer( I, St, S, a.handle ); }); } dispose() { this.gl.handle.deleteFramebuffer(this.handle); } } class Mt { constructor(e, r, a) { this.gl = e, this.widthValue = r, this.heightValue = a, this.handle = e.handle.createRenderbuffer(), e.settings().renderBuffer(this).apply(() => { e.handle.renderbufferStorage( S, J, r, a ); }); } get width() { return this.widthValue; } get height() { return this.heightValue; } resize(e, r) { const { gl: a } = this; return (e !== this.width || r !== this.height) && (this.widthValue = e, this.heightValue = r, a.settings().renderBuffer(this).apply(() => { a.handle.renderbufferStorage( S, J, e, r ); })), this; } dispose() { this.gl.handle.deleteRenderbuffer(this.handle); } } class Dt { constructor(e, r = null, a = L.Dynamic) { this.gl = e, this.usage = a, this.lengthValue = 0, this.handle = e.handle.createBuffer(), r && this.setContent(r); } get length() { return this.lengthValue; } setContent(e) { const r = e instanceof Float32Array ? e : new Float32Array(e); this.lengthValue = r.length; const a = this.gl; return a.settings().arrayBuffer(this).apply(() => { a.handle.bufferData(M, r, this.usage); }), this; } dispose() { this.gl.handle.deleteBuffer(this.handle); } } class $t { constructor(e, r = null, a = L.Dynamic) { this.gl = e, this.usage = a, this.lengthValue = 0, this.handle = e.handle.createBuffer(), r && this.setContent(r); } get length() { return this.lengthValue; } setContent(e) { const r = e instanceof Uint8Array || e instanceof Uint16Array ? e : new Uint16Array(e); this.lengthValue = r.length; const a = this.gl; return a.settings().elementsBuffer(this).apply(() => { a.handle.bufferData(D, r, this.usage); }), this; } dispose() { this.gl.handle.deleteBuffer(this.handle); } } class ee { constructor(e, r, a) { this.gl = e, this.type = r, this.source = a; const t = this.handle = e.handle.createShader(r); if (e.handle.shaderSource(t, a), e.handle.compileShader(t), e.handle.getShaderParameter(t, Rt) === !1) throw new Error( `WebGL error '${e.handle.getShaderInfoLog(t)}' in '${a}'` ); } dispose() { this.gl.handle.deleteShader(this.handle); } } class Bt { constructor(e, r, a) { this.gl = e, this.vertex = r, this.fragment = a, this.uniforms = {}, this.attributes = {}; const t = this.handle = e.handle.createProgram(); if (e.handle.attachShader(t, r.handle), e.handle.attachShader(t, a.handle), e.handle.linkProgram(t), e.handle.validateProgram(t), e.handle.getProgramParameter(t, it) === !1) throw new Error( e.handle.getProgramInfoLog(t) || `Program linking error: ${r.source}; ${a.source}` ); const s = e.handle.getProgramParameter( t, lt ); for (let l = 0; l < s; l++) { const h = e.handle.getActiveUniform(t, l); h !== null && (this.uniforms[h.name] = { type: h.type, location: e.handle.getUniformLocation(t, h.name), size: h.size }); } const i = e.handle.getProgramParameter( t, ht ); for (let l = 0; l < i; l++) { const h = e.handle.getActiveAttrib(t, l); h != null && (this.attributes[h.name] = { type: h.type, location: l, size: h.size }); } } setUniform(e, r) { const { gl: a, uniforms: t } = this, s = t[e]; if (s) { const { location: i, type: l } = s; a.settings().program(this).apply(() => { switch (l) { case Lt: a.handle.uniform1i(i, r[0] ? 1 : 0); break; case vt: a.handle.uniform1iv(i, r); break; case T: a.handle.uniform1fv(i, r); break; case j: a.handle.uniform2fv(i, r); break; case X: a.handle.uniform3fv(i, r); break; case Q: a.handle.uniform4fv(i, r); break; case Y: a.handle.uniformMatrix2fv(i, !1, r); break; case Z: a.handle.uniformMatrix3fv(i, !1, r); break; case K: a.handle.uniformMatrix4fv(i, !1, r); break; } }); } } setAttribute(e, r, a, t) { const s = this.attributes[e]; if (s != null) { const { gl: i } = this; i.settings().arrayBuffer(r).apply(() => { i.handle.vertexAttribPointer( s.location, (() => { switch (s.type) { case T: return 1; case j: return 2; case X: return 3; case Q: return 4; case Y: return 4; case Z: return 9; case K: return 16; default: throw new Error( `Invalid attribute type '${s.type}'` ); } })(), T, !1, a * 4, t * 4 ); }); } else console.warn(`Attribute '${e}' not found`); } dispose() { this.gl.handle.deleteProgram(this.handle); } } export { Dt as ArrayBuffer, N as BlendEquation, w as BlendFunction, Vt as BufferTarget, L as BufferUsage, me as Command, ae as DepthFunction, B as Disposable, $t as ElementsBuffer, Nt as ErrorCode, se as FaceCulling, ce as FrameBuffer, Pt as Gl, A as Glsl, x as GlslBuilder, y as PixelFormat, de as Precision, Ct as PrimitivesType, Bt as Program, Mt as RenderBuffer, u as Settings, V as ShaderType, he as Texture, ie as TextureFilter, le as TextureFormat, p as Type, m as TypeMap, ge as command, Ee as create, be as dispose, pe as source, we as use, Le as uses, v as val }; //# sourceMappingURL=index.js.map