UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

726 lines (725 loc) 26.4 kB
/** * 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 {};