UNPKG

webgl-dsl

Version:

Thin functional WebGL wrapper with strong typed GLSL DSL

327 lines (326 loc) 15.4 kB
import { Texture } from './texture'; export declare enum Type { Scalar = "float", Vector2 = "vec2", Matrix2 = "mat2", Vector3 = "vec3", Matrix3 = "mat3", Vector4 = "vec4", Matrix4 = "mat4", Boolean = "bool", Sampler = "sampler2D" } export declare enum Precision { High = "highp", Medium = "mediump", Low = "lowp" } export type TypeSize = 1 | 2 | 3 | 4; export declare namespace Type { function size(type: Type.Boolean | Type.Scalar | Type.Sampler): 1; function size(type: Type.Vector2 | Type.Matrix2): 2; function size(type: Type.Vector3 | Type.Matrix3): 3; function size(type: Type.Vector4 | Type.Matrix4): 4; function size(type: Type): TypeSize; function vector(size: 2): Type.Vector2; function vector(size: 3): Type.Vector3; function vector(size: 4): Type.Vector4; function vector(size: 2 | 3 | 4): Type.AnyVector; function numeric(size: 1): Type.Scalar; function numeric(size: 2): Type.Vector2; function numeric(size: 3): Type.Vector3; function numeric(size: 4): Type.Vector4; function numeric(size: TypeSize): Type.AnyNumeric; type Numeric<S extends TypeSize> = S extends 1 ? Type.Scalar : S extends 2 ? Type.Vector2 : S extends 3 ? Type.Vector3 : Type.Vector4; type GetSize<T extends Type.AnyNumeric> = T extends Type.Scalar ? 1 : T extends Type.Vector2 ? 2 : T extends Type.Vector3 ? 3 : 4; type Indexes<T extends Type.AnyVector> = T extends Type.Vector2 ? 0 | 1 : T extends Type.Vector3 ? 0 | 1 | 2 : 0 | 1 | 2 | 3; type AnyVector = Type.Vector2 | Type.Vector3 | Type.Vector4; type AnyMatrix = Type.Matrix2 | Type.Matrix3 | Type.Matrix4; type AnyNumeric = Type.Scalar | AnyVector; type JsType<T extends Type> = T extends Type.Scalar ? number : T extends Type.Vector2 ? number[] | { x: number; y: number; } : T extends Type.Vector3 ? number[] | { x: number; y: number; z: number; } : T extends Type.Vector4 ? number[] : T extends Type.Matrix2 ? number[] : T extends Type.Matrix3 ? number[] : T extends Type.Matrix4 ? number[] : T extends Type.Sampler ? Texture : never; function isVector(v: Type): v is AnyVector; function isMatrix(v: Type): v is AnyMatrix; } export type Value<T extends Type = Type> = Readonly<{ type: T; content: string; }>; export declare class GlslBuilder { private readonly cache; private global; private local; constructor(cache?: Map<string, any>); once<R>(id: string, callback: () => R): R; getGlobal(): string; addGlobal(content: string): this; getLocal(): string; addLocal(content: string): this; child(): GlslBuilder; } export declare namespace Glsl { type Boolean = Glsl<Type.Boolean>; type Scalar = Glsl<Type.Scalar>; type Vector2 = Glsl<Type.Vector2>; type Vector3 = Glsl<Type.Vector3>; type Vector4 = Glsl<Type.Vector4>; type Matrix2 = Glsl<Type.Matrix2>; type Matrix3 = Glsl<Type.Matrix3>; type Matrix4 = Glsl<Type.Matrix4>; type Sampler = Glsl<Type.Sampler>; type AnyVector = Glsl<Type.AnyVector>; type AnyNumeric = Glsl<Type.AnyNumeric>; type AnyMatrix = Glsl<Type.AnyMatrix>; } export declare class Glsl<T extends Type = Type> { readonly getValue: (builder: GlslBuilder) => Value<T>; constructor(getValue: (builder: GlslBuilder) => Value<T>); private static call; private unary; sin(this: Glsl<Type.AnyNumeric>): Glsl<T>; cos(this: Glsl<Type.AnyNumeric>): Glsl<T>; radians(this: Glsl<Type.AnyNumeric>): Glsl<T>; degrees(this: Glsl<Type.AnyNumeric>): Glsl<T>; tan(this: Glsl<Type.AnyNumeric>): Glsl<T>; asin(this: Glsl<Type.AnyNumeric>): Glsl<T>; acos(this: Glsl<Type.AnyNumeric>): Glsl<T>; exp(this: Glsl<Type.AnyNumeric>): Glsl<T>; log(this: Glsl<Type.AnyNumeric>): Glsl<T>; exp2(this: Glsl<Type.AnyNumeric>): Glsl<T>; log2(this: Glsl<Type.AnyNumeric>): Glsl<T>; sqrt(this: Glsl<Type.AnyNumeric>): Glsl<T>; inversesqrt(this: Glsl<Type.AnyNumeric>): Glsl<T>; abs(this: Glsl<Type.AnyNumeric>): Glsl<T>; sign(this: Glsl<Type.AnyNumeric>): Glsl<T>; floor(this: Glsl<Type.AnyNumeric>): Glsl<T>; ceil(this: Glsl<Type.AnyNumeric>): Glsl<T>; fract(this: Glsl<Type.AnyNumeric>): Glsl<T>; normalize(this: Glsl<Type.AnyNumeric>): Glsl<T>; round<T extends Glsl.AnyNumeric>(this: T): T; not(this: Glsl<Type.Boolean>): Glsl<Type.Boolean>; atan<T extends Type.AnyNumeric>(this: Glsl<T>): Glsl<T>; atan<T extends Type.AnyNumeric>(this: Glsl<T>, x: Glsl<T>): Glsl<T>; atan(this: Glsl.Scalar, x: number): Glsl.Scalar; pow(this: Glsl.Scalar, p: Glsl.Scalar): Glsl.Scalar; pow(this: Glsl.Vector2, p: Glsl.Vector2): Glsl.Vector2; pow(this: Glsl.Vector3, p: Glsl.Vector3): Glsl.Vector3; pow(this: Glsl.Vector4, p: Glsl.Vector4): Glsl.Vector4; pow(this: Glsl.Scalar, p: number): Glsl.Scalar; mod<P extends Type.AnyNumeric>(this: Glsl<P>, p: Glsl<P>): Glsl<P>; mod(this: Glsl.Scalar, p: number): Glsl.Scalar; min<P extends Type.AnyNumeric>(this: Glsl<P>, p: Glsl<P>): Glsl<P>; min(this: Glsl.Scalar, p: number): Glsl.Scalar; max<P extends Type.AnyNumeric>(this: Glsl<P>, p: Glsl<P>): Glsl<P>; max(this: Glsl.Scalar, p: number): Glsl.Scalar; mix<P extends Glsl.AnyNumeric>(this: P, other: P, p: P): P; mix<P extends Glsl.AnyNumeric>(this: P, other: P, p: number): P; mix(this: Glsl.Scalar, other: number, p: Glsl.Scalar | number): Glsl.Scalar; clamp<T extends Glsl.AnyNumeric>(this: T, min: T, max: T): T; clamp<T extends Glsl.AnyNumeric>(this: T, min: Glsl.Scalar | number, max: Glsl.Scalar | number): T; smoothstep(this: Glsl.Scalar, edge1: Glsl.Scalar | number, edge2: Glsl.Scalar | number): Glsl.Scalar; smoothstep<T extends Glsl.AnyNumeric>(this: T, edge1: T, edge2: T): T; smoothstep<T extends Glsl.AnyNumeric>(this: Glsl.Scalar, edge1: Glsl.Scalar | number, edge2: Glsl.Scalar | number): T; length(this: Glsl.AnyNumeric): Glsl.Scalar; distance<T extends Glsl.AnyNumeric>(this: T, other: T): Glsl.Scalar; distance(this: Glsl.Scalar, other: number): Glsl.Scalar; dot<T extends Glsl.AnyNumeric>(this: T, other: T): Glsl.Scalar; dot(this: Glsl.Scalar, other: number): Glsl.Scalar; reflect<T extends Glsl.AnyNumeric>(this: T, n: T): T; refract<T extends Glsl.AnyNumeric>(this: T, n: T, eta: Glsl.Scalar | number): T; /** * Get texture value at the specified point */ texture2D(this: Glsl.Sampler, point: Glsl.Vector2): Glsl.Vector4; add<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(this: T, other: T | Glsl.Scalar | number): T; add<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(this: Glsl.Scalar, other: T): T; sub<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(this: T, other: T | Glsl.Scalar | number): T; sub<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(this: Glsl.Scalar, other: T): T; div<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(this: T, other: T | Glsl.Scalar | number): T; div<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(this: Glsl.Scalar, other: T): T; mul<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(this: T, other: T | Glsl.Scalar | number): T; mul<T extends Glsl.AnyNumeric | Glsl.AnyMatrix>(this: Glsl.Scalar, other: T | Glsl.Scalar | number): T; mul(this: Glsl.Matrix2, other: Glsl.Vector2): Glsl.Vector2; mul(this: Glsl.Vector2, other: Glsl.Matrix2): Glsl.Vector2; mul(this: Glsl.Matrix3, other: Glsl.Vector3): Glsl.Vector3; mul(this: Glsl.Vector3, other: Glsl.Matrix3): Glsl.Vector3; mul(this: Glsl.Matrix4, other: Glsl.Vector4): Glsl.Vector4; mul(this: Glsl.Vector4, other: Glsl.Matrix4): Glsl.Vector4; private bool; /** Less */ lt(this: Glsl.Scalar, other: Glsl.Scalar | number): Glsl.Boolean; /** Greater */ gt(this: Glsl.Scalar, other: Glsl.Scalar | number): Glsl.Boolean; /** Less or equal */ lte(this: Glsl.Scalar, other: Glsl.Scalar | number): Glsl.Boolean; /** Greater or equal */ gte(this: Glsl.Scalar, other: Glsl.Scalar | number): Glsl.Boolean; /** Equal */ eq(this: Glsl.Scalar, other: Glsl.Scalar | number): Glsl.Boolean; /** Not equal */ neq(this: Glsl.Scalar, other: Glsl.Scalar | number): Glsl.Boolean; and(this: Glsl.Boolean, other: Glsl.Boolean): Glsl.Boolean; or(this: Glsl.Boolean, other: Glsl.Boolean): Glsl.Boolean; /** * Save some expression into a variable */ mem<T extends Glsl>(this: T, precision: Precision): T; /** * Save some expression with high quality into a variable */ memHQ(): this; /** * Save some expression with medium quality into a variable */ memMQ(): this; /** * Save some expression with low quality into a variable */ memLQ(): this; /** * Conditional expression * @param precision Precision of the expression result * @param whenTrue True brunch of the condition * @param whenFalse False brunch of the condition */ cond<T extends Glsl>(this: Glsl.Boolean, precision: Precision, whenTrue: T, whenFalse: T): T; condHQ<T extends Glsl>(this: Glsl.Boolean, whenTrue: T, whenFalse: T): T; condMQ<T extends Glsl>(this: Glsl.Boolean, whenTrue: T, whenFalse: T): T; condLQ<T extends Glsl>(this: Glsl.Boolean, whenTrue: T, whenFalse: T): T; take<T extends Type.AnyVector>(this: Glsl<T>, i: Type.Indexes<T>): Glsl.Scalar; take<T extends Type.AnyVector>(this: Glsl<T>, i1: Type.Indexes<T>, i2: Type.Indexes<T>): Glsl.Vector2; take<T extends Type.Vector3 | Type.Vector4>(this: Glsl<T>, i1: Type.Indexes<T>, i2: Type.Indexes<T>, i3: Type.Indexes<T>): Glsl.Vector3; take(this: Glsl.Vector4, i1: Type.Indexes<Type.Vector4>, i2: Type.Indexes<Type.Vector4>, i3: Type.Indexes<Type.Vector4>, i4: Type.Indexes<Type.Vector4>): Glsl.Vector4; vec2(this: Glsl.Scalar): Glsl.Vector2; vec3(this: Glsl.Scalar): Glsl.Vector3; vec4(this: Glsl.Scalar): Glsl.Vector4; /** * Get the first component of vector */ x(this: Glsl.AnyVector): Glsl.Scalar; /** * Get the second component of vector */ y(this: Glsl.Vector2 | Glsl.Vector3 | Glsl.Vector4): Glsl.Scalar; /** * Get the third component of vector */ z(this: Glsl.Vector3 | Glsl.Vector4): Glsl.Scalar; /** * Get the fourth component of vector */ w(this: Glsl.Vector4): Glsl.Scalar; /** * Get the first component of vector */ r(this: Glsl.AnyVector): Glsl.Scalar; /** * Get the second component of vector */ g(this: Glsl.Vector2 | Glsl.Vector3 | Glsl.Vector4): Glsl.Scalar; /** * Get the third component of vector */ b(this: Glsl.Vector3 | Glsl.Vector4): Glsl.Scalar; /** * Get the fourth component of vector */ a(this: Glsl.Vector4): Glsl.Scalar; cat(this: Glsl.Scalar, v: Glsl.Scalar | number): Glsl.Vector2; cat(this: Glsl.Scalar, v: Glsl.Vector2): Glsl.Vector3; cat(this: Glsl.Scalar, v: Glsl.Vector3): Glsl.Vector4; cat(this: Glsl.Vector2, v: Glsl.Scalar | number): Glsl.Vector3; cat(this: Glsl.Vector2, v: Glsl.Vector2): Glsl.Vector4; cat(this: Glsl.Vector3, v: Glsl.Scalar | number): Glsl.Vector4; static val(v: boolean): Glsl<Type.Boolean>; static val(v: number): Glsl.Scalar; static val<T extends Glsl>(v: T): T; static val(v1: Glsl.Scalar | number, v2: Glsl.Scalar | number): Glsl.Vector2; static val(v1: Glsl.Scalar | number, v2: Glsl.Vector2): Glsl.Vector3; static val(v1: Glsl.Scalar | number, v2: Glsl.Vector3): Glsl.Vector4; static val(v1: Glsl.Vector2, v2: Glsl.Scalar | number): Glsl.Vector3; static val(v1: Glsl.Vector3, v2: Glsl.Scalar | number): Glsl.Vector4; static val(v1: Glsl.Scalar | number, v2: Glsl.Scalar | number, v3: Glsl.Scalar | number): Glsl.Vector3; static val(v1: Glsl.Vector2, v2: Glsl.Scalar | number, v3: Glsl.Scalar | number): Glsl.Vector4; static val(v1: Glsl.Scalar | number, v2: Glsl.Vector2, v3: Glsl.Scalar | number): Glsl.Vector4; static val(v1: Glsl.Scalar | number, v2: Glsl.Scalar | number, v3: Glsl.Vector2): Glsl.Vector4; static val(v1: Glsl.Scalar | number, v2: Glsl.Scalar | number, v3: Glsl.Scalar | number, v4: Glsl.Scalar | number): Glsl.Vector4; static PI: Glsl.Scalar; } /** * Description of attributes/uniforms/varyings */ export type TypeMap = { [key: string]: Type | [Type, Precision]; }; export declare namespace TypeMap { type GetType<T extends Type | [Type, Precision]> = T extends Type ? T : T[0]; type JsTypeMap<T extends TypeMap> = { [key in keyof T]: Type.JsType<GetType<T[key]>>; }; type ToValues<M extends TypeMap> = { [key in keyof M]: Glsl<GetType<M[key]>>; }; type WithoutPrecision<M extends TypeMap> = { [key in keyof M]: GetType<M[key]>; }; function getType(v: Type | [Type, Precision]): Type; function getPrecision(v: Type | [Type, Precision]): Precision; function withoutPrecision<M extends TypeMap>(map: M): WithoutPrecision<M>; function values(storage: "uniform" | "attribute" | "varying", types: TypeMap): { [key: string]: Glsl<Type>; }; function stride(map: TypeMap): number; interface LayoutItem { name: string; size: number; stride: number; offset: number; } function layout(map: TypeMap): LayoutItem[]; } /** * Description of a shader program */ export type SourceConfig<Uniforms extends TypeMap, Attributes extends TypeMap, Instances extends TypeMap, Varyings extends TypeMap = {}> = { uniforms: Uniforms; attributes: Attributes; instances?: Instances; varyings?: Varyings; vertex: (input: TypeMap.ToValues<Uniforms> & TypeMap.ToValues<Attributes> & TypeMap.ToValues<Instances>) => TypeMap.ToValues<Varyings> & { gl_Position: Glsl.Vector4; gl_PointSize?: Glsl.Scalar; }; fragment: (input: TypeMap.ToValues<Uniforms> & TypeMap.ToValues<Varyings> & { gl_FragCoord: Glsl.Vector4; gl_FrontFacing: Glsl.Boolean; gl_PointCoord: Glsl.Vector2; }) => { gl_FragColor: Glsl.Vector4; }; }; export type ProgramSource<Uniforms extends TypeMap, Attributes extends TypeMap, Instances extends TypeMap> = { uniforms: Uniforms; attributes: Attributes; instances: Instances; fragment: string; vertex: string; }; export declare namespace ProgramSource { type GetUniforms<T extends ProgramSource<any, any, any>> = T extends ProgramSource<infer R, any, any> ? R : never; type GetAttributes<T extends ProgramSource<any, any, any>> = T extends ProgramSource<any, infer R, any> ? R : never; type GetInstances<T extends ProgramSource<any, any, any>> = T extends ProgramSource<any, any, infer R> ? R : never; } /** * Create GLSL program source from argument types and shaders described with the DSL */ export declare function source<Uniforms extends TypeMap, Attributes extends TypeMap, Instances extends TypeMap, Varyings extends TypeMap = {}>({ uniforms, attributes, varyings, instances, fragment, vertex, }: SourceConfig<Uniforms, Attributes, Instances, Varyings>): ProgramSource<TypeMap.WithoutPrecision<Uniforms>, TypeMap.WithoutPrecision<Attributes>, TypeMap.WithoutPrecision<Instances>>; /** * Wrap a set of values into a single GLSL value */ export declare const val: typeof Glsl.val;