Files
nothoughts/node_modules/pixi.js/lib/rendering/renderers/shared/shader/Shader.d.ts
2025-08-04 18:57:35 +02:00

186 lines
7.7 KiB
TypeScript

import EventEmitter from 'eventemitter3';
import { GlProgram } from '../../gl/shader/GlProgram';
import { BindGroup } from '../../gpu/shader/BindGroup';
import { GpuProgram } from '../../gpu/shader/GpuProgram';
import type { GlProgramOptions } from '../../gl/shader/GlProgram';
import type { GpuProgramOptions } from '../../gpu/shader/GpuProgram';
/**
* A record of {@link BindGroup}'s used by the shader.
*
* `Record<number, BindGroup>`
* @memberof rendering
*/
export type ShaderGroups = Record<number, BindGroup>;
interface ShaderBase {
/** The WebGL program used by the WebGL renderer. */
glProgram?: GlProgram;
/** The WebGPU program used by the WebGPU renderer. */
gpuProgram?: GpuProgram;
/**
* A number that uses two bits on whether the shader is compatible with the WebGL renderer and/or the WebGPU renderer.
* 0b00 - not compatible with either
* 0b01 - compatible with WebGL
* 0b10 - compatible with WebGPU
* This is automatically set based on if a {@link GlProgram} or {@link GpuProgram} is provided.
*/
compatibleRenderers?: number;
}
export interface GlShaderWith extends ShaderBase {
/** The WebGL program used by the WebGL renderer. */
glProgram: GlProgram;
}
export interface GpuShaderWith extends ShaderBase {
/** The WebGPU program used by the WebGPU renderer. */
gpuProgram: GpuProgram;
}
export interface ShaderWithGroupsDescriptor {
/** A record of {@link BindGroup}'s used by the shader. */
groups: ShaderGroups;
/** an optional map of how to bind the groups. This is automatically generated by reading the WebGPU program */
groupMap?: Record<string, Record<string, any>>;
}
interface ShaderWithResourcesDescriptor {
/**
* A key value of uniform resources used by the shader.
* Under the hood pixi will look at the provided shaders and figure out where
* the resources are mapped. Its up to you to make sure the resource key
* matches the uniform name in the webGPU program. WebGL is a little more forgiving!
*/
resources?: Record<string, any>;
}
/**
* A descriptor for a shader
* @memberof rendering
*/
export type ShaderWith = GlShaderWith | GpuShaderWith;
/**
* A descriptor for a shader with groups.
* @memberof rendering
*/
export type ShaderWithGroups = ShaderWithGroupsDescriptor & ShaderWith;
export interface IShaderWithGroups extends ShaderWithGroupsDescriptor, ShaderBase {
}
/**
* A descriptor for a shader with resources. This is an easier way to work with uniforms.
* especially when you are not working with bind groups
* @memberof rendering
*/
export type ShaderWithResources = ShaderWithResourcesDescriptor & ShaderWith;
export interface IShaderWithResources extends ShaderWithResourcesDescriptor, ShaderBase {
}
export type ShaderDescriptor = ShaderWithGroups & ShaderWithResources;
type GlShaderFromWith = {
gpu?: GpuProgramOptions;
gl: GlProgramOptions;
};
type GpuShaderFromWith = {
gpu: GpuProgramOptions;
gl?: GlProgramOptions;
};
export type ShaderFromGroups = (GlShaderFromWith | GpuShaderFromWith) & Omit<ShaderWithGroups, 'glProgram' | 'gpuProgram'>;
export type ShaderFromResources = (GlShaderFromWith | GpuShaderFromWith) & Omit<ShaderWithResources, 'glProgram' | 'gpuProgram'>;
/**
* The Shader class is an integral part of the PixiJS graphics pipeline.
* Central to rendering in PixiJS are two key elements: A [shader] and a [geometry].
* The shader incorporates a {@link GlProgram} for WebGL or a {@link GpuProgram} for WebGPU,
* instructing the respective technology on how to render the geometry.
*
* The primary goal of the Shader class is to offer a unified interface compatible with both WebGL and WebGPU.
* When constructing a shader, you need to provide both a WebGL program and a WebGPU program due to the distinctions
* between the two rendering engines. If only one is provided, the shader won't function with the omitted renderer.
*
* Both WebGL and WebGPU utilize the same resource object when passed into the shader.
* Post-creation, the shader's interface remains consistent across both WebGL and WebGPU.
* The sole distinction lies in whether a glProgram or a gpuProgram is employed.
*
* Modifying shader uniforms, which can encompass:
* - TextureSampler {@link TextureStyle}
* - TextureSource {@link TextureSource}
* - UniformsGroups {@link UniformGroup}
* @example
*
* const shader = new Shader({
* glProgram: glProgram,
* gpuProgram: gpuProgram,
* resources: {
* uTexture: texture.source,
* uSampler: texture.sampler,
* uColor: [1, 0, 0, 1],
* },
* });
*
* // update the uniforms
* shader.resources.uColor[1] = 1;
* shader.resources.uTexture = texture2.source;
* @class
* @memberof rendering
*/
export declare class Shader extends EventEmitter<{
'destroy': Shader;
}> {
/** An instance of the GPU program used by the WebGPU renderer */
gpuProgram: GpuProgram;
/** An instance of the GL program used by the WebGL renderer */
glProgram: GlProgram;
/**
* A number that uses two bits on whether the shader is compatible with the WebGL renderer and/or the WebGPU renderer.
* 0b00 - not compatible with either
* 0b01 - compatible with WebGL
* 0b10 - compatible with WebGPU
* This is automatically set based on if a {@link GlProgram} or {@link GpuProgram} is provided.
*/
readonly compatibleRenderers: number;
/** */
groups: Record<number, BindGroup>;
/** A record of the resources used by the shader. */
resources: Record<string, any>;
/**
* A record of the uniform groups and resources used by the shader.
* This is used by WebGL renderer to sync uniform data.
* @internal
* @ignore
*/
_uniformBindMap: Record<number, Record<number, string>>;
private readonly _ownedBindGroups;
/**
* Fired after rendering finishes.
* @event rendering.Shader#destroy
*/
/**
* There are two ways to create a shader.
* one is to pass in resources which is a record of uniform groups and resources.
* another is to pass in groups which is a record of {@link BindGroup}s.
* this second method is really to make use of shared {@link BindGroup}s.
* For most cases you will want to use resources as they are easier to work with.
* USe Groups if you want to share {@link BindGroup}s between shaders.
* you cannot mix and match - either use resources or groups.
* @param {ShaderWithResourcesDescriptor} options - The options for the shader using ShaderWithResourcesDescriptor.
*/
constructor(options: ShaderWithResources);
constructor(options: ShaderWithGroups);
/**
* Sometimes a resource group will be provided later (for example global uniforms)
* In such cases, this method can be used to let the shader know about the group.
* @param name - the name of the resource group
* @param groupIndex - the index of the group (should match the webGPU shader group location)
* @param bindIndex - the index of the bind point (should match the webGPU shader bind point)
*/
addResource(name: string, groupIndex: number, bindIndex: number): void;
private _buildResourceAccessor;
/**
* Use to destroy the shader when its not longer needed.
* It will destroy the resources and remove listeners.
* @param destroyPrograms - if the programs should be destroyed as well.
* Make sure its not being used by other shaders!
*/
destroy(destroyPrograms?: boolean): void;
/**
* A short hand function to create a shader based of a vertex and fragment shader.
* @param options
* @returns A shiny new PixiJS shader!
*/
static from(options: ShaderFromGroups): Shader;
static from(options: ShaderFromResources): Shader;
}
export {};