UNPKG

@babylonjs/viewer

Version:

The Babylon Viewer aims to simplify a specific but common Babylon.js use case: loading, viewing, and interacting with a 3D model.

897 lines (892 loc) 47.6 kB
import { S as ShaderStore, bH as ProcessIncludes, l as __runInitializers, C as Constants, o as SerializationHelper, q as __esDecorate, s as serialize, z as __classPrivateFieldGet, D as __classPrivateFieldSet, F as Material, as as MaterialFlags, $ as PrepareDefinesForMergedUV, ak as BindTextureMatrix, aw as MaterialDefines, J as serializeAsTexture, H as expandToProperty } from './index-MZPybX0H.esm.js'; /** This file must only contain pure code and pure imports */ const RxOption = /*#__PURE__*/ new RegExp("^([gimus]+)!"); /** * Class that manages the plugins of a material * @since 5.0 */ class MaterialPluginManager { /** * Creates a new instance of the plugin manager * @param material material that this manager will manage the plugins for */ constructor(material) { /** @internal */ this._plugins = []; this._activePlugins = []; this._activePluginsForExtraEvents = []; this._material = material; this._scene = material.getScene(); this._engine = this._scene.getEngine(); } /** * @internal */ _addPlugin(plugin) { for (let i = 0; i < this._plugins.length; ++i) { if (this._plugins[i].name === plugin.name) { return false; } } if (this._material._uniformBufferLayoutBuilt) { this._material.resetDrawCache(); this._material._createUniformBuffer(); } if (!plugin.isCompatible(this._material.shaderLanguage)) { // eslint-disable-next-line no-throw-literal throw `The plugin "${plugin.name}" can't be added to the material "${this._material.name}" because the plugin is not compatible with the shader language of the material.`; } const pluginClassName = plugin.getClassName(); if (!MaterialPluginManager._MaterialPluginClassToMainDefine[pluginClassName]) { MaterialPluginManager._MaterialPluginClassToMainDefine[pluginClassName] = "MATERIALPLUGIN_" + ++MaterialPluginManager._MaterialPluginCounter; } this._material._callbackPluginEventGeneric = (id, info) => this._handlePluginEvent(id, info); this._plugins.push(plugin); this._plugins.sort((a, b) => a.priority - b.priority); this._codeInjectionPoints = {}; const defineNamesFromPlugins = {}; defineNamesFromPlugins[MaterialPluginManager._MaterialPluginClassToMainDefine[pluginClassName]] = { type: "boolean", default: true, }; for (const plugin of this._plugins) { plugin.collectDefines(defineNamesFromPlugins); this._collectPointNames("vertex", plugin.getCustomCode("vertex", this._material.shaderLanguage)); this._collectPointNames("fragment", plugin.getCustomCode("fragment", this._material.shaderLanguage)); } this._defineNamesFromPlugins = defineNamesFromPlugins; return true; } /** * @internal */ _activatePlugin(plugin) { if (this._activePlugins.indexOf(plugin) === -1) { this._activePlugins.push(plugin); this._activePlugins.sort((a, b) => a.priority - b.priority); this._material._callbackPluginEventIsReadyForSubMesh = this._handlePluginEventIsReadyForSubMesh.bind(this); this._material._callbackPluginEventPrepareDefinesBeforeAttributes = this._handlePluginEventPrepareDefinesBeforeAttributes.bind(this); this._material._callbackPluginEventPrepareDefines = this._handlePluginEventPrepareDefines.bind(this); this._material._callbackPluginEventBindForSubMesh = this._handlePluginEventBindForSubMesh.bind(this); if (plugin.registerForExtraEvents) { this._activePluginsForExtraEvents.push(plugin); this._activePluginsForExtraEvents.sort((a, b) => a.priority - b.priority); this._material._callbackPluginEventHasRenderTargetTextures = this._handlePluginEventHasRenderTargetTextures.bind(this); this._material._callbackPluginEventFillRenderTargetTextures = this._handlePluginEventFillRenderTargetTextures.bind(this); this._material._callbackPluginEventHardBindForSubMesh = this._handlePluginEventHardBindForSubMesh.bind(this); } } } /** * Gets a plugin from the list of plugins managed by this manager * @param name name of the plugin * @returns the plugin if found, else null */ getPlugin(name) { for (let i = 0; i < this._plugins.length; ++i) { if (this._plugins[i].name === name) { return this._plugins[i]; } } return null; } _handlePluginEventIsReadyForSubMesh(eventData) { let isReady = true; for (const plugin of this._activePlugins) { isReady = isReady && plugin.isReadyForSubMesh(eventData.defines, this._scene, this._engine, eventData.subMesh); } eventData.isReadyForSubMesh = isReady; } _handlePluginEventPrepareDefinesBeforeAttributes(eventData) { for (const plugin of this._activePlugins) { plugin.prepareDefinesBeforeAttributes(eventData.defines, this._scene, eventData.mesh); } } _handlePluginEventPrepareDefines(eventData) { for (const plugin of this._activePlugins) { plugin.prepareDefines(eventData.defines, this._scene, eventData.mesh); } } _handlePluginEventHardBindForSubMesh(eventData) { for (const plugin of this._activePluginsForExtraEvents) { plugin.hardBindForSubMesh(this._material._uniformBuffer, this._scene, this._engine, eventData.subMesh); } } _handlePluginEventBindForSubMesh(eventData) { for (const plugin of this._activePlugins) { plugin.bindForSubMesh(this._material._uniformBuffer, this._scene, this._engine, eventData.subMesh); } } _handlePluginEventHasRenderTargetTextures(eventData) { let hasRenderTargetTextures = false; for (const plugin of this._activePluginsForExtraEvents) { hasRenderTargetTextures = plugin.hasRenderTargetTextures(); if (hasRenderTargetTextures) { break; } } eventData.hasRenderTargetTextures = hasRenderTargetTextures; } _handlePluginEventFillRenderTargetTextures(eventData) { for (const plugin of this._activePluginsForExtraEvents) { plugin.fillRenderTargetTextures(eventData.renderTargets); } } _handlePluginEvent(id, info) { switch (id) { case 512 /* MaterialPluginEvent.GetActiveTextures */: { const eventData = info; for (const plugin of this._activePlugins) { plugin.getActiveTextures(eventData.activeTextures); } break; } case 256 /* MaterialPluginEvent.GetAnimatables */: { const eventData = info; for (const plugin of this._activePlugins) { plugin.getAnimatables(eventData.animatables); } break; } case 1024 /* MaterialPluginEvent.HasTexture */: { const eventData = info; let hasTexture = false; for (const plugin of this._activePlugins) { hasTexture = plugin.hasTexture(eventData.texture); if (hasTexture) { break; } } eventData.hasTexture = hasTexture; break; } case 2 /* MaterialPluginEvent.Disposed */: { const eventData = info; for (const plugin of this._plugins) { plugin.dispose(eventData.forceDisposeTextures); } break; } case 4 /* MaterialPluginEvent.GetDefineNames */: { const eventData = info; eventData.defineNames = this._defineNamesFromPlugins; break; } case 128 /* MaterialPluginEvent.PrepareEffect */: { const eventData = info; for (const plugin of this._activePlugins) { eventData.fallbackRank = plugin.addFallbacks(eventData.defines, eventData.fallbacks, eventData.fallbackRank); plugin.getAttributes(eventData.attributes, this._scene, eventData.mesh); } if (this._uniformList.length > 0) { eventData.uniforms.push(...this._uniformList); } if (this._samplerList.length > 0) { eventData.samplers.push(...this._samplerList); } if (this._uboList.length > 0) { eventData.uniformBuffersNames.push(...this._uboList); } eventData.customCode = this._injectCustomCode(eventData, eventData.customCode); break; } case 8 /* MaterialPluginEvent.PrepareUniformBuffer */: { const eventData = info; this._uboDeclaration = ""; this._vertexDeclaration = ""; this._fragmentDeclaration = ""; this._uniformList = []; this._samplerList = []; this._uboList = []; const isWebGPU = this._material.shaderLanguage === 1 /* ShaderLanguage.WGSL */; for (const plugin of this._plugins) { const uniforms = plugin.getUniforms(this._material.shaderLanguage); if (uniforms) { if (uniforms.ubo) { for (const uniform of uniforms.ubo) { if (uniform.size && uniform.type) { const arraySize = uniform.arraySize ?? 0; eventData.ubo.addUniform(uniform.name, uniform.size, arraySize); if (isWebGPU) { let type; switch (uniform.type) { case "mat4": type = "mat4x4f"; break; case "float": type = "f32"; break; default: type = `${uniform.type}f`; break; } if (arraySize > 0) { this._uboDeclaration += `uniform ${uniform.name}: array<${type}, ${arraySize}>;\n`; } else { this._uboDeclaration += `uniform ${uniform.name}: ${type};\n`; } } else { this._uboDeclaration += `${uniform.type} ${uniform.name}${arraySize > 0 ? `[${arraySize}]` : ""};\n`; } } this._uniformList.push(uniform.name); } } if (uniforms.vertex) { this._vertexDeclaration += uniforms.vertex + "\n"; } if (uniforms.fragment) { this._fragmentDeclaration += uniforms.fragment + "\n"; } // These are uniforms which are used by the shader but not updated by the plugin directly. // They still need to be present in the _uniformList so the Effect can determine their locations. if (uniforms.externalUniforms) { this._uniformList.push(...uniforms.externalUniforms); } } plugin.getSamplers(this._samplerList); plugin.getUniformBuffersNames(this._uboList); } break; } } } _collectPointNames(shaderType, customCode) { if (!customCode) { return; } for (const pointName in customCode) { if (!this._codeInjectionPoints[shaderType]) { this._codeInjectionPoints[shaderType] = {}; } this._codeInjectionPoints[shaderType][pointName] = true; } } _injectCustomCode(eventData, existingCallback) { return (shaderType, code) => { if (existingCallback) { code = existingCallback(shaderType, code); } if (this._uboDeclaration) { code = code.replace("#define ADDITIONAL_UBO_DECLARATION", this._uboDeclaration); } if (this._vertexDeclaration) { code = code.replace("#define ADDITIONAL_VERTEX_DECLARATION", this._vertexDeclaration); } if (this._fragmentDeclaration) { code = code.replace("#define ADDITIONAL_FRAGMENT_DECLARATION", this._fragmentDeclaration); } const points = this._codeInjectionPoints?.[shaderType]; if (!points) { return code; } let processorOptions = null; for (let pointName in points) { let injectedCode = ""; for (const plugin of this._activePlugins) { const shaderLanguage = this._material.shaderLanguage; let customCode = plugin.getCustomCode(shaderType, shaderLanguage)?.[pointName]; if (!customCode) { continue; } if (plugin.resolveIncludes) { if (processorOptions === null) { processorOptions = { defines: [], // not used by _ProcessIncludes indexParameters: eventData.indexParameters, isFragment: false, shouldUseHighPrecisionShader: this._engine._shouldUseHighPrecisionShader, processor: undefined, // not used by _ProcessIncludes supportsUniformBuffers: this._engine.supportsUniformBuffers, shadersRepository: ShaderStore.GetShadersRepository(shaderLanguage), includesShadersStore: ShaderStore.GetIncludesShadersStore(shaderLanguage), version: undefined, // not used by _ProcessIncludes platformName: this._engine.shaderPlatformName, processingContext: undefined, // not used by _ProcessIncludes isNDCHalfZRange: this._engine.isNDCHalfZRange, useReverseDepthBuffer: this._engine.useReverseDepthBuffer, processCodeAfterIncludes: undefined, // not used by _ProcessIncludes }; } processorOptions.isFragment = shaderType === "fragment"; ProcessIncludes(customCode, processorOptions, (code) => (customCode = code)); } injectedCode += customCode + "\n"; } if (injectedCode.length > 0) { if (pointName.charAt(0) === "!") { // pointName is a regular expression pointName = pointName.substring(1); let regexFlags = "g"; if (pointName.charAt(0) === "!") { // no flags regexFlags = ""; pointName = pointName.substring(1); } else { // get the flag(s) const matchOption = RxOption.exec(pointName); if (matchOption && matchOption.length >= 2) { regexFlags = matchOption[1]; pointName = pointName.substring(regexFlags.length + 1); } } if (regexFlags.indexOf("g") < 0) { // we force the "g" flag so that the regexp object is stateful! regexFlags += "g"; } const rx = new RegExp(pointName, regexFlags); let match = rx.exec(code); while (match !== null) { const { index } = match; const newCode = ReplaceRegExpSubstitutions(injectedCode, match); code = code.substring(0, index) + newCode + code.substring(index + match[0].length); rx.lastIndex = index + newCode.length; match = rx.exec(code); } } else { const fullPointName = "#define " + pointName; code = code.replace(fullPointName, "\n" + injectedCode + "\n" + fullPointName); } } } return code; }; } } /** Map a plugin class name to a #define name (used in the vertex/fragment shaders as a marker of the plugin usage) */ MaterialPluginManager._MaterialPluginClassToMainDefine = {}; MaterialPluginManager._MaterialPluginCounter = 0; /** * Replace regex substitution patterns (e.g. $1, $2, etc.) * @param value The replacement string * @param match The regex match array * @returns Value having $X substitutions replaced with the equivalent `match[X]` */ function ReplaceRegExpSubstitutions(value, match) { return value.replace(/\$(\d+)/g, (group0, group1) => { const index = Number(group1); return index < match.length ? match[index] : ""; }); } /** This file must only contain pure code and pure imports */ /** * Base class for material plugins. * @since 5.0 */ let MaterialPluginBase = (() => { var _a; let _name_decorators; let _name_initializers = []; let _name_extraInitializers = []; let _priority_decorators; let _priority_initializers = []; let _priority_extraInitializers = []; let _resolveIncludes_decorators; let _resolveIncludes_initializers = []; let _resolveIncludes_extraInitializers = []; let _registerForExtraEvents_decorators; let _registerForExtraEvents_initializers = []; let _registerForExtraEvents_extraInitializers = []; return _a = class MaterialPluginBase { /** * Gets a boolean indicating that the plugin is compatible with a given shader language. * @param shaderLanguage The shader language to use. * @returns true if the plugin is compatible with the shader language */ isCompatible(shaderLanguage) { switch (shaderLanguage) { case 0 /* ShaderLanguage.GLSL */: return true; default: return false; } } _enable(enable) { if (enable) { this._pluginManager._activatePlugin(this); } } /** * Creates a new material plugin * @param material parent material of the plugin * @param name name of the plugin * @param priority priority of the plugin * @param defines list of defines used by the plugin. The value of the property is the default value for this property * @param addToPluginList true to add the plugin to the list of plugins managed by the material plugin manager of the material (default: true) * @param enable true to enable the plugin (it is handy if the plugin does not handle properties to switch its current activation) * @param resolveIncludes Indicates that any #include directive in the plugin code must be replaced by the corresponding code (default: false) */ constructor(material, name, priority, defines, addToPluginList = true, enable = false, resolveIncludes = false) { /** * Defines the name of the plugin */ this.name = __runInitializers(this, _name_initializers, void 0); /** * Defines the priority of the plugin. Lower numbers run first. */ this.priority = (__runInitializers(this, _name_extraInitializers), __runInitializers(this, _priority_initializers, 500)); /** * Indicates that any #include directive in the plugin code must be replaced by the corresponding code. */ this.resolveIncludes = (__runInitializers(this, _priority_extraInitializers), __runInitializers(this, _resolveIncludes_initializers, false)); /** * Indicates that this plugin should be notified for the extra events (HasRenderTargetTextures / FillRenderTargetTextures / HardBindForSubMesh) */ this.registerForExtraEvents = (__runInitializers(this, _resolveIncludes_extraInitializers), __runInitializers(this, _registerForExtraEvents_initializers, false)); /** * Specifies if the material plugin should be serialized, `true` to skip serialization */ this.doNotSerialize = (__runInitializers(this, _registerForExtraEvents_extraInitializers), false); this._material = material; this.name = name; this.priority = priority; this.resolveIncludes = resolveIncludes; if (!material.pluginManager) { material.pluginManager = new MaterialPluginManager(material); material.onDisposeObservable.add(() => { material.pluginManager = undefined; }); } this._pluginDefineNames = defines; this._pluginManager = material.pluginManager; if (addToPluginList) { this._pluginManager._addPlugin(this); } if (enable) { this._enable(true); } this.markAllDefinesAsDirty = material._dirtyCallbacks[Constants.MATERIAL_AllDirtyFlag]; } /** * Gets the current class name useful for serialization or dynamic coding. * @returns The class name. */ getClassName() { return "MaterialPluginBase"; } /** * Specifies that the submesh is ready to be used. * @param _defines the list of "defines" to update. * @param _scene defines the scene the material belongs to. * @param _engine the engine this scene belongs to. * @param _subMesh the submesh to check for readiness * @returns - boolean indicating that the submesh is ready or not. */ isReadyForSubMesh(_defines, _scene, _engine, _subMesh) { return true; } /** * Binds the material data (this function is called even if mustRebind() returns false) * @param _uniformBuffer defines the Uniform buffer to fill in. * @param _scene defines the scene the material belongs to. * @param _engine defines the engine the material belongs to. * @param _subMesh the submesh to bind data for */ hardBindForSubMesh(_uniformBuffer, _scene, _engine, _subMesh) { } /** * Binds the material data. * @param _uniformBuffer defines the Uniform buffer to fill in. * @param _scene defines the scene the material belongs to. * @param _engine the engine this scene belongs to. * @param _subMesh the submesh to bind data for */ bindForSubMesh(_uniformBuffer, _scene, _engine, _subMesh) { } /** * Disposes the resources of the material. * @param _forceDisposeTextures - Forces the disposal of all textures. */ dispose(_forceDisposeTextures) { } /** * Returns a list of custom shader code fragments to customize the shader. * @param _shaderType "vertex" or "fragment" * @param _shaderLanguage The shader language to use. * @returns null if no code to be added, or a list of pointName =\> code. * Note that `pointName` can also be a regular expression if it starts with a `!`. * In that case, the string found by the regular expression (if any) will be * replaced by the code provided. */ getCustomCode(_shaderType, _shaderLanguage = 0 /* ShaderLanguage.GLSL */) { return null; } /** * Collects all defines. * @param defines The object to append to. */ collectDefines(defines) { if (!this._pluginDefineNames) { return; } for (const key of Object.keys(this._pluginDefineNames)) { if (key[0] === "_") { continue; } const type = typeof this._pluginDefineNames[key]; defines[key] = { type: type === "number" ? "number" : type === "string" ? "string" : type === "boolean" ? "boolean" : "object", default: this._pluginDefineNames[key], }; } } /** * Sets the defines for the next rendering. Called before PrepareDefinesForAttributes is called. * @param _defines the list of "defines" to update. * @param _scene defines the scene to the material belongs to. * @param _mesh the mesh being rendered */ prepareDefinesBeforeAttributes(_defines, _scene, _mesh) { } /** * Sets the defines for the next rendering * @param _defines the list of "defines" to update. * @param _scene defines the scene to the material belongs to. * @param _mesh the mesh being rendered */ prepareDefines(_defines, _scene, _mesh) { } /** * Checks to see if a texture is used in the material. * @param _texture - Base texture to use. * @returns - Boolean specifying if a texture is used in the material. */ hasTexture(_texture) { return false; } /** * Gets a boolean indicating that current material needs to register RTT * @returns true if this uses a render target otherwise false. */ hasRenderTargetTextures() { return false; } /** * Fills the list of render target textures. * @param _renderTargets the list of render targets to update */ fillRenderTargetTextures(_renderTargets) { } /** * Returns an array of the actively used textures. * @param _activeTextures Array of BaseTextures */ getActiveTextures(_activeTextures) { } /** * Returns the animatable textures. * @param _animatables Array of animatable textures. */ getAnimatables(_animatables) { } /** * Add fallbacks to the effect fallbacks list. * @param defines defines the Base texture to use. * @param fallbacks defines the current fallback list. * @param currentRank defines the current fallback rank. * @returns the new fallback rank. */ addFallbacks(defines, fallbacks, currentRank) { return currentRank; } /** * Gets the samplers used by the plugin. * @param _samplers list that the sampler names should be added to. */ getSamplers(_samplers) { } /** * Gets the attributes used by the plugin. * @param _attributes list that the attribute names should be added to. * @param _scene the scene that the material belongs to. * @param _mesh the mesh being rendered. */ getAttributes(_attributes, _scene, _mesh) { } /** * Gets the uniform buffers names added by the plugin. * @param _ubos list that the ubo names should be added to. */ getUniformBuffersNames(_ubos) { } /** * Gets the description of the uniforms to add to the ubo (if engine supports ubos) or to inject directly in the vertex/fragment shaders (if engine does not support ubos) * @param _shaderLanguage The shader language to use. * @returns the description of the uniforms */ getUniforms(_shaderLanguage = 0 /* ShaderLanguage.GLSL */) { return {}; } /** * Makes a duplicate of the current configuration into another one. * @param plugin define the config where to copy the info */ copyTo(plugin) { SerializationHelper.Clone(() => plugin, this); } /** * Serializes this plugin configuration. * @returns - An object with the serialized config. */ serialize() { return SerializationHelper.Serialize(this); } /** * Parses a plugin configuration from a serialized object. * @param source - Serialized object. * @param scene Defines the scene we are parsing for * @param rootUrl Defines the rootUrl to load from */ parse(source, scene, rootUrl) { SerializationHelper.Parse(() => this, source, scene, rootUrl); } }, (() => { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0; _name_decorators = [serialize()]; _priority_decorators = [serialize()]; _resolveIncludes_decorators = [serialize()]; _registerForExtraEvents_decorators = [serialize()]; __esDecorate(null, null, _name_decorators, { kind: "field", name: "name", static: false, private: false, access: { has: obj => "name" in obj, get: obj => obj.name, set: (obj, value) => { obj.name = value; } }, metadata: _metadata }, _name_initializers, _name_extraInitializers); __esDecorate(null, null, _priority_decorators, { kind: "field", name: "priority", static: false, private: false, access: { has: obj => "priority" in obj, get: obj => obj.priority, set: (obj, value) => { obj.priority = value; } }, metadata: _metadata }, _priority_initializers, _priority_extraInitializers); __esDecorate(null, null, _resolveIncludes_decorators, { kind: "field", name: "resolveIncludes", static: false, private: false, access: { has: obj => "resolveIncludes" in obj, get: obj => obj.resolveIncludes, set: (obj, value) => { obj.resolveIncludes = value; } }, metadata: _metadata }, _resolveIncludes_initializers, _resolveIncludes_extraInitializers); __esDecorate(null, null, _registerForExtraEvents_decorators, { kind: "field", name: "registerForExtraEvents", static: false, private: false, access: { has: obj => "registerForExtraEvents" in obj, get: obj => obj.registerForExtraEvents, set: (obj, value) => { obj.registerForExtraEvents = value; } }, metadata: _metadata }, _registerForExtraEvents_initializers, _registerForExtraEvents_extraInitializers); if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); })(), _a; })(); /** * @internal */ class MaterialDetailMapDefines extends MaterialDefines { constructor() { super(...arguments); this.DETAIL = false; this.DETAILDIRECTUV = 0; this.DETAIL_NORMALBLENDMETHOD = 0; } } /** * Plugin that implements the detail map component of a material * * Inspired from: * Unity: https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@9.0/manual/Mask-Map-and-Detail-Map.html and https://docs.unity3d.com/Manual/StandardShaderMaterialParameterDetail.html * Unreal: https://docs.unrealengine.com/en-US/Engine/Rendering/Materials/HowTo/DetailTexturing/index.html * Cryengine: https://docs.cryengine.com/display/SDKDOC2/Detail+Maps */ let DetailMapConfiguration = (() => { var _a, _DetailMapConfiguration_texture_accessor_storage, _DetailMapConfiguration_normalBlendMethod_accessor_storage, _DetailMapConfiguration_isEnabled_accessor_storage; let _classSuper = MaterialPluginBase; let _texture_decorators; let _texture_initializers = []; let _texture_extraInitializers = []; let _diffuseBlendLevel_decorators; let _diffuseBlendLevel_initializers = []; let _diffuseBlendLevel_extraInitializers = []; let _roughnessBlendLevel_decorators; let _roughnessBlendLevel_initializers = []; let _roughnessBlendLevel_extraInitializers = []; let _bumpLevel_decorators; let _bumpLevel_initializers = []; let _bumpLevel_extraInitializers = []; let _normalBlendMethod_decorators; let _normalBlendMethod_initializers = []; let _normalBlendMethod_extraInitializers = []; let _isEnabled_decorators; let _isEnabled_initializers = []; let _isEnabled_extraInitializers = []; return _a = class DetailMapConfiguration extends _classSuper { /** * The detail texture of the material. */ get texture() { return __classPrivateFieldGet(this, _DetailMapConfiguration_texture_accessor_storage, "f"); } set texture(value) { __classPrivateFieldSet(this, _DetailMapConfiguration_texture_accessor_storage, value, "f"); } /** * The method used to blend the bump and detail normals together */ get normalBlendMethod() { return __classPrivateFieldGet(this, _DetailMapConfiguration_normalBlendMethod_accessor_storage, "f"); } set normalBlendMethod(value) { __classPrivateFieldSet(this, _DetailMapConfiguration_normalBlendMethod_accessor_storage, value, "f"); } /** * Enable or disable the detail map on this material */ get isEnabled() { return __classPrivateFieldGet(this, _DetailMapConfiguration_isEnabled_accessor_storage, "f"); } set isEnabled(value) { __classPrivateFieldSet(this, _DetailMapConfiguration_isEnabled_accessor_storage, value, "f"); } /** @internal */ _markAllSubMeshesAsTexturesDirty() { this._enable(this._isEnabled); this._internalMarkAllSubMeshesAsTexturesDirty(); } /** * Gets a boolean indicating that the plugin is compatible with a given shader language. * @returns true if the plugin is compatible with the shader language */ isCompatible() { return true; } constructor(material, addToPluginList = true) { super(material, "DetailMap", 140, new MaterialDetailMapDefines(), addToPluginList); this._texture = null; _DetailMapConfiguration_texture_accessor_storage.set(this, __runInitializers(this, _texture_initializers, void 0)); /** * Defines how strongly the detail diffuse/albedo channel is blended with the regular diffuse/albedo texture * Bigger values mean stronger blending */ this.diffuseBlendLevel = (__runInitializers(this, _texture_extraInitializers), __runInitializers(this, _diffuseBlendLevel_initializers, 1)); /** * Defines how strongly the detail roughness channel is blended with the regular roughness value * Bigger values mean stronger blending. Only used with PBR materials */ this.roughnessBlendLevel = (__runInitializers(this, _diffuseBlendLevel_extraInitializers), __runInitializers(this, _roughnessBlendLevel_initializers, 1)); /** * Defines how strong the bump effect from the detail map is * Bigger values mean stronger effect */ this.bumpLevel = (__runInitializers(this, _roughnessBlendLevel_extraInitializers), __runInitializers(this, _bumpLevel_initializers, 1)); this._normalBlendMethod = (__runInitializers(this, _bumpLevel_extraInitializers), Material.MATERIAL_NORMALBLENDMETHOD_WHITEOUT); _DetailMapConfiguration_normalBlendMethod_accessor_storage.set(this, __runInitializers(this, _normalBlendMethod_initializers, void 0)); this._isEnabled = (__runInitializers(this, _normalBlendMethod_extraInitializers), false); _DetailMapConfiguration_isEnabled_accessor_storage.set(this, __runInitializers(this, _isEnabled_initializers, false)); /** @internal */ this._internalMarkAllSubMeshesAsTexturesDirty = __runInitializers(this, _isEnabled_extraInitializers); this._internalMarkAllSubMeshesAsTexturesDirty = material._dirtyCallbacks[Constants.MATERIAL_TextureDirtyFlag]; } /** * Checks whether the detail map textures are ready for the sub mesh. * @param defines defines the material defines to inspect * @param scene defines the scene to use for readiness checks * @param engine defines the engine to use for readiness checks * @returns true if the detail map is ready */ isReadyForSubMesh(defines, scene, engine) { if (!this._isEnabled) { return true; } if (defines._areTexturesDirty && scene.texturesEnabled) { if (engine.getCaps().standardDerivatives && this._texture && MaterialFlags.DetailTextureEnabled) { // Detail texture cannot be not blocking. if (!this._texture.isReady()) { return false; } } } return true; } /** * Updates the material defines for the detail map. * @param defines defines the material defines to update * @param scene defines the scene to use for texture checks */ prepareDefines(defines, scene) { if (this._isEnabled) { defines.DETAIL_NORMALBLENDMETHOD = this._normalBlendMethod; const engine = scene.getEngine(); if (defines._areTexturesDirty) { if (engine.getCaps().standardDerivatives && this._texture && MaterialFlags.DetailTextureEnabled && this._isEnabled) { PrepareDefinesForMergedUV(this._texture, defines, "DETAIL"); defines.DETAIL_NORMALBLENDMETHOD = this._normalBlendMethod; } else { defines.DETAIL = false; } } } else { defines.DETAIL = false; } } /** * Binds the detail map data for a sub mesh. * @param uniformBuffer defines the uniform buffer to update * @param scene defines the scene to use for texture binding */ bindForSubMesh(uniformBuffer, scene) { if (!this._isEnabled) { return; } const isFrozen = this._material.isFrozen; if (!uniformBuffer.useUbo || !isFrozen || !uniformBuffer.isSync) { if (this._texture && MaterialFlags.DetailTextureEnabled) { uniformBuffer.updateFloat4("vDetailInfos", this._texture.coordinatesIndex, this.diffuseBlendLevel, this.bumpLevel, this.roughnessBlendLevel); BindTextureMatrix(this._texture, uniformBuffer, "detail"); } } // Textures if (scene.texturesEnabled) { if (this._texture && MaterialFlags.DetailTextureEnabled) { uniformBuffer.setTexture("detailSampler", this._texture); } } } /** * Checks whether the detail map uses a texture. * @param texture defines the texture to check * @returns true if the texture is used by the detail map */ hasTexture(texture) { if (this._texture === texture) { return true; } return false; } /** * Adds the active detail map textures. * @param activeTextures defines the list of active textures to update */ getActiveTextures(activeTextures) { if (this._texture) { activeTextures.push(this._texture); } } /** * Adds the animatable detail map textures. * @param animatables defines the list of animatables to update */ getAnimatables(animatables) { if (this._texture && this._texture.animations && this._texture.animations.length > 0) { animatables.push(this._texture); } } /** * Disposes the detail map textures. * @param forceDisposeTextures defines whether to dispose the textures */ dispose(forceDisposeTextures) { if (forceDisposeTextures) { this._texture?.dispose(); } } getClassName() { return "DetailMapConfiguration"; } /** * Adds the detail map sampler names. * @param samplers defines the list of sampler names to update */ getSamplers(samplers) { samplers.push("detailSampler"); } getUniforms() { return { ubo: [ { name: "vDetailInfos", size: 4, type: "vec4" }, { name: "detailMatrix", size: 16, type: "mat4" }, ], }; } }, _DetailMapConfiguration_texture_accessor_storage = new WeakMap(), _DetailMapConfiguration_normalBlendMethod_accessor_storage = new WeakMap(), _DetailMapConfiguration_isEnabled_accessor_storage = new WeakMap(), (() => { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; _texture_decorators = [serializeAsTexture("detailTexture"), expandToProperty("_markAllSubMeshesAsTexturesDirty")]; _diffuseBlendLevel_decorators = [serialize()]; _roughnessBlendLevel_decorators = [serialize()]; _bumpLevel_decorators = [serialize()]; _normalBlendMethod_decorators = [serialize(), expandToProperty("_markAllSubMeshesAsTexturesDirty")]; _isEnabled_decorators = [serialize(), expandToProperty("_markAllSubMeshesAsTexturesDirty")]; __esDecorate(_a, null, _texture_decorators, { kind: "accessor", name: "texture", static: false, private: false, access: { has: obj => "texture" in obj, get: obj => obj.texture, set: (obj, value) => { obj.texture = value; } }, metadata: _metadata }, _texture_initializers, _texture_extraInitializers); __esDecorate(_a, null, _normalBlendMethod_decorators, { kind: "accessor", name: "normalBlendMethod", static: false, private: false, access: { has: obj => "normalBlendMethod" in obj, get: obj => obj.normalBlendMethod, set: (obj, value) => { obj.normalBlendMethod = value; } }, metadata: _metadata }, _normalBlendMethod_initializers, _normalBlendMethod_extraInitializers); __esDecorate(_a, null, _isEnabled_decorators, { kind: "accessor", name: "isEnabled", static: false, private: false, access: { has: obj => "isEnabled" in obj, get: obj => obj.isEnabled, set: (obj, value) => { obj.isEnabled = value; } }, metadata: _metadata }, _isEnabled_initializers, _isEnabled_extraInitializers); __esDecorate(null, null, _diffuseBlendLevel_decorators, { kind: "field", name: "diffuseBlendLevel", static: false, private: false, access: { has: obj => "diffuseBlendLevel" in obj, get: obj => obj.diffuseBlendLevel, set: (obj, value) => { obj.diffuseBlendLevel = value; } }, metadata: _metadata }, _diffuseBlendLevel_initializers, _diffuseBlendLevel_extraInitializers); __esDecorate(null, null, _roughnessBlendLevel_decorators, { kind: "field", name: "roughnessBlendLevel", static: false, private: false, access: { has: obj => "roughnessBlendLevel" in obj, get: obj => obj.roughnessBlendLevel, set: (obj, value) => { obj.roughnessBlendLevel = value; } }, metadata: _metadata }, _roughnessBlendLevel_initializers, _roughnessBlendLevel_extraInitializers); __esDecorate(null, null, _bumpLevel_decorators, { kind: "field", name: "bumpLevel", static: false, private: false, access: { has: obj => "bumpLevel" in obj, get: obj => obj.bumpLevel, set: (obj, value) => { obj.bumpLevel = value; } }, metadata: _metadata }, _bumpLevel_initializers, _bumpLevel_extraInitializers); if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); })(), _a; })(); export { DetailMapConfiguration as D, MaterialPluginBase as M }; //# sourceMappingURL=material.detailMapConfiguration-CHgbrJ-3.esm.js.map