/** * a complete custom shader program. Historically a WebGL-only GLSL * program (the class keeps its name for compatibility), since 20.0 it can * carry one realization per GPU backend — a `{vertex, fragment}` GLSL * pair for the WebGL renderer and/or a complete `wgsl` module for the * WebGPU renderer — mirroring how {@link ShaderEffect} carries one body * per shading language. The {@link GLShader#isWebGL} / {@link GLShader#isWebGPU} * flags report which realizations exist; a renderer hosts the one it * speaks and anything else degrades to the built-in shading (never fatal). * * ### The WGSL module contract (custom `Mesh` shaders) * * The `wgsl` source is a complete module hosted by the mesh batchers: * entry points must be named **`vertex_main`** (`@vertex`) and * **`fragment_main`** (`@fragment`), over the frozen mesh vertex layout — * `@location(0) aVertex : vec3f`, `@location(1) aRegion : vec2f`, * `@location(2) aColor : vec4f`, plus `@location(3) aNormal : vec3f` on * the 48-byte `lit` layout. Bind groups (declare only what is read): * group 0 `FrameUniforms {projection : mat4x4, lineWidth : f32}`, * group 1 the mesh texture + sampler, group 2 the `Light3dBlock` (lit * host only), group 3 `MeshUniforms {model, view : mat4x4, * tint, params, emissive : vec4f}` (`params.x` = alpha cutout). The * vertex stage owns the projection (`projection * view * model`) and must * remap the GL-convention clip z: `(clip.z + clip.w) * 0.5`. WGSL * validation is asynchronous and never throws — a failing module logs its * errors once and the mesh falls back to the built-in shading. * @category Rendering */ export default class GLShader { /** * @param {WebGLRenderingContext} [gl] - the current WebGL rendering * context (`renderer.gl` — undefined on non-WebGL renderers, which * simply skips the GLSL realization) * @param {string|object} vertex - a string containing the GLSL vertex * source, OR a sources object `{vertex, fragment, wgsl, precision, * label}` carrying one realization per backend (any omittable) * @param {string} [fragment] - a string containing the GLSL fragment source * @param {string} [precision=auto detected] - float precision ('lowp', 'mediump' or 'highp'). * @see https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_on_the_web/GLSL_Shaders * @example * // create a basic shader * let myShader = new me.GLShader( * // WebGL rendering context * gl, * // vertex shader * [ * "void main() {", * " gl_Position = doMathToMakeClipspaceCoordinates;", * "}" * ].join("\n"), * // fragment shader * [ * "void main() {", * " gl_FragColor = doMathToMakeAColor;", * "}" * ].join("\n") * ) * // use the shader * myShader.bind(); * @example * // a dual-backend custom mesh shader: the same object hosts on * // whichever GPU renderer is active (gl is undefined on WebGPU) * myMesh.addPostEffect(new me.GLShader(app.renderer.gl, { * vertex: toonVertexGLSL, * fragment: toonFragmentGLSL, * wgsl: toonModuleWGSL, * })); */ constructor(gl?: WebGLRenderingContext, vertex: string | object, fragment?: string, precision?: string); /** * the active gl rendering context * @type {WebGLRenderingContext} */ gl: WebGLRenderingContext; /** * `true` when this shader carries a WebGL realization: a * `{vertex, fragment}` GLSL pair compiled against a live context. * @type {boolean} * @readonly */ readonly isWebGL: boolean; /** * `true` when this shader carries a WebGPU realization: a complete * `wgsl` module (see the class docs for the module contract). * @type {boolean} * @readonly */ readonly isWebGPU: boolean; /** * the complete WGSL module source, when {@link GLShader#isWebGPU} * @type {string|undefined} */ wgsl: string | undefined; /** * optional debug label, carried onto the GPU shader module (shows * up in browser GPU error messages and profilers) * @type {string|undefined} */ label: string | undefined; wgslValid: boolean; /** * `true` once {@link destroy} has been called. After this flag is * `true`, every method on the shader is a silent no-op — callers * holding a stale reference (e.g. a still-registered update loop) * do not crash the frame. * @type {boolean} * @readonly */ readonly destroyed: boolean; /** * When `true`, a renderable will NOT auto-destroy this shader when it is * removed from its `postEffects` (via the `shader` setter, * `removePostEffect`, `clearPostEffects`) or when the renderable itself * is destroyed. Set this on a shader shared across several renderables so * one of them going away doesn't free the GL program still used by the * others — you then own its lifecycle and call {@link destroy} yourself. * @type {boolean} * @default false */ shared: boolean; /** * `true` while the WebGL context is lost (and until it's * restored). The GL program/attributes/uniforms are released * during the suspended window but the shader source code is * preserved so {@link _onContextRestored} can rebuild the * program against the new context. User code generally doesn't * read this — methods short-circuit internally — but it's * available for diagnostic / debug-plugin tooling. * @type {boolean} * @readonly */ readonly suspended: boolean; program: WebGLProgram; uniforms: object; attributes: number[]; vertex: any; fragment: any; /** * Installs this shader program as part of current rendering state */ bind(): void; /** * returns the location of an attribute variable in this shader program * @param {string} name - the name of the attribute variable whose location to get. * @returns {GLint} number indicating the location of the variable name if found. Returns -1 otherwise */ getAttribLocation(name: string): GLint; /** * Set the uniform to the given value * @param {string} name - the uniform name * @param {number|boolean|number[]|Float32Array|object} value - the value to assign to that * uniform. Scalars (`float`, `int`, `bool`) take a number or a boolean; * vectors and matrices take an array, a `Float32Array`, or any object * exposing `toArray()` — which is every {@link Vector2d}, * {@link Vector3d}, {@link Color} and {@link Matrix3d}. * @example * myShader.setUniform("uProjectionMatrix", this.projectionMatrix); * myShader.setUniform("uStrength", 0.5); // a scalar is a plain number */ setUniform(name: string, value: number | boolean | number[] | Float32Array | object): void; /** * activate the given vertex attribute for this shader. * * Note: since 20.0 the engine no longer calls this per frame — each * {@link WebGLBatcher} captures its attribute layout once into an immutable * vertex-state object (VAO) at init (see `WebGLBatcher.createVertexState`). * Kept public for custom callers managing their own vertex setup. * Custom shaders hosted by a built-in batcher must declare that * batcher's attributes first, in layout order — attribute locations * are bound in declaration order and the vertex state is frozen. * @param {WebGLRenderingContext} gl - the current WebGL rendering context * @param {object[]} attributes - an array of vertex attributes * @param {number} stride - the size of a single vertex in bytes */ setVertexAttributes(gl: WebGLRenderingContext, attributes: object[], stride: number): void; /** * Create an independent copy of this shader, compiled as its own GL * program from the same vertex + fragment sources (and precision), with * every uniform value set so far replayed onto the copy. Use it when * several renderables need the same custom shader with *different* * uniform values — a single instance has a single set of uniforms. * * Ownership and lifecycle state do NOT carry over: the clone's * {@link shared} flag is **always reset to `false`**, even when cloning * a shared shader — the clone is caller-owned and will be auto-destroyed * by the renderable it is assigned to, unless you explicitly set * `shared = true` on it yourself. Note that `ShaderEffect` (which wraps * a GLShader by composition) has its own `clone()` with the same * semantics, which additionally copies its effect-level state (extra * `setTexture` bindings). * @returns {GLShader} a new, caller-owned shader (`shared === false`) */ clone(): GLShader; /** * destroy this shader objects resources (program, attributes, uniforms). * Idempotent — calling destroy twice (or after a context-lost suspend) * is safe. Unsubscribes from the renderer's context lost / restored * events so a destroyed shader is never automatically resurrected. */ destroy(): void; } //# sourceMappingURL=glshader.d.ts.map