playcanvas
Version:
PlayCanvas WebGL game engine
726 lines (725 loc) • 26.4 kB
TypeScript
/**
* Callback used by {@link Layer} to calculate the "sort distance" for a {@link MeshInstance},
* which determines its place in the render order.
*/
export type CalculateSortDistanceCallback = (meshInstance: MeshInstance, cameraPosition: Vec3, cameraForward: Vec3) => void;
/**
* @callback CalculateSortDistanceCallback
* Callback used by {@link Layer} to calculate the "sort distance" for a {@link MeshInstance},
* which determines its place in the render order.
* @param {MeshInstance} meshInstance - The mesh instance.
* @param {Vec3} cameraPosition - The position of the camera.
* @param {Vec3} cameraForward - The forward vector of the camera.
* @returns {void}
*/
/**
* An instance of a {@link Mesh}. A single mesh can be referenced by many mesh instances that can
* have different transforms and materials.
*
* ### Instancing
*
* Hardware instancing lets the GPU draw many copies of the same geometry with a single draw call.
* Use {@link setInstancing} to attach a vertex buffer that holds per-instance data
* (for example a mat4 world-matrix for every instance). Set {@link instancingCount}
* to control how many instances are rendered. Passing `null` to {@link setInstancing}
* disables instancing once again.
*
* ```javascript
* // vb is a vertex buffer with one 4×4 matrix per instance
* meshInstance.setInstancing(vb);
* meshInstance.instancingCount = numInstances;
* ```
*
* **Examples**
*
* - {@link https://playcanvas.github.io/#graphics/instancing-basic graphics/instancing-basic}
* - {@link https://playcanvas.github.io/#graphics/instancing-custom graphics/instancing-custom}
*
* ### GPU-Driven Indirect Rendering (WebGPU Only)
*
* Instead of issuing draw calls from the CPU, parameters are written into a GPU
* storage buffer and executed via indirect draw commands. Allocate one or more slots with
* `GraphicsDevice.getIndirectDrawSlot(count)`, then bind the mesh instance to those slots:
*
* ```javascript
* const slot = app.graphicsDevice.getIndirectDrawSlot(count);
* meshInstance.setIndirect(null, slot, count); // first arg can be a CameraComponent or null
* ```
*
* **Example**
*
* - {@link https://playcanvas.github.io/#compute/indirect-draw compute/indirect-draw}
*
* ### Multi-draw
*
* Multi-draw lets the engine submit multiple sub-draws with a single API call. On WebGL2 this maps
* to the `WEBGL_multi_draw` extension; on WebGPU, to indirect multi-draw. Use {@link setMultiDraw}
* to allocate a {@link DrawCommands} container, fill it with sub-draws using
* {@link DrawCommands#add} and finalize with {@link DrawCommands#update} whenever the data changes.
*
* Support: {@link GraphicsDevice#supportsMultiDraw} is true on WebGPU and commonly true on WebGL2
* (high coverage). When not supported, the engine can still render by issuing a fast internal loop
* of single draws using the multi-draw data.
*
* ```javascript
* // two indexed sub-draws from a single mesh
* const cmd = meshInstance.setMultiDraw(null, 2);
* cmd.add(0, 36, 1, 0);
* cmd.add(1, 60, 1, 36);
* cmd.update(2);
* ```
*
* @category Graphics
*/
export class MeshInstance {
static lightmapParamNames: string[];
/**
* Sets the render style for an array of mesh instances.
*
* @param {MeshInstance[]} meshInstances - The mesh instances to set the render style for.
* @param {number} renderStyle - The render style to set.
* @ignore
*/
static _prepareRenderStyleForArray(meshInstances: MeshInstance[], renderStyle: number): void;
/**
* Create a new MeshInstance instance.
*
* @param {Mesh} mesh - The graphics mesh to instance.
* @param {Material} material - The material to use for this mesh instance.
* @param {GraphNode} [node] - The graph node defining the transform for this instance. This
* parameter is optional when used with {@link RenderComponent} and will use the node the
* component is attached to.
* @example
* // Create a mesh instance pointing to a 1x1x1 'cube' mesh
* const mesh = pc.Mesh.fromGeometry(app.graphicsDevice, new pc.BoxGeometry());
* const material = new pc.StandardMaterial();
*
* const meshInstance = new pc.MeshInstance(mesh, material);
*
* const entity = new pc.Entity();
* entity.addComponent('render', {
* meshInstances: [meshInstance]
* });
*
* // Add the entity to the scene hierarchy
* this.app.scene.root.addChild(entity);
*/
constructor(mesh: Mesh, material: Material, node?: GraphNode);
/**
* Enable shadow casting for this mesh instance. Use this property to enable/disable shadow
* casting without overhead of removing from scene. Note that this property does not add the
* mesh instance to appropriate list of shadow casters on a {@link Layer}, but allows mesh to
* be skipped from shadow casting while it is in the list already. Defaults to false.
*
* @type {boolean}
*/
castShadow: boolean;
/**
* Specifies a bitmask that controls which shadow cascades a mesh instance contributes
* to when rendered with a {@link LIGHTTYPE_DIRECTIONAL} light source.
* This setting is only effective if the {@link castShadow} property is enabled.
* Defaults to {@link SHADOW_CASCADE_ALL}, which means the mesh casts shadows into all available cascades.
*
* @type {number}
*/
shadowCascadeMask: number;
/**
* Controls whether the mesh instance can be culled by frustum culling (see
* {@link CameraComponent#frustumCulling}). Defaults to true.
*
* @type {boolean}
*/
cull: boolean;
/**
* Determines the rendering order of mesh instances. Only used when mesh instances are added to
* a {@link Layer} with {@link Layer#opaqueSortMode} or {@link Layer#transparentSortMode}
* (depending on the material) set to {@link SORTMODE_MANUAL}.
*
* @type {number}
*/
drawOrder: number;
/**
* @type {number}
* @ignore
*/
_drawBucket: number;
/**
* The graph node defining the transform for this instance.
*
* @type {GraphNode}
*/
node: GraphNode;
/**
* Enable rendering for this mesh instance. Use visible property to enable/disable rendering
* without overhead of removing from scene. But note that the mesh instance is still in the
* hierarchy and still in the draw call list.
*
* @type {boolean}
*/
visible: boolean;
/**
* Read this value in {@link Scene.EVENT_POSTCULL} event to determine if the object is actually going
* to be rendered.
*
* @type {boolean}
*/
visibleThisFrame: boolean;
/**
* Negative scale batching support.
*
* @type {number}
* @ignore
*/
flipFacesFactor: number;
/**
* @type {GSplatInstance|null}
* @ignore
*/
gsplatInstance: GSplatInstance | null;
/** @ignore */
id: number;
/**
* Custom function used to customize culling (e.g. for 2D UI elements).
*
* @type {Function|null}
* @ignore
*/
isVisibleFunc: Function | null;
/**
* @type {InstancingData|null}
* @ignore
*/
instancingData: InstancingData | null;
/**
* @type {DrawCommands|null}
* @ignore
*/
indirectData: DrawCommands | null;
/**
* Map of camera to their corresponding indirect draw data. Lazily allocated.
*
* @type {Map<Camera|null, DrawCommands>|null}
* @ignore
*/
drawCommands: Map<Camera | null, DrawCommands> | null;
/**
* Stores mesh metadata used for indirect rendering. Lazily allocated on first access
* via getIndirectMetaData().
*
* @type {Int32Array|null}
* @ignore
*/
meshMetaData: Int32Array | null;
/**
* @type {Record<string, {scopeId: ScopeId|null, data: any, passFlags: number}>}
* @ignore
*/
parameters: Record<string, {
scopeId: ScopeId | null;
data: any;
passFlags: number;
}>;
/**
* True if the mesh instance is pickable by the {@link Picker}. Defaults to true.
*
* @type {boolean}
* @ignore
*/
pick: boolean;
/**
* The stencil parameters for front faces or null if no stencil is enabled.
*
* @type {StencilParameters|null}
* @ignore
*/
stencilFront: StencilParameters | null;
/**
* The stencil parameters for back faces or null if no stencil is enabled.
*
* @type {StencilParameters|null}
* @ignore
*/
stencilBack: StencilParameters | null;
/**
* True if the material of the mesh instance is transparent. Optimization to avoid accessing
* the material. Updated by the material instance itself.
*
* @ignore
*/
transparent: boolean;
/** @private */
private _aabb;
/** @private */
private _aabbVer;
/** @private */
private _aabbMeshVer;
/**
* @type {BoundingBox|null}
* @private
*/
private _customAabb;
/** @private */
private _updateAabb;
/** @private */
private _updateAabbFunc;
/**
* The internal sorting key used by the shadow renderer.
*
* @ignore
*/
_sortKeyShadow: number;
/**
* The internal sorting key used by the forward renderer, in case SORTMODE_MATERIALMESH sorting
* is used.
*
* @private
*/
private _sortKeyForward;
/**
* The internal sorting key used by the forward renderer, in case SORTMODE_BACK2FRONT or
* SORTMODE_FRONT2BACK sorting is used.
*
* @ignore
*/
_sortKeyDynamic: number;
/** @private */
private _layer;
/**
* @type {Material|null}
* @private
*/
private _material;
/**
* @type {SkinInstance|null}
* @private
*/
private _skinInstance;
/**
* @type {MorphInstance|null}
* @private
*/
private _morphInstance;
/** @private */
private _receiveShadow;
/** @private */
private _renderStyle;
/** @private */
private _screenSpace;
/**
* The cache of shaders, indexed by a hash value.
*
* @type {Map<number, ShaderInstance>}
* @private
*/
private _shaderCache;
/**
* 2 byte toggles, 2 bytes light mask; Default value is no toggles and mask = pc.MASK_AFFECT_DYNAMIC
*
* @private
*/
private _shaderDefs;
/**
* @type {CalculateSortDistanceCallback|null}
* @private
*/
private _calculateSortDistance;
_mesh: Mesh;
/**
* Sets the material used by this mesh instance.
*
* @type {Material}
*/
set material(material: Material);
/**
* Gets the material used by this mesh instance.
*
* @type {Material}
*/
get material(): Material;
/**
* Sets the draw bucket for mesh instances. The draw bucket, an integer from 0 to 255 (default
* 127), serves as the primary sort key for mesh rendering. Meshes are sorted by draw bucket,
* then by sort mode. This setting is only effective when mesh instances are added to a
* {@link Layer} with its {@link Layer#opaqueSortMode} or {@link Layer#transparentSortMode}
* (depending on the material) set to {@link SORTMODE_BACK2FRONT}, {@link SORTMODE_FRONT2BACK},
* or {@link SORTMODE_MATERIALMESH}.
*
* Note: When {@link SORTMODE_BACK2FRONT} is used, a descending sort order is used; otherwise,
* an ascending sort order is used.
*
* @type {number}
*/
set drawBucket(bucket: number);
/**
* Gets the draw bucket for mesh instance.
*
* @type {number}
*/
get drawBucket(): number;
/**
* Sets the render style of the mesh instance. Can be:
*
* - {@link RENDERSTYLE_SOLID}
* - {@link RENDERSTYLE_WIREFRAME}
* - {@link RENDERSTYLE_POINTS}
*
* Defaults to {@link RENDERSTYLE_SOLID}.
*
* @type {number}
*/
set renderStyle(renderStyle: number);
/**
* Gets the render style of the mesh instance.
*
* @type {number}
*/
get renderStyle(): number;
/**
* Sets the graphics mesh being instanced.
*
* @type {Mesh}
*/
set mesh(mesh: Mesh);
/**
* Gets the graphics mesh being instanced.
*
* @type {Mesh}
*/
get mesh(): Mesh;
/**
* Sets the world space axis-aligned bounding box for this mesh instance.
*
* @type {BoundingBox}
*/
set aabb(aabb: BoundingBox);
/**
* Gets the world space axis-aligned bounding box for this mesh instance.
*
* @type {BoundingBox}
*/
get aabb(): BoundingBox;
/**
* Clear the internal shader cache.
*
* @ignore
*/
clearShaders(): void;
/**
* Returns the shader instance for the specified shader pass and light hash that is compatible
* with this mesh instance.
*
* @param {number} shaderPass - The shader pass index.
* @param {number} lightHash - The hash value of the lights that are affecting this mesh instance.
* @param {Scene} scene - The scene.
* @param {CameraShaderParams} cameraShaderParams - The camera shader parameters.
* @param {UniformBufferFormat} [viewUniformFormat] - The format of the view uniform buffer.
* @param {BindGroupFormat} [viewBindGroupFormat] - The format of the view bind group.
* @param {any} [sortedLights] - Array of arrays of lights.
* @returns {ShaderInstance} - the shader instance.
* @ignore
*/
getShaderInstance(shaderPass: number, lightHash: number, scene: Scene, cameraShaderParams: CameraShaderParams, viewUniformFormat?: UniformBufferFormat, viewBindGroupFormat?: BindGroupFormat, sortedLights?: any): ShaderInstance;
/**
* @param {number} shaderDefs - The shader definitions to set.
* @private
*/
private _updateShaderDefs;
/**
* Sets the callback to calculate sort distance. In some circumstances mesh instances are
* sorted by a distance calculation to determine their rendering order. Set this callback to
* override the default distance calculation, which gives the dot product of the camera forward
* vector and the vector between the camera position and the center of the mesh instance's
* axis-aligned bounding box. This option can be particularly useful for rendering transparent
* meshes in a better order than the default.
*
* @type {CalculateSortDistanceCallback|null}
*/
set calculateSortDistance(calculateSortDistance: CalculateSortDistanceCallback | null);
/**
* Gets the callback to calculate sort distance.
*
* @type {CalculateSortDistanceCallback|null}
*/
get calculateSortDistance(): CalculateSortDistanceCallback | null;
set receiveShadow(val: boolean);
get receiveShadow(): boolean;
set batching(val: boolean);
get batching(): boolean;
/**
* Sets the skin instance managing skinning of this mesh instance. Set to null if skinning is
* not used.
*
* @type {SkinInstance|null}
*/
set skinInstance(val: SkinInstance | null);
/**
* Gets the skin instance managing skinning of this mesh instance.
*
* @type {SkinInstance|null}
*/
get skinInstance(): SkinInstance | null;
/**
* Sets the morph instance managing morphing of this mesh instance. Set to null if morphing is
* not used.
*
* @type {MorphInstance|null}
*/
set morphInstance(val: MorphInstance | null);
/**
* Gets the morph instance managing morphing of this mesh instance.
*
* @type {MorphInstance|null}
*/
get morphInstance(): MorphInstance | null;
set screenSpace(val: boolean);
get screenSpace(): boolean;
set key(val: number);
get key(): number;
/**
* Sets the mask controlling which {@link LightComponent}s light this mesh instance, which
* {@link CameraComponent} sees it and in which {@link Layer} it is rendered. Defaults to 1.
*
* @type {number}
*/
set mask(val: number);
/**
* Gets the mask controlling which {@link LightComponent}s light this mesh instance, which
* {@link CameraComponent} sees it and in which {@link Layer} it is rendered.
*
* @type {number}
*/
get mask(): number;
/**
* Sets the number of instances when using hardware instancing to render the mesh.
*
* @type {number}
*/
set instancingCount(value: number);
/**
* Gets the number of instances when using hardware instancing to render the mesh.
*
* @type {number}
*/
get instancingCount(): number;
destroy(): void;
destroyDrawCommands(): void;
/**
* Test if meshInstance is visible by camera. It requires the frustum of the camera to be up to
* date, which forward-renderer takes care of. This function should not be called elsewhere.
*
* @param {Camera} camera - The camera to test visibility against.
* @returns {boolean} - True if the mesh instance is visible by the camera, false otherwise.
* @ignore
*/
_isVisible(camera: Camera): boolean;
updateKey(): void;
/**
* Sets up {@link MeshInstance} to be rendered using Hardware Instancing.
* Note that {@link instancingCount} is automatically set to the number of vertices of the
* vertex buffer when it is provided.
*
* @param {VertexBuffer|null} vertexBuffer - Vertex buffer to hold per-instance vertex data
* (usually world matrices). Pass null to turn off hardware instancing.
* @param {boolean} cull - Whether to perform frustum culling on this instance. If true, the whole
* instance will be culled by the camera frustum. This often involves setting
* {@link RenderComponent#customAabb} containing all instances. Defaults to false, which means
* the whole instance is always rendered.
*/
setInstancing(vertexBuffer: VertexBuffer | null, cull?: boolean): void;
/**
* Sets the {@link MeshInstance} to be rendered using indirect rendering, where the GPU,
* typically using a Compute shader, stores draw call parameters in a buffer.
* Note that this is only supported on WebGPU, and ignored on other platforms.
*
* @param {CameraComponent|null} camera - Camera component to set indirect data for, or
* null if the indirect slot should be used for all cameras.
* @param {number} slot - Slot in the buffer to set the draw call parameters. Allocate a slot
* in the buffer by calling {@link GraphicsDevice#getIndirectDrawSlot}. Pass -1 to disable
* indirect rendering for the specified camera (or the shared entry when camera is null).
* @param {number} [count] - Optional number of consecutive slots to use. Defaults to 1.
*/
setIndirect(camera: CameraComponent | null, slot: number, count?: number): void;
/**
* Sets the {@link MeshInstance} to be rendered using multi-draw, where multiple sub-draws are
* executed with a single draw call.
*
* @param {CameraComponent|null} camera - Camera component to bind commands to, or null to share
* across all cameras.
* @param {number} [maxCount] - Maximum number of sub-draws to allocate. Defaults to 1. Pass 0
* to disable multi-draw for the specified camera (or the shared entry when camera is null).
* @returns {DrawCommands|undefined} The commands container to populate with sub-draw commands.
*/
setMultiDraw(camera: CameraComponent | null, maxCount?: number): DrawCommands | undefined;
_deleteDrawCommandsKey(key: any): void;
/**
* Retrieves the draw commands for a specific camera, or the default commands when none are
* bound to that camera.
*
* @param {Camera} camera - The camera to retrieve commands for.
* @returns {DrawCommands|undefined} - The draw commands, or undefined.
* @ignore
*/
getDrawCommands(camera: Camera): DrawCommands | undefined;
/**
* Retrieves the mesh metadata needed for indirect rendering.
*
* @returns {Int32Array} - A typed array with 4 elements representing the mesh metadata, which
* is typically needed when generating indirect draw call parameters using Compute shader. These
* can be provided to the Compute shader using vec4i uniform. The values are based on
* {@link Mesh#primitive}, stored in this order: [count, base, baseVertex, 0]. The last value is
* always zero and is reserved for future use.
*/
getIndirectMetaData(): Int32Array;
ensureMaterial(device: any): void;
clearParameters(): void;
getParameters(): Record<string, {
scopeId: ScopeId | null;
data: any;
passFlags: number;
}>;
/**
* Retrieves the specified shader parameter from a mesh instance.
*
* @param {string} name - The name of the parameter to query.
* @returns {object} The named parameter.
*/
getParameter(name: string): object;
/**
* Sets a shader parameter on a mesh instance. Note that this parameter will take precedence
* over parameter of the same name if set on Material this mesh instance uses for rendering.
*
* @param {string} name - The name of the parameter to set.
* @param {number|number[]|Texture|Float32Array} data - The value for the specified parameter.
* @param {number} [passFlags] - Mask describing which passes the material should be included
* in. Defaults to 0xFFFFFFFF (all passes).
*/
setParameter(name: string, data: number | number[] | Texture | Float32Array, passFlags?: number): void;
/**
* A wrapper over settings parameter specifically for realtime baked lightmaps. This handles
* reference counting of lightmaps and releases them when no longer referenced.
*
* @param {string} name - The name of the parameter to set.
* @param {Texture|null} texture - The lightmap texture to set.
* @ignore
*/
setRealtimeLightmap(name: string, texture: Texture | null): void;
/**
* Deletes a shader parameter on a mesh instance.
*
* @param {string} name - The name of the parameter to delete.
*/
deleteParameter(name: string): void;
/**
* Used to apply parameters from this mesh instance into scope of uniforms, called internally
* by forward-renderer.
*
* @param {GraphicsDevice} device - The graphics device.
* @param {number} passFlag - The pass flag for the current render pass.
* @ignore
*/
setParameters(device: GraphicsDevice, passFlag: number): void;
/**
* @param {boolean} value - True to enable lightmapped rendering, false to disable.
* @ignore
*/
setLightmapped(value: boolean): void;
/**
* @param {BoundingBox|null} aabb - The custom axis-aligned bounding box or null to reset to
* the mesh's bounding box.
* @ignore
*/
setCustomAabb(aabb: BoundingBox | null): void;
/** @private */
private _setupSkinUpdate;
}
import type { Vec3 } from '../core/math/vec3.js';
import { GraphNode } from './graph-node.js';
import type { GSplatInstance } from './gsplat/gsplat-instance.js';
/**
* Internal data structure used to store data used by hardware instancing.
*
* @ignore
*/
declare class InstancingData {
/**
* @param {number} numObjects - The number of objects instanced.
*/
constructor(numObjects: number);
/** @type {VertexBuffer|null} */
vertexBuffer: VertexBuffer | null;
/**
* True if the vertex buffer is destroyed when the mesh instance is destroyed.
*
* @type {boolean}
*/
_destroyVertexBuffer: boolean;
count: number;
destroy(): void;
}
import { DrawCommands } from '../platform/graphics/draw-commands.js';
import type { Camera } from './camera.js';
import type { ScopeId } from '../platform/graphics/scope-id.js';
import type { StencilParameters } from '../platform/graphics/stencil-parameters.js';
import type { Mesh } from './mesh.js';
import type { Material } from './materials/material.js';
import { BoundingBox } from '../core/shape/bounding-box.js';
import type { Scene } from './scene.js';
import type { CameraShaderParams } from './camera-shader-params.js';
import type { UniformBufferFormat } from '../platform/graphics/uniform-buffer-format.js';
import type { BindGroupFormat } from '../platform/graphics/bind-group-format.js';
/**
* Internal helper class for storing the shader and related mesh bind group in the shader cache.
*
* @ignore
*/
declare class ShaderInstance {
/**
* A shader.
*
* @type {Shader|undefined}
*/
shader: Shader | undefined;
/**
* A bind group storing mesh textures / samplers for the shader. but not the uniform buffer.
*
* @type {BindGroup|null}
*/
bindGroup: BindGroup | null;
/**
* A uniform buffer storing mesh uniforms for the shader.
*
* @type {UniformBuffer|null}
*/
uniformBuffer: UniformBuffer | null;
/**
* The full array of hashes used to lookup the pipeline, used in case of hash collision.
*
* @type {Uint32Array}
*/
hashes: Uint32Array;
/**
* Returns the mesh bind group for the shader.
*
* @param {GraphicsDevice} device - The graphics device.
* @returns {BindGroup} - The mesh bind group.
*/
getBindGroup(device: GraphicsDevice): BindGroup;
/**
* Returns the uniform buffer for the shader.
*
* @param {GraphicsDevice} device - The graphics device.
* @returns {UniformBuffer} - The uniform buffer.
*/
getUniformBuffer(device: GraphicsDevice): UniformBuffer;
destroy(): void;
}
import type { SkinInstance } from './skin-instance.js';
import type { MorphInstance } from './morph-instance.js';
import type { VertexBuffer } from '../platform/graphics/vertex-buffer.js';
import type { CameraComponent } from '../framework/components/camera/component.js';
import type { Texture } from '../platform/graphics/texture.js';
import type { GraphicsDevice } from '../platform/graphics/graphics-device.js';
import type { Shader } from '../platform/graphics/shader.js';
import { BindGroup } from '../platform/graphics/bind-group.js';
import { UniformBuffer } from '../platform/graphics/uniform-buffer.js';
export {};