123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- import { Material } from "../Materials/material.js";
- import { Tags } from "../Misc/tags.js";
- import { RegisterClass } from "../Misc/typeStore.js";
- /**
- * A multi-material is used to apply different materials to different parts of the same object without the need of
- * separate meshes. This can be use to improve performances.
- * @see https://doc.babylonjs.com/features/featuresDeepDive/materials/using/multiMaterials
- */
- export class MultiMaterial extends Material {
- /**
- * Gets or Sets the list of Materials used within the multi material.
- * They need to be ordered according to the submeshes order in the associated mesh
- */
- get subMaterials() {
- return this._subMaterials;
- }
- set subMaterials(value) {
- this._subMaterials = value;
- this._hookArray(value);
- }
- /**
- * Function used to align with Node.getChildren()
- * @returns the list of Materials used within the multi material
- */
- getChildren() {
- return this.subMaterials;
- }
- /**
- * Instantiates a new Multi Material
- * A multi-material is used to apply different materials to different parts of the same object without the need of
- * separate meshes. This can be use to improve performances.
- * @see https://doc.babylonjs.com/features/featuresDeepDive/materials/using/multiMaterials
- * @param name Define the name in the scene
- * @param scene Define the scene the material belongs to
- */
- constructor(name, scene) {
- super(name, scene, true);
- /** @internal */
- this._waitingSubMaterialsUniqueIds = [];
- this.getScene().addMultiMaterial(this);
- this.subMaterials = [];
- this._storeEffectOnSubMeshes = true; // multimaterial is considered like a push material
- }
- _hookArray(array) {
- const oldPush = array.push;
- array.push = (...items) => {
- const result = oldPush.apply(array, items);
- this._markAllSubMeshesAsTexturesDirty();
- return result;
- };
- const oldSplice = array.splice;
- array.splice = (index, deleteCount) => {
- const deleted = oldSplice.apply(array, [index, deleteCount]);
- this._markAllSubMeshesAsTexturesDirty();
- return deleted;
- };
- }
- /**
- * Get one of the submaterial by its index in the submaterials array
- * @param index The index to look the sub material at
- * @returns The Material if the index has been defined
- */
- getSubMaterial(index) {
- if (index < 0 || index >= this.subMaterials.length) {
- return this.getScene().defaultMaterial;
- }
- return this.subMaterials[index];
- }
- /**
- * Get the list of active textures for the whole sub materials list.
- * @returns All the textures that will be used during the rendering
- */
- getActiveTextures() {
- return super.getActiveTextures().concat(...this.subMaterials.map((subMaterial) => {
- if (subMaterial) {
- return subMaterial.getActiveTextures();
- }
- else {
- return [];
- }
- }));
- }
- /**
- * Specifies if any sub-materials of this multi-material use a given texture.
- * @param texture Defines the texture to check against this multi-material's sub-materials.
- * @returns A boolean specifying if any sub-material of this multi-material uses the texture.
- */
- hasTexture(texture) {
- if (super.hasTexture(texture)) {
- return true;
- }
- for (let i = 0; i < this.subMaterials.length; i++) {
- if (this.subMaterials[i]?.hasTexture(texture)) {
- return true;
- }
- }
- return false;
- }
- /**
- * Gets the current class name of the material e.g. "MultiMaterial"
- * Mainly use in serialization.
- * @returns the class name
- */
- getClassName() {
- return "MultiMaterial";
- }
- /**
- * Checks if the material is ready to render the requested sub mesh
- * @param mesh Define the mesh the submesh belongs to
- * @param subMesh Define the sub mesh to look readiness for
- * @param useInstances Define whether or not the material is used with instances
- * @returns true if ready, otherwise false
- */
- isReadyForSubMesh(mesh, subMesh, useInstances) {
- for (let index = 0; index < this.subMaterials.length; index++) {
- const subMaterial = this.subMaterials[index];
- if (subMaterial) {
- if (subMaterial._storeEffectOnSubMeshes) {
- if (!subMaterial.isReadyForSubMesh(mesh, subMesh, useInstances)) {
- return false;
- }
- continue;
- }
- if (!subMaterial.isReady(mesh)) {
- return false;
- }
- }
- }
- return true;
- }
- /**
- * Clones the current material and its related sub materials
- * @param name Define the name of the newly cloned material
- * @param cloneChildren Define if submaterial will be cloned or shared with the parent instance
- * @returns the cloned material
- */
- clone(name, cloneChildren) {
- const newMultiMaterial = new MultiMaterial(name, this.getScene());
- for (let index = 0; index < this.subMaterials.length; index++) {
- let subMaterial = null;
- const current = this.subMaterials[index];
- if (cloneChildren && current) {
- subMaterial = current.clone(name + "-" + current.name);
- }
- else {
- subMaterial = this.subMaterials[index];
- }
- newMultiMaterial.subMaterials.push(subMaterial);
- }
- return newMultiMaterial;
- }
- /**
- * Serializes the materials into a JSON representation.
- * @returns the JSON representation
- */
- serialize() {
- const serializationObject = {};
- serializationObject.name = this.name;
- serializationObject.id = this.id;
- serializationObject.uniqueId = this.uniqueId;
- if (Tags) {
- serializationObject.tags = Tags.GetTags(this);
- }
- serializationObject.materialsUniqueIds = [];
- serializationObject.materials = [];
- for (let matIndex = 0; matIndex < this.subMaterials.length; matIndex++) {
- const subMat = this.subMaterials[matIndex];
- if (subMat) {
- serializationObject.materialsUniqueIds.push(subMat.uniqueId);
- serializationObject.materials.push(subMat.id);
- }
- else {
- serializationObject.materialsUniqueIds.push(null);
- serializationObject.materials.push(null);
- }
- }
- return serializationObject;
- }
- /**
- * Dispose the material and release its associated resources
- * @param forceDisposeEffect Define if we want to force disposing the associated effect (if false the shader is not released and could be reuse later on)
- * @param forceDisposeTextures Define if we want to force disposing the associated textures (if false, they will not be disposed and can still be use elsewhere in the app)
- * @param forceDisposeChildren Define if we want to force disposing the associated submaterials (if false, they will not be disposed and can still be use elsewhere in the app)
- */
- dispose(forceDisposeEffect, forceDisposeTextures, forceDisposeChildren) {
- const scene = this.getScene();
- if (!scene) {
- return;
- }
- if (forceDisposeChildren) {
- for (let index = 0; index < this.subMaterials.length; index++) {
- const subMaterial = this.subMaterials[index];
- if (subMaterial) {
- subMaterial.dispose(forceDisposeEffect, forceDisposeTextures);
- }
- }
- }
- const index = scene.multiMaterials.indexOf(this);
- if (index >= 0) {
- scene.multiMaterials.splice(index, 1);
- }
- super.dispose(forceDisposeEffect, forceDisposeTextures);
- }
- /**
- * Creates a MultiMaterial from parsed MultiMaterial data.
- * @param parsedMultiMaterial defines parsed MultiMaterial data.
- * @param scene defines the hosting scene
- * @returns a new MultiMaterial
- */
- static ParseMultiMaterial(parsedMultiMaterial, scene) {
- const multiMaterial = new MultiMaterial(parsedMultiMaterial.name, scene);
- multiMaterial.id = parsedMultiMaterial.id;
- multiMaterial._loadedUniqueId = parsedMultiMaterial.uniqueId;
- if (Tags) {
- Tags.AddTagsTo(multiMaterial, parsedMultiMaterial.tags);
- }
- if (parsedMultiMaterial.materialsUniqueIds) {
- multiMaterial._waitingSubMaterialsUniqueIds = parsedMultiMaterial.materialsUniqueIds;
- }
- else {
- parsedMultiMaterial.materials.forEach((subMatId) => multiMaterial.subMaterials.push(scene.getLastMaterialById(subMatId)));
- }
- return multiMaterial;
- }
- }
- RegisterClass("BABYLON.MultiMaterial", MultiMaterial);
- //# sourceMappingURL=multiMaterial.js.map
|