/** * A shader is a program that is responsible for rendering graphical primitives on a device's * graphics processor. The shader is generated from a shader definition. This shader definition * specifies the code for processing vertices and fragments processed by the GPU. The language of * the code is GLSL (or more specifically ESSL, the OpenGL ES Shading Language). The shader * definition also describes how the PlayCanvas engine should map vertex buffer elements onto the * attributes specified in the vertex shader code. * * @category Graphics */ export class Shader { /** * Creates a new Shader instance. * * Consider {@link ShaderUtils.createShader} as a simpler and more powerful way to create * a shader. * * @param {GraphicsDevice} graphicsDevice - The graphics device used to manage this shader. * @param {object} definition - The shader definition from which to build the shader. * @param {string} [definition.name] - The name of the shader. * @param {Object} [definition.attributes] - Object detailing the mapping of * vertex shader attribute names to semantics SEMANTIC_*. This enables the engine to match * vertex buffer data as inputs to the shader. When not specified, rendering without vertex * buffer is assumed. * @param {string[]} [definition.feedbackVaryings] - A list of shader output variable * names that will be captured when using transform feedback. This setting is only effective * if the useTransformFeedback property is enabled. * @param {number} [definition.feedbackVaryingsMode] - Specifies how transform feedback varyings * are written into GPU buffers. Use {@link TRANSFORM_FEEDBACK_INTERLEAVED} to pack all captured * varyings into a single buffer, or {@link TRANSFORM_FEEDBACK_SEPARATE} to store each varying * in its own buffer. This setting is only effective when useTransformFeedback property is enabled. * Defaults to {@link TRANSFORM_FEEDBACK_INTERLEAVED}. * @param {string} [definition.vshader] - Vertex shader source (GLSL code). Optional when * compute shader is specified. * @param {string} [definition.fshader] - Fragment shader source (GLSL code). Optional when * useTransformFeedback or compute shader is specified. * @param {string} [definition.cshader] - Compute shader source (WGSL code). Only supported on * WebGPU platform. * @param {string} [definition.computeEntryPoint] - The entry point function name for the compute * shader. Defaults to 'main'. * @param {BindGroupFormat} [definition.computeBindGroupFormat] - The bind group format for * caller-provided compute resources in group 0. Only used on WebGPU. * @param {Object} [definition.computeUniformBufferFormats] - The * uniform buffer formats keyed by bind group entry name. Requires computeBindGroupFormat. * @param {Map} [definition.vincludes] - A map containing key-value pairs of * include names and their content. These are used for resolving #include directives in the * vertex shader source. * @param {Map} [definition.fincludes] - A map containing key-value pairs * of include names and their content. These are used for resolving #include directives in the * fragment shader source. * @param {Map} [definition.cincludes] - A map containing key-value pairs * of include names and their content. These are used for resolving #include directives in the * compute shader source. * @param {Map} [definition.cdefines] - A map containing key-value pairs of * define names and their values. These are used for resolving defines in the compute shader. * @param {boolean} [definition.useTransformFeedback] - Specifies that this shader outputs * post-VS data to a buffer. * @param {string | string[]} [definition.fragmentOutputTypes] - Fragment shader output types, * which default to vec4. Passing a string will set the output type for all color attachments. * Passing an array will set the output type for each color attachment. * @param {boolean} [definition.useDualSourceBlending] - Whether the fragment shader outputs a * secondary color for dual-source blending. Defaults to false. * @param {string} [definition.shaderLanguage] - Specifies the shader language of vertex and * fragment shaders. Defaults to {@link SHADERLANGUAGE_GLSL}. * @example * // Create a shader that renders primitives with a solid red color * * // Vertex shader * const vshader = ` * attribute vec3 aPosition; * * void main(void) { * gl_Position = vec4(aPosition, 1.0); * } * `; * * // Fragment shader * const fshader = ` * precision ${graphicsDevice.precision} float; * * void main(void) { * gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); * } * `; * * const shaderDefinition = { * attributes: { * aPosition: SEMANTIC_POSITION * }, * vshader, * fshader * }; * * const shader = new Shader(graphicsDevice, shaderDefinition); */ constructor(graphicsDevice: GraphicsDevice, definition: { name?: string; attributes?: { [x: string]: string; }; feedbackVaryings?: string[]; feedbackVaryingsMode?: number; vshader?: string; fshader?: string; cshader?: string; computeEntryPoint?: string; computeBindGroupFormat?: BindGroupFormat; computeUniformBufferFormats?: { [x: string]: UniformBufferFormat; }; vincludes?: Map; fincludes?: Map; cincludes?: Map; cdefines?: Map; useTransformFeedback?: boolean; fragmentOutputTypes?: string | string[]; useDualSourceBlending?: boolean; shaderLanguage?: string; }); /** * Format of the uniform buffer for mesh bind group. * * @type {UniformBufferFormat} * @ignore */ meshUniformBufferFormat: UniformBufferFormat; /** * True when the mesh uniform buffer holds no uniforms of the shader, only a placeholder, as * WebGPU requires the buffer bound. Its draws can share one buffer, bound once per pass. * * @type {boolean} * @ignore */ meshUniformBufferEmpty: boolean; /** * Format of the bind group for the mesh bind group. * * @type {BindGroupFormat} * @ignore */ meshBindGroupFormat: BindGroupFormat; /** * Format of the view bind group when the shader reads textures the renderer supplies per pass * in it, following the view uniform buffer, or null when the group holds only the view uniform * buffer. The format is shared by all shaders reading the same textures, and is not owned by * the shader. * * @type {BindGroupFormat|null} * @ignore */ viewBindGroupFormat: BindGroupFormat | null; /** * True when the vertex shader reads the model and normal matrices of the mesh instance from the * mesh instance storage of the device, see {@link GraphicsDevice#meshInstanceStorage}, indexed * by the instance index. The draws of such a shader pass the slot of the mesh instance as the * first instance. * * @type {boolean} * @ignore */ usesMeshInstanceStorage: boolean; /** * The attributes that this shader code uses. The location is the key, the value is the name. * These attributes are queried / extracted from the final shader. * * @type {Map} * @ignore */ attributes: Map; /** * Set by the shadow renderer once it has checked whether the shader reads the normal matrix, * which the shadow pass does not supply. Debug builds only. * * @type {boolean} * @private */ private _debugNormalMatrixChecked; id: number; device: GraphicsDevice; definition: { name?: string; attributes?: { [x: string]: string; }; feedbackVaryings?: string[]; feedbackVaryingsMode?: number; vshader?: string; fshader?: string; cshader?: string; computeEntryPoint?: string; computeBindGroupFormat?: BindGroupFormat; computeUniformBufferFormats?: { [x: string]: UniformBufferFormat; }; vincludes?: Map; fincludes?: Map; cincludes?: Map; cdefines?: Map; useTransformFeedback?: boolean; fragmentOutputTypes?: string | string[]; useDualSourceBlending?: boolean; shaderLanguage?: string; }; name: string; cUnmodified: string; vUnmodified: string; fUnmodified: string; failed: boolean; impl: any; /** * Initialize a shader back to its default state. * * @private */ private init; ready: boolean; /** @ignore */ get label(): string; /** * Whether the shader reads a uniform, for debug validation. On WebGL the active uniforms of the * linked program, from which the driver strips the unused ones. On WebGPU the uniforms the * shader declares, as WGSL is not reflected. Debug builds only. * * @param {string} name - The name of the uniform. * @returns {boolean|null} Whether the shader reads the uniform, or null when that is not known, * before the shader is ready or on a device without shader reflection. * @ignore */ debugReadsUniform(name: string): boolean | null; /** * Frees resources associated with this shader. */ destroy(): void; /** * Called when the WebGL context was lost. It releases all context related resources. * * @ignore */ loseContext(): void; /** @ignore */ restoreContext(): void; } import type { UniformBufferFormat } from './uniform-buffer-format.js'; import type { BindGroupFormat } from './bind-group-format.js'; import type { GraphicsDevice } from './graphics-device.js';