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` * @memberof rendering */ export type ShaderGroups = Record; 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>; } 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; } /** * 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; export type ShaderFromResources = (GlShaderFromWith | GpuShaderFromWith) & Omit; /** * 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; /** A record of the resources used by the shader. */ resources: Record; /** * 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>; 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 {};