UNPKG

@openhps/core

Version:

Open Hybrid Positioning System - Core component

312 lines (284 loc) 8.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.pmremTexture = exports.default = void 0; var _TempNode = _interopRequireDefault(require("../core/TempNode.js")); var _TextureNode = require("../accessors/TextureNode.js"); var _PMREMUtils = require("./PMREMUtils.js"); var _UniformNode = require("../core/UniformNode.js"); var _constants = require("../core/constants.js"); var _TSLBase = require("../tsl/TSLBase.js"); var _Texture = require("../../textures/Texture.js"); var _PMREMGenerator = _interopRequireDefault(require("../../renderers/common/extras/PMREMGenerator.js")); var _MaterialProperties = require("../accessors/MaterialProperties.js"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const _cache = new WeakMap(); /** * Generates the cubeUV size based on the given image height. * * @private * @param {number} imageHeight - The image height. * @return {{texelWidth: number,texelHeight: number, maxMip: number}} The result object. */ function _generateCubeUVSize(imageHeight) { const maxMip = Math.log2(imageHeight) - 2; const texelHeight = 1.0 / imageHeight; const texelWidth = 1.0 / (3 * Math.max(Math.pow(2, maxMip), 7 * 16)); return { texelWidth, texelHeight, maxMip }; } /** * Generates a PMREM from the given texture. * * @private * @param {Texture} texture - The texture to create the PMREM for. * @param {Renderer} renderer - The renderer. * @param {PMREMGenerator} generator - The PMREM generator. * @return {?Texture} The PMREM. */ function _getPMREMFromTexture(texture, renderer, generator) { const cache = _getCache(renderer); let cacheTexture = cache.get(texture); const pmremVersion = cacheTexture !== undefined ? cacheTexture.pmremVersion : -1; if (pmremVersion !== texture.pmremVersion) { const image = texture.image; if (texture.isCubeTexture) { if (isCubeMapReady(image)) { cacheTexture = generator.fromCubemap(texture, cacheTexture); } else { return null; } } else { if (isEquirectangularMapReady(image)) { cacheTexture = generator.fromEquirectangular(texture, cacheTexture); } else { return null; } } cacheTexture.pmremVersion = texture.pmremVersion; cache.set(texture, cacheTexture); } return cacheTexture.texture; } /** * Returns a cache that stores generated PMREMs for the respective textures. * A cache must be maintained per renderer since PMREMs are render target textures * which can't be shared across render contexts. * * @private * @param {Renderer} renderer - The renderer. * @return {WeakMap<Texture, Texture>} The PMREM cache. */ function _getCache(renderer) { let rendererCache = _cache.get(renderer); if (rendererCache === undefined) { rendererCache = new WeakMap(); _cache.set(renderer, rendererCache); } return rendererCache; } /** * This node represents a PMREM which is a special type of preprocessed * environment map intended for PBR materials. * * ```js * const material = new MeshStandardNodeMaterial(); * material.envNode = pmremTexture( envMap ); * ``` * * @augments TempNode */ class PMREMNode extends _TempNode.default { static get type() { return 'PMREMNode'; } /** * Constructs a new function overloading node. * * @param {Texture} value - The input texture. * @param {Node<vec2>} [uvNode=null] - The uv node. * @param {Node<float>} [levelNode=null] - The level node. */ constructor(value, uvNode = null, levelNode = null) { super('vec3'); /** * Reference to the input texture. * * @private * @type {Texture} */ this._value = value; /** * Reference to the generated PMREM. * * @private * @type {Texture | null} * @default null */ this._pmrem = null; /** * The uv node. * * @type {Node<vec2>} */ this.uvNode = uvNode; /** * The level node. * * @type {Node<float>} */ this.levelNode = levelNode; /** * Reference to a PMREM generator. * * @private * @type {?PMREMGenerator} * @default null */ this._generator = null; const defaultTexture = new _Texture.Texture(); defaultTexture.isRenderTargetTexture = true; /** * The texture node holding the generated PMREM. * * @private * @type {TextureNode} */ this._texture = (0, _TextureNode.texture)(defaultTexture); /** * A uniform representing the PMREM's width. * * @private * @type {UniformNode<float>} */ this._width = (0, _UniformNode.uniform)(0); /** * A uniform representing the PMREM's height. * * @private * @type {UniformNode<float>} */ this._height = (0, _UniformNode.uniform)(0); /** * A uniform representing the PMREM's max Mip. * * @private * @type {UniformNode<float>} */ this._maxMip = (0, _UniformNode.uniform)(0); /** * The `updateBeforeType` is set to `NodeUpdateType.RENDER`. * * @type {string} * @default 'render' */ this.updateBeforeType = _constants.NodeUpdateType.RENDER; } set value(value) { this._value = value; this._pmrem = null; } /** * The node's texture value. * * @type {Texture} */ get value() { return this._value; } /** * Uses the given PMREM texture to update internal values. * * @param {Texture} texture - The PMREM texture. */ updateFromTexture(texture) { const cubeUVSize = _generateCubeUVSize(texture.image.height); this._texture.value = texture; this._width.value = cubeUVSize.texelWidth; this._height.value = cubeUVSize.texelHeight; this._maxMip.value = cubeUVSize.maxMip; } updateBefore(frame) { let pmrem = this._pmrem; const pmremVersion = pmrem ? pmrem.pmremVersion : -1; const texture = this._value; if (pmremVersion !== texture.pmremVersion) { if (texture.isPMREMTexture === true) { pmrem = texture; } else { pmrem = _getPMREMFromTexture(texture, frame.renderer, this._generator); } if (pmrem !== null) { this._pmrem = pmrem; this.updateFromTexture(pmrem); } } } setup(builder) { if (this._generator === null) { this._generator = new _PMREMGenerator.default(builder.renderer); } this.updateBefore(builder); // let uvNode = this.uvNode; if (uvNode === null && builder.context.getUV) { uvNode = builder.context.getUV(this); } // uvNode = _MaterialProperties.materialEnvRotation.mul((0, _TSLBase.vec3)(uvNode.x, uvNode.y.negate(), uvNode.z)); // let levelNode = this.levelNode; if (levelNode === null && builder.context.getTextureLevel) { levelNode = builder.context.getTextureLevel(this); } // return (0, _PMREMUtils.textureCubeUV)(this._texture, uvNode, levelNode, this._width, this._height, this._maxMip); } dispose() { super.dispose(); if (this._generator !== null) this._generator.dispose(); } } var _default = exports.default = PMREMNode; /** * Returns `true` if the given cube map image has been fully loaded. * * @private * @param {?Array<(Image|Object)>} [image] - The cube map image. * @return {boolean} Whether the given cube map is ready or not. */ function isCubeMapReady(image) { if (image === null || image === undefined) return false; let count = 0; const length = 6; for (let i = 0; i < length; i++) { if (image[i] !== undefined) count++; } return count === length; } /** * Returns `true` if the given equirectangular image has been fully loaded. * * @private * @param {(Image|Object)} image - The equirectangular image. * @return {boolean} Whether the given cube map is ready or not. */ function isEquirectangularMapReady(image) { if (image === null || image === undefined) return false; return image.height > 0; } /** * TSL function for creating a PMREM node. * * @tsl * @function * @param {Texture} value - The input texture. * @param {?Node<vec2>} [uvNode=null] - The uv node. * @param {?Node<float>} [levelNode=null] - The level node. * @returns {PMREMNode} */ const pmremTexture = exports.pmremTexture = /*@__PURE__*/(0, _TSLBase.nodeProxy)(PMREMNode).setParameterLength(1, 3);