webgl-dsl
Version:
Thin functional WebGL wrapper with strong typed GLSL DSL
1 lines • 187 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/dsl.ts","../src/consts.ts","../src/enums.ts","../src/texture.ts","../src/command.ts","../src/disposable/join.ts","../src/disposable/dispose.ts","../src/disposable/create.ts","../src/disposable/use.ts","../src/disposable/uses.ts","../src/disposable/disposable.ts","../src/settings.ts","../src/program.ts","../src/elements-buffer.ts","../src/array-buffer.ts","../src/render-buffer.ts","../src/frame-buffer.ts","../src/gl.ts"],"sourcesContent":["import { Texture } from \"./texture\";\n\nconst id = (() => {\n let sequence = 0;\n return function id() {\n return sequence++;\n };\n})();\n\nexport enum Type {\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}\n\nexport enum Precision {\n High = \"highp\",\n Medium = \"mediump\",\n Low = \"lowp\",\n}\n\nexport type TypeSize = 1 | 2 | 3 | 4;\n\nexport namespace Type {\n export function size(type: Type.Boolean | Type.Scalar | Type.Sampler): 1;\n export function size(type: Type.Vector2 | Type.Matrix2): 2;\n export function size(type: Type.Vector3 | Type.Matrix3): 3;\n export function size(type: Type.Vector4 | Type.Matrix4): 4;\n export function size(type: Type): TypeSize;\n export function size(type: Type): TypeSize {\n switch (type) {\n case Type.Boolean:\n case Type.Scalar:\n case Type.Sampler:\n return 1;\n case Type.Vector2:\n case Type.Matrix2:\n return 2;\n case Type.Vector3:\n case Type.Matrix3:\n return 3;\n case Type.Vector4:\n case Type.Matrix4:\n return 4;\n }\n }\n\n export function vector(size: 2): Type.Vector2;\n export function vector(size: 3): Type.Vector3;\n export function vector(size: 4): Type.Vector4;\n export function vector(size: 2 | 3 | 4): Type.AnyVector;\n export function vector(size: 2 | 3 | 4): Type.AnyVector {\n switch (size) {\n case 2:\n return Type.Vector2;\n case 3:\n return Type.Vector3;\n case 4:\n return Type.Vector4;\n }\n }\n\n export function numeric(size: 1): Type.Scalar;\n export function numeric(size: 2): Type.Vector2;\n export function numeric(size: 3): Type.Vector3;\n export function numeric(size: 4): Type.Vector4;\n export function numeric(size: TypeSize): Type.AnyNumeric;\n export function numeric(size: TypeSize): Type.AnyNumeric {\n switch (size) {\n case 1:\n return Type.Scalar;\n case 2:\n return Type.Vector2;\n case 3:\n return Type.Vector3;\n case 4:\n return Type.Vector4;\n }\n }\n\n export type Numeric<S extends TypeSize> = S extends 1\n ? Type.Scalar\n : S extends 2\n ? Type.Vector2\n : S extends 3\n ? Type.Vector3\n : Type.Vector4;\n\n export type GetSize<T extends Type.AnyNumeric> = T extends Type.Scalar\n ? 1\n : T extends Type.Vector2\n ? 2\n : T extends Type.Vector3\n ? 3\n : 4;\n\n export type Indexes<T extends Type.AnyVector> = T extends Type.Vector2\n ? 0 | 1\n : T extends Type.Vector3\n ? 0 | 1 | 2\n : 0 | 1 | 2 | 3;\n\n export type AnyVector = Type.Vector2 | Type.Vector3 | Type.Vector4;\n export type AnyMatrix = Type.Matrix2 | Type.Matrix3 | Type.Matrix4;\n export type AnyNumeric = Type.Scalar | AnyVector;\n\n export type JsType<T extends Type> = T extends Type.Scalar\n ? number\n : T extends Type.Vector2\n ? number[] | { x: number; y: number }\n : T extends Type.Vector3\n ? number[] | { x: number; y: number; z: number }\n : T extends Type.Vector4\n ? number[]\n : T extends Type.Matrix2\n ? number[]\n : T extends Type.Matrix3\n ? number[]\n : T extends Type.Matrix4\n ? number[]\n : T extends Type.Sampler\n ? Texture\n : never;\n\n export function isVector(v: Type): v is AnyVector {\n return v === Type.Vector2 || v === Type.Vector3 || v === Type.Vector4;\n }\n export function isMatrix(v: Type): v is AnyMatrix {\n return v === Type.Matrix2 || v === Type.Matrix3 || v === Type.Matrix4;\n }\n}\n\nexport type Value<T extends Type = Type> = Readonly<{\n type: T;\n content: string;\n}>;\n\nexport class GlslBuilder {\n private global = \"\";\n private local = \"\";\n\n constructor(private readonly cache = new Map<string, any>()) {}\n\n once<R>(id: string, callback: () => R): R {\n if (this.cache.has(id)) {\n return this.cache.get(id) as R;\n } else {\n const result = callback();\n this.cache.set(id, result);\n return result;\n }\n }\n getGlobal(): string {\n return this.global;\n }\n addGlobal(content: string): this {\n this.global += content;\n return this;\n }\n getLocal(): string {\n return this.local;\n }\n addLocal(content: string): this {\n this.local += content;\n return this;\n }\n\n child() {\n return new GlslBuilder(this.cache);\n }\n}\n\nexport namespace Glsl {\n export type Boolean = Glsl<Type.Boolean>;\n export type Scalar = Glsl<Type.Scalar>;\n export type Vector2 = Glsl<Type.Vector2>;\n export type Vector3 = Glsl<Type.Vector3>;\n export type Vector4 = Glsl<Type.Vector4>;\n export type Matrix2 = Glsl<Type.Matrix2>;\n export type Matrix3 = Glsl<Type.Matrix3>;\n export type Matrix4 = Glsl<Type.Matrix4>;\n export type Sampler = Glsl<Type.Sampler>;\n export type AnyVector = Glsl<Type.AnyVector>;\n export type AnyNumeric = Glsl<Type.AnyNumeric>;\n export type AnyMatrix = Glsl<Type.AnyMatrix>;\n}\n\nconst operators = \"==+-*/<><=>=!&&||\";\n\nexport class Glsl<T extends Type = Type> {\n constructor(public readonly getValue: (builder: GlslBuilder) => Value<T>) {}\n\n private static call(\n name: string,\n values: (Glsl | number)[],\n rtype: (types: Type[]) => Type,\n ) {\n const isOperator = operators.indexOf(name) !== -1;\n const glsls = values.map(v => (typeof v === \"number\" ? val(v) : v));\n if (values.length === 2 && isOperator) {\n return new Glsl(builder => {\n const computed = glsls.map(v => v.getValue(builder));\n return {\n type: rtype(computed.map(v => v.type)),\n content: `((${computed[0].content}) ${name} (${computed[1].content}))`,\n };\n });\n } else {\n return new Glsl(builder => {\n const computed = glsls.map(v => v.getValue(builder));\n return {\n type: rtype(computed.map(v => v.type)),\n content: `${name}(${computed.map(v => v.content).join(\", \")})`,\n };\n });\n }\n }\n\n private unary(name: string) {\n return Glsl.call(name, [this], t => t[0]) as Glsl<T>;\n }\n\n sin(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"sin\") as Glsl<T>;\n }\n cos(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"cos\") as Glsl<T>;\n }\n radians(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"radians\") as Glsl<T>;\n }\n degrees(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"degrees\") as Glsl<T>;\n }\n tan(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"tan\") as Glsl<T>;\n }\n asin(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"asin\") as Glsl<T>;\n }\n acos(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"acos\") as Glsl<T>;\n }\n\n exp(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"exp\") as Glsl<T>;\n }\n log(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"log\") as Glsl<T>;\n }\n exp2(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"exp2\") as Glsl<T>;\n }\n log2(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"log2\") as Glsl<T>;\n }\n sqrt(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"sqrt\") as Glsl<T>;\n }\n inversesqrt(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"inversesqrt\") as Glsl<T>;\n }\n\n abs(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"abs\") as Glsl<T>;\n }\n sign(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"sign\") as Glsl<T>;\n }\n floor(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"floor\") as Glsl<T>;\n }\n ceil(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"ceil\") as Glsl<T>;\n }\n fract(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"fract\") as Glsl<T>;\n }\n normalize(this: Glsl<Type.AnyNumeric>) {\n return this.unary(\"normalize\") as Glsl<T>;\n }\n\n round<T extends Glsl.AnyNumeric>(this: T): T {\n return this.add(0.5).floor() as T;\n }\n\n not(this: Glsl<Type.Boolean>) {\n return this.unary(\"!\");\n }\n\n atan<T extends Type.AnyNumeric>(this: Glsl<T>): Glsl<T>;\n atan<T extends Type.AnyNumeric>(this: Glsl<T>, x: Glsl<T>): Glsl<T>;\n atan(this: Glsl.Scalar, x: number): Glsl.Scalar;\n atan(v?: Glsl.AnyNumeric | number): Glsl.AnyNumeric {\n if (v === undefined) {\n return Glsl.call(\n \"atan\",\n [this],\n ([type]) => type,\n ) as Glsl.AnyNumeric;\n } else {\n return Glsl.call(\n \"atan\",\n [this, v],\n types => types[0],\n ) as Glsl.AnyNumeric;\n }\n }\n\n pow(this: Glsl.Scalar, p: Glsl.Scalar): Glsl.Scalar;\n pow(this: Glsl.Vector2, p: Glsl.Vector2): Glsl.Vector2;\n pow(this: Glsl.Vector3, p: Glsl.Vector3): Glsl.Vector3;\n pow(this: Glsl.Vector4, p: Glsl.Vector4): Glsl.Vector4;\n pow(this: Glsl.Scalar, p: number): Glsl.Scalar;\n pow(p: Glsl.AnyNumeric | number): Glsl {\n const pv = typeof p === \"number\" ? val(p) : p;\n return Glsl.call(\"pow\", [this, pv], ([t]) => t);\n }\n\n mod<P extends Type.AnyNumeric>(this: Glsl<P>, p: Glsl<P>): Glsl<P>;\n mod(this: Glsl.Scalar, p: number): Glsl.Scalar;\n mod(p: Glsl.AnyNumeric | number): Glsl<Type> {\n const pv = typeof p === \"number\" ? val(p) : p;\n return Glsl.call(\"mod\", [this, pv], ([t]) => t);\n }\n\n min<P extends Type.AnyNumeric>(this: Glsl<P>, p: Glsl<P>): Glsl<P>;\n min(this: Glsl.Scalar, p: number): Glsl.Scalar;\n min(p: Glsl.AnyNumeric | number): Glsl<Type> {\n const pv = typeof p === \"number\" ? val(p) : p;\n return Glsl.call(\"min\", [this, pv], ([t]) => t);\n }\n\n max<P extends Type.AnyNumeric>(this: Glsl<P>, p: Glsl<P>): Glsl<P>;\n max(this: Glsl.Scalar, p: number): Glsl.Scalar;\n max(p: Glsl.AnyNumeric | number): Glsl {\n return Glsl.call(\"max\", [this, p], ([t]) => t);\n }\n\n mix<P extends Glsl.AnyNumeric>(this: P, other: P, p: P): P;\n mix<P extends Glsl.AnyNumeric>(this: P, other: P, p: number): P;\n mix(this: Glsl.Scalar, other: number, p: Glsl.Scalar | number): Glsl.Scalar;\n mix(\n other: Glsl.AnyNumeric | number,\n p: Glsl.AnyNumeric | number,\n ): Glsl<Type> {\n return Glsl.call(\"mix\", [this, other, p], ([t]) => t);\n }\n\n clamp<T extends Glsl.AnyNumeric>(this: T, min: T, max: T): T;\n clamp<T extends Glsl.AnyNumeric>(\n this: T,\n min: Glsl.Scalar | number,\n max: Glsl.Scalar | number,\n ): T;\n clamp(min: Glsl.AnyNumeric | number, max: Glsl.AnyNumeric | number): Glsl {\n return Glsl.call(\"clamp\", [this, min, max], ([t]) => t);\n }\n\n smoothstep(\n this: Glsl.Scalar,\n edge1: Glsl.Scalar | number,\n edge2: Glsl.Scalar | number,\n ): Glsl.Scalar;\n smoothstep<T extends Glsl.AnyNumeric>(this: T, edge1: T, edge2: T): T;\n smoothstep<T extends Glsl.AnyNumeric>(\n this: Glsl.Scalar,\n edge1: Glsl.Scalar | number,\n edge2: Glsl.Scalar | number,\n ): T;\n smoothstep(edge1: Glsl | number, edge2: Glsl | number): Glsl {\n return Glsl.call(\"smoothstep\", [edge1, edge2, this], ([t]) => t);\n }\n\n length(this: Glsl.AnyNumeric): Glsl.Scalar;\n length(): Glsl {\n return Glsl.call(\"length\", [this], () => Type.Scalar);\n }\n\n distance<T extends Glsl.AnyNumeric>(this: T, other: T): Glsl.Scalar;\n distance(this: Glsl.Scalar, other: number): Glsl.Scalar;\n /**\n * Distance to other point\n */\n distance(other: Glsl | number): Glsl {\n return Glsl.call(\"distance\", [this, other], () => Type.Scalar);\n }\n\n dot<T extends Glsl.AnyNumeric>(this: T, other: T): Glsl.Scalar;\n dot(this: Glsl.Scalar, other: number): Glsl.Scalar;\n /**\n * Dot product\n */\n dot(other: Glsl | number): Glsl {\n return Glsl.call(\"dot\", [this, other], () => Type.Scalar);\n }\n\n reflect<T extends Glsl.AnyNumeric>(this: T, n: T): T;\n reflect(v: Glsl): Glsl {\n return Glsl.call(\"reflect\", [this, v], ([t]) => t);\n }\n\n refract<T extends Glsl.AnyNumeric>(\n this: T,\n n: T,\n eta: Glsl.Scalar | number,\n ): T;\n refract(n: Glsl, eta: Glsl | number): Glsl {\n return Glsl.call(\"refract\", [this, n, eta], ([t]) => t);\n }\n\n /**\n * Get texture value at the specified point\n */\n texture2D(this: Glsl.Sampler, point: Glsl.Vector2): Glsl.Vector4 {\n return Glsl.call(\n \"texture2D\",\n [this, point],\n () => Type.Vector4,\n ) as Glsl.Vector4;\n }\n\n add<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(\n this: T,\n other: T | Glsl.Scalar | number,\n ): T;\n add<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(\n this: Glsl.Scalar,\n other: T,\n ): T;\n /**\n * Addition\n */\n add<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(\n this: T,\n other: T | Glsl.Scalar | number,\n ): Glsl.AnyNumeric | Glsl.AnyMatrix {\n return Glsl.call(\"+\", [this, other], ([t1, t2]) =>\n t1 === Type.Scalar ? t2 : t1,\n ) as T;\n }\n\n sub<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(\n this: T,\n other: T | Glsl.Scalar | number,\n ): T;\n sub<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(\n this: Glsl.Scalar,\n other: T,\n ): T;\n /**\n * Substraction\n */\n sub<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(\n this: T,\n other: T | Glsl.Scalar | number,\n ): Glsl.AnyNumeric | Glsl.AnyMatrix {\n return Glsl.call(\"-\", [this, other], ([t1, t2]) =>\n t1 === Type.Scalar ? t2 : t1,\n ) as T;\n }\n\n div<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(\n this: T,\n other: T | Glsl.Scalar | number,\n ): T;\n div<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(\n this: Glsl.Scalar,\n other: T,\n ): T;\n /**\n * Division\n */\n div<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(\n this: T,\n other: T | Glsl.Scalar | number,\n ): Glsl.AnyNumeric | Glsl.AnyMatrix {\n return Glsl.call(\"/\", [this, other], ([t1, t2]) =>\n t1 === Type.Scalar ? t2 : t1,\n ) as T;\n }\n\n mul<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(\n this: T,\n other: T | Glsl.Scalar | number,\n ): T;\n mul<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(\n this: Glsl.Scalar,\n other: T | Glsl.Scalar | number,\n ): T;\n mul(this: Glsl.Matrix2, other: Glsl.Vector2): Glsl.Vector2;\n mul(this: Glsl.Vector2, other: Glsl.Matrix2): Glsl.Vector2;\n mul(this: Glsl.Matrix3, other: Glsl.Vector3): Glsl.Vector3;\n mul(this: Glsl.Vector3, other: Glsl.Matrix3): Glsl.Vector3;\n mul(this: Glsl.Matrix4, other: Glsl.Vector4): Glsl.Vector4;\n mul(this: Glsl.Vector4, other: Glsl.Matrix4): Glsl.Vector4;\n /**\n * Multiplication operation\n */\n mul<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(\n this: T,\n other: T | Glsl.Scalar | number,\n ): T {\n return Glsl.call(\"*\", [this, other], ([t1, t2]) => {\n if (t1 === Type.Scalar || t1 === t2) {\n return t2;\n } else if (t2 === Type.Scalar) {\n return t1;\n } else if (Type.isVector(t1)) {\n return t1;\n } else if (Type.isVector(t2)) {\n return t2;\n } else {\n return t1;\n }\n }) as T;\n }\n\n private bool(this: Glsl.Scalar, name: string, other: Glsl.Scalar | number) {\n return Glsl.call(\n name,\n [this, other],\n () => Type.Boolean,\n ) as Glsl.Boolean;\n }\n\n /** Less */\n lt(this: Glsl.Scalar, other: Glsl.Scalar | number): Glsl.Boolean {\n return this.bool(\"<\", other);\n }\n /** Greater */\n gt(this: Glsl.Scalar, other: Glsl.Scalar | number): Glsl.Boolean {\n return this.bool(\">\", other);\n }\n /** Less or equal */\n lte(this: Glsl.Scalar, other: Glsl.Scalar | number): Glsl.Boolean {\n return this.bool(\"<=\", other);\n }\n /** Greater or equal */\n gte(this: Glsl.Scalar, other: Glsl.Scalar | number): Glsl.Boolean {\n return this.bool(\">=\", other);\n }\n /** Equal */\n eq(this: Glsl.Scalar, other: Glsl.Scalar | number): Glsl.Boolean {\n return this.bool(\"==\", other);\n }\n /** Not equal */\n neq(this: Glsl.Scalar, other: Glsl.Scalar | number): Glsl.Boolean {\n return this.bool(\"!=\", other);\n }\n\n and(this: Glsl.Boolean, other: Glsl.Boolean): Glsl.Boolean {\n return Glsl.call(\n \"&&\",\n [this, other],\n () => Type.Boolean,\n ) as Glsl.Boolean;\n }\n or(this: Glsl.Boolean, other: Glsl.Boolean): Glsl.Boolean {\n return Glsl.call(\n \"||\",\n [this, other],\n () => Type.Boolean,\n ) as Glsl.Boolean;\n }\n\n /**\n * Save some expression into a variable\n */\n mem<T extends Glsl>(this: T, precision: Precision): T {\n const name = `mem${id()}`;\n return new Glsl(builder => {\n const v = this.getValue(builder);\n builder.once(name, () => {\n const hasPrecision = v.type !== Type.Boolean;\n builder.addLocal(\n `${hasPrecision ? `${precision} ` : \"\"}${v.type} ${name} = ${v.content};\\n`,\n );\n });\n return {\n type: v.type,\n content: name,\n };\n }) as T;\n }\n\n /**\n * Save some expression with high quality into a variable\n */\n memHQ() {\n return this.mem(Precision.High);\n }\n /**\n * Save some expression with medium quality into a variable\n */\n memMQ() {\n return this.mem(Precision.Medium);\n }\n /**\n * Save some expression with low quality into a variable\n */\n memLQ() {\n return this.mem(Precision.Low);\n }\n\n /**\n * Conditional expression\n * @param precision Precision of the expression result\n * @param whenTrue True brunch of the condition\n * @param whenFalse False brunch of the condition\n */\n cond<T extends Glsl>(\n this: Glsl.Boolean,\n precision: Precision,\n whenTrue: T,\n whenFalse: T,\n ): T {\n const name = `cond${id()}`;\n let type: Type | null = null;\n return new Glsl(builder => {\n builder.once(name, () => {\n const condition = this.getValue(builder);\n\n const trueBuilder = builder.child();\n const trueValue = whenTrue.getValue(trueBuilder);\n\n const falseBuilder = builder.child();\n const falseValue = whenFalse.getValue(falseBuilder);\n\n type = trueValue.type;\n\n builder\n .addGlobal(trueBuilder.getGlobal())\n .addGlobal(falseBuilder.getGlobal());\n\n builder\n .addLocal(\n `${trueValue.type !== Type.Boolean ? precision + \" \" : \"\"}${trueValue.type} ${name};\\n`,\n )\n .addLocal(`if (${condition.content}) {\\n`)\n .addLocal(trueBuilder.getLocal())\n .addLocal(`${name} = ${trueValue.content};\\n`)\n .addLocal(\"} else {\\n\")\n .addLocal(falseBuilder.getLocal())\n .addLocal(`${name} = ${falseValue.content};\\n`)\n .addLocal(\"}\\n\");\n });\n\n return {\n type: type!,\n content: name,\n };\n }) as T;\n }\n\n condHQ<T extends Glsl>(this: Glsl.Boolean, whenTrue: T, whenFalse: T): T {\n return this.cond(Precision.High, whenTrue, whenFalse);\n }\n condMQ<T extends Glsl>(this: Glsl.Boolean, whenTrue: T, whenFalse: T): T {\n return this.cond(Precision.Medium, whenTrue, whenFalse);\n }\n condLQ<T extends Glsl>(this: Glsl.Boolean, whenTrue: T, whenFalse: T): T {\n return this.cond(Precision.Low, whenTrue, whenFalse);\n }\n\n take<T extends Type.AnyVector>(\n this: Glsl<T>,\n i: Type.Indexes<T>,\n ): Glsl.Scalar;\n take<T extends Type.AnyVector>(\n this: Glsl<T>,\n i1: Type.Indexes<T>,\n i2: Type.Indexes<T>,\n ): Glsl.Vector2;\n take<T extends Type.Vector3 | Type.Vector4>(\n this: Glsl<T>,\n i1: Type.Indexes<T>,\n i2: Type.Indexes<T>,\n i3: Type.Indexes<T>,\n ): Glsl.Vector3;\n take(\n this: Glsl.Vector4,\n i1: Type.Indexes<Type.Vector4>,\n i2: Type.Indexes<Type.Vector4>,\n i3: Type.Indexes<Type.Vector4>,\n i4: Type.Indexes<Type.Vector4>,\n ): Glsl.Vector4;\n /**\n * Take one or more components from vector\n */\n take(i1: number, i2?: number, i3?: number, i4?: number): Glsl.AnyNumeric {\n return new Glsl(builder => {\n const indexes = [i1, i2, i3, i4].filter(\n i => i !== undefined,\n ) as number[];\n const value = this.getValue(builder);\n return {\n type:\n indexes.length === 1\n ? Type.Scalar\n : Type.vector(indexes.length as 2 | 3 | 4),\n content: `(${value.content}).${indexes\n .map(i => {\n return \"xyzw\".charAt(i);\n })\n .join(\"\")}`,\n };\n });\n }\n\n vec2(this: Glsl.Scalar): Glsl.Vector2 {\n return new Glsl(builder => {\n return {\n type: Type.Vector2,\n content: `vec2(${this.getValue(builder).content})`,\n };\n });\n }\n\n vec3(this: Glsl.Scalar): Glsl.Vector3 {\n return new Glsl(builder => {\n return {\n type: Type.Vector3,\n content: `vec3(${this.getValue(builder).content})`,\n };\n });\n }\n\n vec4(this: Glsl.Scalar): Glsl.Vector4 {\n return new Glsl(builder => {\n return {\n type: Type.Vector4,\n content: `vec4(${this.getValue(builder).content})`,\n };\n });\n }\n\n /**\n * Get the first component of vector\n */\n x(this: Glsl.AnyVector) {\n return this.take(0);\n }\n /**\n * Get the second component of vector\n */\n y(this: Glsl.Vector2 | Glsl.Vector3 | Glsl.Vector4) {\n return this.take(1);\n }\n /**\n * Get the third component of vector\n */\n z(this: Glsl.Vector3 | Glsl.Vector4) {\n return this.take(2);\n }\n /**\n * Get the fourth component of vector\n */\n w(this: Glsl.Vector4) {\n return this.take(3);\n }\n\n /**\n * Get the first component of vector\n */\n r(this: Glsl.AnyVector) {\n return this.take(0);\n }\n /**\n * Get the second component of vector\n */\n g(this: Glsl.Vector2 | Glsl.Vector3 | Glsl.Vector4) {\n return this.take(1);\n }\n /**\n * Get the third component of vector\n */\n b(this: Glsl.Vector3 | Glsl.Vector4) {\n return this.take(2);\n }\n /**\n * Get the fourth component of vector\n */\n a(this: Glsl.Vector4) {\n return this.take(3);\n }\n\n cat(this: Glsl.Scalar, v: Glsl.Scalar | number): Glsl.Vector2;\n cat(this: Glsl.Scalar, v: Glsl.Vector2): Glsl.Vector3;\n cat(this: Glsl.Scalar, v: Glsl.Vector3): Glsl.Vector4;\n cat(this: Glsl.Vector2, v: Glsl.Scalar | number): Glsl.Vector3;\n cat(this: Glsl.Vector2, v: Glsl.Vector2): Glsl.Vector4;\n cat(this: Glsl.Vector3, v: Glsl.Scalar | number): Glsl.Vector4;\n /**\n * Create vector as a concatenation of current value and argument\n */\n cat(\n this: Glsl<Type.Scalar | Type.Vector2 | Type.Vector3>,\n v: Glsl<Type.Scalar | Type.Vector2 | Type.Vector3> | number,\n ): Glsl.AnyNumeric {\n if (typeof v === \"number\") {\n return (this as Glsl.Scalar).cat(Glsl.val(v));\n } else {\n return new Glsl(builder => {\n const v1 = this.getValue(builder),\n v2 = v.getValue(builder),\n rt = Type.numeric(\n (Type.size(v1.type) + Type.size(v2.type)) as TypeSize,\n );\n return {\n type: rt,\n content: `${rt}(${v1.content}, ${v2.content})`,\n };\n });\n }\n }\n\n static val(v: boolean): Glsl<Type.Boolean>;\n static val(v: number): Glsl.Scalar;\n static val<T extends Glsl>(v: T): T;\n static val(\n v1: Glsl.Scalar | number,\n v2: Glsl.Scalar | number,\n ): Glsl.Vector2;\n static val(v1: Glsl.Scalar | number, v2: Glsl.Vector2): Glsl.Vector3;\n static val(v1: Glsl.Scalar | number, v2: Glsl.Vector3): Glsl.Vector4;\n static val(v1: Glsl.Vector2, v2: Glsl.Scalar | number): Glsl.Vector3;\n static val(v1: Glsl.Vector3, v2: Glsl.Scalar | number): Glsl.Vector4;\n\n static val(\n v1: Glsl.Scalar | number,\n v2: Glsl.Scalar | number,\n v3: Glsl.Scalar | number,\n ): Glsl.Vector3;\n static val(\n v1: Glsl.Vector2,\n v2: Glsl.Scalar | number,\n v3: Glsl.Scalar | number,\n ): Glsl.Vector4;\n static val(\n v1: Glsl.Scalar | number,\n v2: Glsl.Vector2,\n v3: Glsl.Scalar | number,\n ): Glsl.Vector4;\n static val(\n v1: Glsl.Scalar | number,\n v2: Glsl.Scalar | number,\n v3: Glsl.Vector2,\n ): Glsl.Vector4;\n\n static val(\n v1: Glsl.Scalar | number,\n v2: Glsl.Scalar | number,\n v3: Glsl.Scalar | number,\n v4: Glsl.Scalar | number,\n ): Glsl.Vector4;\n\n /**\n * Wrap set of values into single GLSL value\n */\n static val(...values: (Glsl | number | boolean)[]): Glsl {\n if (values.length === 1) {\n if (typeof values[0] === \"boolean\") {\n return new Glsl(() => ({\n type: Type.Boolean,\n content: values[0] ? \"1\" : \"0\",\n }));\n } else if (values[0] instanceof Glsl) {\n return values[0];\n } else {\n const s = values[0].toString();\n return new Glsl(() => ({\n type: Type.Scalar,\n content: /[e\\.]/.test(s) ? s : `${s}.0`,\n }));\n }\n } else if (values.some(v => typeof v === \"number\")) {\n const vs = values.map(v => Glsl.val(v as any));\n return Glsl.val.apply(null, vs as any);\n } else {\n return values.reduce((r, v) => (r as any).cat(v)) as Glsl;\n }\n }\n\n static PI = Glsl.val(Math.PI);\n}\n\n/**\n * Description of attributes/uniforms/varyings\n */\nexport type TypeMap = {\n [key: string]: Type | [Type, Precision];\n};\n\nexport namespace TypeMap {\n export type GetType<T extends Type | [Type, Precision]> = T extends Type\n ? T\n : T[0];\n\n export type JsTypeMap<T extends TypeMap> = {\n [key in keyof T]: Type.JsType<GetType<T[key]>>;\n };\n\n export type ToValues<M extends TypeMap> = {\n [key in keyof M]: Glsl<GetType<M[key]>>;\n };\n\n export type WithoutPrecision<M extends TypeMap> = {\n [key in keyof M]: GetType<M[key]>;\n };\n\n export function getType(v: Type | [Type, Precision]): Type {\n return Array.isArray(v) ? v[0] : v;\n }\n export function getPrecision(v: Type | [Type, Precision]): Precision {\n return Array.isArray(v) ? v[1] : Precision.High;\n }\n\n export function withoutPrecision<M extends TypeMap>(\n map: M,\n ): WithoutPrecision<M> {\n return Object.keys(map).reduce(\n (r, key) => {\n r[key] = getType(map[key]);\n return r;\n },\n {} as { [key: string]: Type },\n ) as WithoutPrecision<M>;\n }\n\n export function values(\n storage: \"uniform\" | \"attribute\" | \"varying\",\n types: TypeMap,\n ) {\n const result: { [key: string]: Glsl } = {};\n Object.keys(types).forEach(name => {\n const type = types[name];\n result[name] = new Glsl(builder => {\n builder.once(`types_map_value_${name}`, () => {\n builder.addGlobal(\n `${storage} ${TypeMap.getPrecision(type)} ${TypeMap.getType(type)} ${name};\\n`,\n );\n });\n return {\n type: TypeMap.getType(type),\n content: name,\n };\n });\n });\n return result;\n }\n\n export function stride(map: TypeMap) {\n let r = 0;\n for (const i in map) {\n r += Type.size(getType(map[i]));\n }\n return r;\n }\n\n export interface LayoutItem {\n name: string;\n size: number;\n stride: number;\n offset: number;\n }\n\n export function layout(map: TypeMap): LayoutItem[] {\n const s = stride(map);\n\n return Object.keys(map)\n .sort()\n .reduce((r, name) => {\n const previous = r.length ? r[r.length - 1] : null;\n r.push({\n name: name,\n stride: s,\n size: Type.size(getType(map[name])),\n offset: previous ? previous.offset + previous.size : 0,\n });\n return r;\n }, [] as LayoutItem[]);\n }\n}\n\n/**\n * Description of a shader program\n */\nexport type SourceConfig<\n Uniforms extends TypeMap,\n Attributes extends TypeMap,\n Instances extends TypeMap,\n Varyings extends TypeMap = {},\n> = {\n uniforms: Uniforms;\n attributes: Attributes;\n instances?: Instances;\n varyings?: Varyings;\n vertex: (\n input: TypeMap.ToValues<Uniforms> &\n TypeMap.ToValues<Attributes> &\n TypeMap.ToValues<Instances>,\n ) => TypeMap.ToValues<Varyings> & {\n gl_Position: Glsl.Vector4;\n gl_PointSize?: Glsl.Scalar;\n };\n fragment: (\n input: TypeMap.ToValues<Uniforms> &\n TypeMap.ToValues<Varyings> & {\n gl_FragCoord: Glsl.Vector4;\n gl_FrontFacing: Glsl.Boolean;\n gl_PointCoord: Glsl.Vector2;\n },\n ) => {\n gl_FragColor: Glsl.Vector4;\n };\n};\n\nexport type ProgramSource<\n Uniforms extends TypeMap,\n Attributes extends TypeMap,\n Instances extends TypeMap,\n> = {\n uniforms: Uniforms;\n attributes: Attributes;\n instances: Instances;\n fragment: string;\n vertex: string;\n};\n\nexport namespace ProgramSource {\n export type GetUniforms<T extends ProgramSource<any, any, any>> =\n T extends ProgramSource<infer R, any, any> ? R : never;\n export type GetAttributes<T extends ProgramSource<any, any, any>> =\n T extends ProgramSource<any, infer R, any> ? R : never;\n export type GetInstances<T extends ProgramSource<any, any, any>> =\n T extends ProgramSource<any, any, infer R> ? R : never;\n}\n\n/**\n * Create GLSL program source from argument types and shaders described with the DSL\n */\nexport function source<\n Uniforms extends TypeMap,\n Attributes extends TypeMap,\n Instances extends TypeMap,\n Varyings extends TypeMap = {},\n>({\n uniforms,\n attributes,\n varyings,\n instances,\n fragment,\n vertex,\n}: SourceConfig<Uniforms, Attributes, Instances, Varyings>): ProgramSource<\n TypeMap.WithoutPrecision<Uniforms>,\n TypeMap.WithoutPrecision<Attributes>,\n TypeMap.WithoutPrecision<Instances>\n> {\n const uValues = TypeMap.values(\"uniform\", uniforms);\n const aValues = TypeMap.values(\"attribute\", {\n ...attributes,\n ...(instances || {}),\n });\n const vValues = varyings ? TypeMap.values(\"varying\", varyings) : {};\n\n // vertex\n const vertexBuilder = new GlslBuilder();\n\n Object.keys(vValues).forEach(name => {\n vValues[name].getValue(vertexBuilder);\n });\n\n const vertexOutput = vertex({\n ...uValues,\n ...aValues,\n } as any);\n const vertexAssignment = Object.keys(vertexOutput)\n .map(name => {\n return `${name} = ${vertexOutput[name].getValue(vertexBuilder).content};\\n`;\n })\n .join(\"\");\n\n const vertexSource =\n vertexBuilder.getGlobal() +\n \"void main() {\\n\" +\n vertexBuilder.getLocal() +\n vertexAssignment +\n \"}\\n\";\n\n // fragment\n const fragmentBuilder = new GlslBuilder();\n\n Object.keys(vValues).forEach(name => {\n vValues[name].getValue(vertexBuilder);\n });\n\n const fragmentOutput = fragment({\n ...uValues,\n ...vValues,\n gl_FragCoord: new Glsl(() => {\n return {\n type: Type.Vector4,\n content: \"gl_FragCoord\",\n };\n }),\n gl_PointCoord: new Glsl(() => {\n return {\n type: Type.Vector2,\n content: \"gl_FragCoord\",\n };\n }),\n gl_FrontFacing: new Glsl(() => {\n return {\n type: Type.Boolean,\n content: \"gl_FrontFacing\",\n };\n }),\n } as any);\n const fragmentColor = fragmentOutput.gl_FragColor.getValue(fragmentBuilder);\n const fragmentSource =\n fragmentBuilder.getGlobal() +\n \"void main() {\\n\" +\n fragmentBuilder.getLocal() +\n `gl_FragColor = ${fragmentColor.content};\\n` +\n \"}\\n\";\n\n // result\n return {\n vertex: vertexSource,\n fragment: fragmentSource,\n uniforms: TypeMap.withoutPrecision(uniforms),\n attributes: TypeMap.withoutPrecision(attributes),\n instances: TypeMap.withoutPrecision(instances || ({} as Instances)),\n };\n}\n\n/**\n * Wrap a set of values into a single GLSL value\n */\nexport const val = Glsl.val;\n","/*\n * WebGL numeric constants extracted from gl.ts\n * Not every server WebGL implementation has its own WebGLRenderingContext class.\n * Because of this, we declare constants manually here and export them for reuse.\n */\n\n/* ClearBufferMask */\nexport const DEPTH_BUFFER_BIT = 0x00000100;\nexport const STENCIL_BUFFER_BIT = 0x00000400;\nexport const COLOR_BUFFER_BIT = 0x00004000;\n\n/* BeginMode */\nexport const POINTS = 0x0000;\nexport const LINES = 0x0001;\nexport const LINE_LOOP = 0x0002;\nexport const LINE_STRIP = 0x0003;\nexport const TRIANGLES = 0x0004;\nexport const TRIANGLE_STRIP = 0x0005;\nexport const TRIANGLE_FAN = 0x0006;\n\n/* BlendingFactorDest */\nexport const ZERO = 0;\nexport const ONE = 1;\nexport const SRC_COLOR = 0x0300;\nexport const ONE_MINUS_SRC_COLOR = 0x0301;\nexport const SRC_ALPHA = 0x0302;\nexport const ONE_MINUS_SRC_ALPHA = 0x0303;\nexport const DST_ALPHA = 0x0304;\nexport const ONE_MINUS_DST_ALPHA = 0x0305;\n\n/* BlendingFactorSrc */\n/* ZERO */\n/* ONE */\nexport const DST_COLOR = 0x0306;\nexport const ONE_MINUS_DST_COLOR = 0x0307;\nexport const SRC_ALPHA_SATURATE = 0x0308;\n/* SRC_ALPHA */\n/* ONE_MINUS_SRC_ALPHA */\n/* DST_ALPHA */\n/* ONE_MINUS_DST_ALPHA */\n\n/* BlendEquationSeparate */\nexport const FUNC_ADD = 0x8006;\nexport const BLEND_EQUATION = 0x8009;\nexport const BLEND_EQUATION_RGB = 0x8009; /* same as BLEND_EQUATION */\nexport const BLEND_EQUATION_ALPHA = 0x883d;\n\n/* BlendSubtract */\nexport const FUNC_SUBTRACT = 0x800a;\nexport const FUNC_REVERSE_SUBTRACT = 0x800b;\n\n/* Separate Blend Functions */\nexport const BLEND_DST_RGB = 0x80c8;\nexport const BLEND_SRC_RGB = 0x80c9;\nexport const BLEND_DST_ALPHA = 0x80ca;\nexport const BLEND_SRC_ALPHA = 0x80cb;\nexport const CONSTANT_COLOR = 0x8001;\nexport const ONE_MINUS_CONSTANT_COLOR = 0x8002;\nexport const CONSTANT_ALPHA = 0x8003;\nexport const ONE_MINUS_CONSTANT_ALPHA = 0x8004;\nexport const BLEND_COLOR = 0x8005;\n\n/* Buffer Objects */\nexport const ARRAY_BUFFER = 0x8892;\nexport const ELEMENT_ARRAY_BUFFER = 0x8893;\nexport const ARRAY_BUFFER_BINDING = 0x8894;\nexport const ELEMENT_ARRAY_BUFFER_BINDING = 0x8895;\n\nexport const STREAM_DRAW = 0x88e0;\nexport const STATIC_DRAW = 0x88e4;\nexport const DYNAMIC_DRAW = 0x88e8;\n\nexport const BUFFER_SIZE = 0x8764;\nexport const BUFFER_USAGE = 0x8765;\n\nexport const CURRENT_VERTEX_ATTRIB = 0x8626;\n\n/* CullFaceMode */\nexport const FRONT = 0x0404;\nexport const BACK = 0x0405;\nexport const FRONT_AND_BACK = 0x0408;\n\n/* DepthFunction */\n/* NEVER */\n/* LESS */\n/* EQUAL */\n/* LEQUAL */\n/* GREATER */\n/* NOTEQUAL */\n/* GEQUAL */\n/* ALWAYS */\n\n/* EnableCap */\n/* TEXTURE_2D */\nexport const CULL_FACE = 0x0b44;\nexport const BLEND = 0x0be2;\nexport const DITHER = 0x0bd0;\nexport const STENCIL_TEST = 0x0b90;\nexport const DEPTH_TEST = 0x0b71;\nexport const SCISSOR_TEST = 0x0c11;\nexport const POLYGON_OFFSET_FILL = 0x8037;\nexport const SAMPLE_ALPHA_TO_COVERAGE = 0x809e;\nexport const SAMPLE_COVERAGE = 0x80a0;\n\n/* ErrorCode */\nexport const NO_ERROR = 0;\nexport const INVALID_ENUM = 0x0500;\nexport const INVALID_VALUE = 0x0501;\nexport const INVALID_OPERATION = 0x0502;\nexport const OUT_OF_MEMORY = 0x0505;\n\n/* FrontFaceDirection */\nexport const CW = 0x0900;\nexport const CCW = 0x0901;\n\n/* GetPName */\nexport const LINE_WIDTH = 0x0b21;\nexport const ALIASED_POINT_SIZE_RANGE = 0x846d;\nexport const ALIASED_LINE_WIDTH_RANGE = 0x846e;\nexport const CULL_FACE_MODE = 0x0b45;\nexport const FRONT_FACE = 0x0b46;\nexport const DEPTH_RANGE = 0x0b70;\nexport const DEPTH_WRITEMASK = 0x0b72;\nexport const DEPTH_CLEAR_VALUE = 0x0b73;\nexport const DEPTH_FUNC = 0x0b74;\nexport const STENCIL_CLEAR_VALUE = 0x0b91;\nexport const STENCIL_FUNC = 0x0b92;\nexport const STENCIL_FAIL = 0x0b94;\nexport const STENCIL_PASS_DEPTH_FAIL = 0x0b95;\nexport const STENCIL_PASS_DEPTH_PASS = 0x0b96;\nexport const STENCIL_REF = 0x0b97;\nexport const STENCIL_VALUE_MASK = 0x0b93;\nexport const STENCIL_WRITEMASK = 0x0b98;\nexport const STENCIL_BACK_FUNC = 0x8800;\nexport const STENCIL_BACK_FAIL = 0x8801;\nexport const STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802;\nexport const STENCIL_BACK_PASS_DEPTH_PASS = 0x8803;\nexport const STENCIL_BACK_REF = 0x8ca3;\nexport const STENCIL_BACK_VALUE_MASK = 0x8ca4;\nexport const STENCIL_BACK_WRITEMASK = 0x8ca5;\nexport const VIEWPORT = 0x0ba2;\nexport const SCISSOR_BOX = 0x0c10;\n\n/* SCISSOR_TEST */\nexport const COLOR_CLEAR_VALUE = 0x0c22;\nexport const COLOR_WRITEMASK = 0x0c23;\nexport const UNPACK_ALIGNMENT = 0x0cf5;\nexport const PACK_ALIGNMENT = 0x0d05;\nexport const MAX_TEXTURE_SIZE = 0x0d33;\nexport const MAX_VIEWPORT_DIMS = 0x0d3a;\nexport const SUBPIXEL_BITS = 0x0d50;\nexport const RED_BITS = 0x0d52;\nexport const GREEN_BITS = 0x0d53;\nexport const BLUE_BITS = 0x0d54;\nexport const ALPHA_BITS = 0x0d55;\nexport const DEPTH_BITS = 0x0d56;\nexport const STENCIL_BITS = 0x0d57;\nexport const POLYGON_OFFSET_UNITS = 0x2a00;\n/* POLYGON_OFFSET_FILL */\nexport const POLYGON_OFFSET_FACTOR = 0x8038;\nexport const TEXTURE_BINDING_2D = 0x8069;\nexport const SAMPLE_BUFFERS = 0x80a8;\nexport const SAMPLES = 0x80a9;\nexport const SAMPLE_COVERAGE_VALUE = 0x80aa;\nexport const SAMPLE_COVERAGE_INVERT = 0x80ab;\n\n/* GetTextureParameter */\n/* TEXTURE_MAG_FILTER */\n/* TEXTURE_MIN_FILTER */\n/* TEXTURE_WRAP_S */\n/* TEXTURE_WRAP_T */\n\nexport const COMPRESSED_TEXTURE_FORMATS = 0x86a3;\n\n/* HintMode */\nexport const DONT_CARE = 0x1100;\nexport const FASTEST = 0x1101;\nexport const NICEST = 0x1102;\n\n/* HintTarget */\nexport const GENERATE_MIPMAP_HINT = 0x8192;\n\n/* DataType */\nexport const BYTE = 0x1400;\nexport const UNSIGNED_BYTE = 0x1401;\nexport const SHORT = 0x1402;\nexport const UNSIGNED_SHORT = 0x1403;\nexport const INT = 0x1404;\nexport const UNSIGNED_INT = 0x1405;\nexport const FLOAT = 0x1406;\n\n/* PixelFormat */\nexport const DEPTH_COMPONENT = 0x1902;\nexport const ALPHA = 0x1906;\nexport const RGB = 0x1907;\nexport const RGBA = 0x1908;\nexport const LUMINANCE = 0x1909;\nexport const LUMINANCE_ALPHA = 0x190a;\n\n/* PixelType */\n/* UNSIGNED_BYTE */\nexport const UNSIGNED_SHORT_4_4_4_4 = 0x8033;\nexport const UNSIGNED_SHORT_5_5_5_1 = 0x8034;\nexport const UNSIGNED_SHORT_5_6_5 = 0x8363;\n\n/* Shaders */\nexport const FRAGMENT_SHADER = 0x8b30;\nexport const VERTEX_SHADER = 0x8b31;\nexport const MAX_VERTEX_ATTRIBS = 0x8869;\nexport const MAX_VERTEX_UNIFORM_VECTORS = 0x8dfb;\nexport const MAX_VARYING_VECTORS = 0x8dfc;\nexport const MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8b4d;\nexport const MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8b4c;\nexport const MAX_TEXTURE_IMAGE_UNITS = 0x8872;\nexport const MAX_FRAGMENT_UNIFORM_VECTORS = 0x8dfd;\nexport const SHADER_TYPE = 0x8b4f;\nexport const DELETE_STATUS = 0x8b80;\nexport const LINK_STATUS = 0x8b82;\nexport const VALIDATE_STATUS = 0x8b83;\nexport const ATTACHED_SHADERS = 0x8b85;\nexport const ACTIVE_UNIFORMS = 0x8b86;\nexport const ACTIVE_ATTRIBUTES = 0x8b89;\nexport const SHADING_LANGUAGE_VERSION = 0x8b8c;\nexport const CURRENT_PROGRAM = 0x8b8d;\n\n/* StencilFunction */\nexport const NEVER = 0x0200;\nexport const LESS = 0x0201;\nexport const EQUAL = 0x0202;\nexport const LEQUAL = 0x0203;\nexport const GREATER = 0x0204;\nexport const NOTEQUAL = 0x0205;\nexport const GEQUAL = 0x0206;\nexport const ALWAYS = 0x0207;\n\n/* StencilOp */\n/* ZERO */\nexport const KEEP = 0x1e00;\nexport const REPLACE = 0x1e01;\nexport const INCR = 0x1e02;\nexport const DECR = 0x1e03;\nexport const INVERT = 0x150a;\nexport const INCR_WRAP = 0x8507;\nexport const DECR_WRAP = 0x8508;\n\n/* StringName */\nexport const VENDOR = 0x1f00;\nexport const RENDERER = 0x1f01;\nexport const VERSION = 0x1f02;\n\n/* TextureMagFilter */\nexport const NEAREST = 0x2600;\nexport const LINEAR = 0x2601;\n\n/* TextureMinFilter */\n/* NEAREST */\n/* LINEAR */\nexport const NEAREST_MIPMAP_NEAREST = 0x2700;\nexport const LINEAR_MIPMAP_NEAREST = 0x2701;\nexport const NEAREST_MIPMAP_LINEAR = 0x2702;\nexport const LINEAR_MIPMAP_LINEAR = 0x2703;\n\n/* TextureParameterName */\nexport const TEXTURE_MAG_FILTER = 0x2800;\nexport const TEXTURE_MIN_FILTER = 0x2801;\nexport const TEXTURE_WRAP_S = 0x2802;\nexport const TEXTURE_WRAP_T = 0x2803;\n\n/* TextureTarget */\nexport const TEXTURE_2D = 0x0de1;\nexport const TEXTURE = 0x1702;\n\nexport const TEXTURE_CUBE_MAP = 0x8513;\nexport const TEXTURE_BINDING_CUBE_MAP = 0x8514;\nexport const TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;\nexport const TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;\nexport const TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;\nexport const TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;\nexport const TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;\nexport const TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851a;\nexport const MAX_CUBE_MAP_TEXTURE_SIZE = 0x851c;\n\n/* TextureUnit */\nexport const TEXTURE0 = 0x84c0;\nexport const TEXTURE1 = 0x84c1;\nexport const TEXTURE2 = 0x84c2;\nexport const TEXTURE3 = 0x84c3;\nexport const TEXTURE4 = 0x84c4;\nexport const TEXTURE5 = 0x84c5;\nexport const TEXTURE6 = 0x84c6;\nexport const TEXTURE7 = 0x84c7;\nexport const TEXTURE8 = 0x84c8;\nexport const TEXTURE9 = 0x84c9;\nexport const TEXTURE10 = 0x84ca;\nexport const TEXTURE11 = 0x84cb;\nexport const TEXTURE12 = 0x84cc;\nexport const TEXTURE13 = 0x84cd;\nexport const TEXTURE14 = 0x84ce;\nexport const TEXTURE15 = 0x84cf;\nexport const TEXTURE16 = 0x84d0;\nexport const TEXTURE17 = 0x84d1;\nexport const TEXTURE18 = 0x84d2;\nexport const TEXTURE19 = 0x84d3;\nexport const TEXTURE20 = 0x84d4;\nexport const TEXTURE21 = 0x84d5;\nexport const TEXTURE22 = 0x84d6;\nexport const TEXTURE23 = 0x84d7;\nexport const TEXTURE24 = 0x84d8;\nexport const TEXTURE25 = 0x84d9;\nexport const TEXTURE26 = 0x84da;\nexport const TEXTURE27 = 0x84db;\nexport const TEXTURE28 = 0x84dc;\nexport const TEXTURE29 = 0x84dd;\nexport const TEXTURE30 = 0x84de;\nexport const TEXTURE31 = 0x84df;\nexport const ACTIVE_TEXTURE = 0x84e0;\n\n/* TextureWrapMode */\nexport const REPEAT = 0x2901;\nexport const CLAMP_TO_EDGE = 0x812f;\nexport const MIRRORED_REPEAT = 0x8370;\n\n/* Uniform Types */\nexport const FLOAT_VEC2 = 0x8b50;\nexport const FLOAT_VEC3 = 0x8b51;\nexport const FLOAT_VEC4 = 0x8b52;\nexport const INT_VEC2 = 0x8b53;\nexport const INT_VEC3 = 0x8b54;\nexport const INT_VEC4 = 0x8b55;\nexport const BOOL = 0x8b56;\nexport const BOOL_VEC2 = 0x8b57;\nexport const BOOL_VEC3 = 0x8b58;\nexport const BOOL_VEC4 = 0x8b59;\nexport const FLOAT_MAT2 = 0x8b5a;\nexport const FLOAT_MAT3 = 0x8b5b;\nexport const FLOAT_MAT4 = 0x8b5c;\nexport const SAMPLER_2D = 0x8b5e;\nexport const SAMPLER_CUBE = 0x8b60;\n\n/* Vertex Arrays */\nexport const VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622;\nexport const VERTEX_ATTRIB_ARRAY_SIZE = 0x8623;\nexport const VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624;\nexport const VERTEX_ATTRIB_ARRAY_TYPE = 0x8625;\nexport const VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886a;\nexport const VERTEX_ATTRIB_ARRAY_POINTER = 0x8645;\nexport const VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889f;\n\n/* Read Format */\nexport const IMPLEMENTATION_COLOR_READ_TYPE = 0x8b9a;\nexport const IMPLEMENTATION_COLOR_READ_FORMAT = 0x8b9b;\n\n/* Shader Source */\nexport const COMPILE_STATUS = 0x8b81;\n\n/* Shader Precision-Specified Types */\nexport const LOW_FLOAT = 0x8df0;\nexport const MEDIUM_FLOAT = 0x8df1;\nexport const HIGH_FLOAT = 0x8df2;\nexport const LOW_INT = 0x8df3;\nexport const MEDIUM_INT = 0x8df4;\nexport const HIGH_INT = 0x8df5;\n\n/* Framebuffer Object. */\nexport const FRAMEBUFFER = 0x8d40;\nexport const RENDERBUFFER = 0x8d41;\n\nexport const RGBA4 = 0x8056;\nexport const RGB5_A1 = 0x8057;\nexport const RGB565 = 0x8d62;\nexport const DEPTH_COMPONENT16 = 0x81a5;\nexport const STENCIL_INDEX8 = 0x8d48;\nexport const DEPTH_STENCIL = 0x84f9;\n\nexport const RENDERBUFFER_WIDTH = 0x8d42;\nexport const RENDERBUFFER_HEIGHT = 0x8d43;\nexport const RENDERBUFFER_INTERNAL_FORMAT = 0x8d44;\nexport const RENDERBUFFER_RED_SIZE = 0x8d50;\nexport const RENDERBUFFER_GREEN_SIZE = 0x8d51;\nexport const RENDERBUFFER_BLUE_SIZE = 0x8d52;\nexport const RENDERBUFFER_ALPHA_SIZE = 0x8d53;\nexport const RENDERBUFFER_DEPTH_SIZE = 0x8d54;\nexport const RENDERBUFFER_STENCIL_SIZE = 0x8d55;\n\nexport const FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8cd0;\nexport const FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8cd1;\nexport const FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8cd2;\nexport const FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8cd3;\n\nexport const COLOR_ATTACHMENT0 = 0x8ce0;\nexport const DEPTH_ATTACHMENT = 0x8d00;\nexport const STENCIL_ATTACHMENT = 0x8d20;\nexport const DEPTH_STENCIL_ATTACHMENT = 0x821a;\n\nexport const NONE = 0;\n\nexport const FRAMEBUFFER_COMPLETE = 0x8cd5;\nexport const FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8cd6;\nexport const FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8cd7;\nexport const FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8cd9;\nexport const FRAMEBUFFER_UNSUPPORTED = 0x8cdd;\n\nexport const FRAMEBUFFER_BINDING = 0x8ca6;\nexport const RENDERBUFFER_BINDING = 0x8ca7;\nexport const MAX_RENDERBUFFER_SIZE = 0x84e8;\n\nexport const INVALID_FRAMEBUFFER_OPERATION = 0x0506;\n\n/* WebGL-specific enums */\nexport const UNPACK_FLIP_Y_WEBGL = 0x9240;\nexport const UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;\nexport const CONTEXT_LOST_WEBGL = 0x9242;\nexport const UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;\nexport const BROWSER_DEFAULT_WEBGL = 0x9244;\n\nexport const SRGB_EXT = 0x8c40;\nexport const SRGB_ALPHA_EXT = 0x8c42;\nexport const SRGB8_ALPHA8_EXT = 0x8c43;\nexport const FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT = 0x8210;\n","import {\n FRONT,\n BACK,