{"version":3,"sources":["jsdelivr-header.js","/npm/@lume/three-projected-material@0.4.0/dist/ProjectedMaterial.js"],"names":[],"mappings":"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","file":"/npm/@lume/three-projected-material@0.4.0/dist/ProjectedMaterial.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/@lume/three-projected-material@0.4.0/dist/ProjectedMaterial.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","import { MeshPhysicalMaterial } from 'three/src/materials/MeshPhysicalMaterial.js';\nimport { PerspectiveCamera } from 'three/src/cameras/PerspectiveCamera.js';\nimport { Texture } from 'three/src/textures/Texture.js';\nimport { Vector2 } from 'three/src/math/Vector2.js';\nimport { InstancedBufferAttribute } from 'three/src/core/InstancedBufferAttribute.js';\nimport { Matrix4 } from 'three/src/math/Matrix4.js';\nimport { Vector3 } from 'three/src/math/Vector3.js';\nimport { monkeyPatch, addLoadListener } from './three-utils.js';\nimport { version } from './version.js';\nexport class ProjectedMaterial extends MeshPhysicalMaterial {\n    static version = version;\n    // internal values... they are exposed via getters\n    #camera = new PerspectiveCamera();\n    #fitment = 'contain';\n    #textureScale = 1;\n    /**\n     * The camera to be used for texture projection. Any time you change this,\n     * also set `needsUpdate` to `true`.\n     * TODO set needsUpdate automatically.\n     */\n    get camera() {\n        return this.#camera;\n    }\n    set camera(camera) {\n        if (!camera || !camera.isCamera) {\n            throw new Error('Invalid camera set to the ProjectedMaterial');\n        }\n        this.#camera = camera;\n        this.#saveDimensions();\n        this.needsUpdate = true;\n        // toggle between two onBeforeCompile functions in order to force\n        // WebGLRenderer to make a new program when toggled, or else the\n        // renderer will not call onBeforeCompile again if we change the\n        // `camera` (the renderer detects the material have changed if it\n        // detects a different onBeforeCompile function), which means the\n        // material.defines.ORTHOGRAPHIC value will not change when we've\n        // changed the `camera` without this trick.\n        // Issue: https://discourse.threejs.org/t/38614\n        this.onBeforeCompile = isPerspectiveCamera(this.#camera)\n            ? this.#onBeforeCompilePerspective\n            : this.#onBeforeCompileOrtho;\n    }\n    get texture() {\n        return this.uniforms.projectedTexture.value;\n    }\n    set texture(texture) {\n        if (!texture?.isTexture) {\n            throw new Error('Invalid texture set to the ProjectedMaterial');\n        }\n        this.uniforms.projectedTexture.value = texture;\n        this.uniforms.isTextureLoaded.value = Boolean(texture.image);\n        if (!this.uniforms.isTextureLoaded.value) {\n            addLoadListener(texture, () => {\n                this.uniforms.isTextureLoaded.value = true;\n                this.#saveDimensions();\n            });\n        }\n        else {\n            this.#saveDimensions();\n        }\n    }\n    get textureScale() {\n        return this.#textureScale;\n    }\n    set textureScale(textureScale) {\n        this.#textureScale = textureScale;\n        this.#saveDimensions();\n    }\n    get textureOffset() {\n        return this.uniforms.textureOffset.value;\n    }\n    set textureOffset(textureOffset) {\n        this.uniforms.textureOffset.value = textureOffset;\n    }\n    get fitment() {\n        return this.#fitment;\n    }\n    set fitment(value) {\n        this.#fitment = value;\n        this.#saveDimensions();\n    }\n    get frontFacesOnly() {\n        return this.uniforms.frontFacesOnly.value;\n    }\n    set frontFacesOnly(frontFacesOnly) {\n        this.uniforms.frontFacesOnly.value = frontFacesOnly;\n    }\n    uniforms;\n    isProjectedMaterial = true;\n    constructor({ camera, texture = new Texture(), textureScale, textureOffset = new Vector2(), fitment, frontFacesOnly = true, ...options } = {}) {\n        if (!texture.isTexture) {\n            throw new Error('Invalid texture passed to the ProjectedMaterial');\n        }\n        if (camera && !camera.isCamera) {\n            throw new Error('Invalid camera passed to the ProjectedMaterial');\n        }\n        super(options);\n        Object.defineProperty(this, 'isProjectedMaterial', { value: this.isProjectedMaterial });\n        this.#fitment = fitment ?? this.#fitment;\n        this.#textureScale = textureScale ?? this.#textureScale;\n        this.uniforms = {\n            projectedTexture: { value: texture },\n            // this avoids rendering black if the texture\n            // hasn't loaded yet\n            isTextureLoaded: { value: Boolean(texture.image) },\n            // don't show the texture if we haven't called project()\n            isTextureProjected: { value: false },\n            // if we have multiple materials we want to show the\n            // background only of the first material\n            backgroundOpacity: { value: 1 },\n            // these will be set on project()\n            viewMatrixCamera: { value: new Matrix4() },\n            projectionMatrixCamera: { value: new Matrix4() },\n            projPosition: { value: new Vector3() },\n            projDirection: { value: new Vector3(0, 0, -1) },\n            // we will set this later when we will have positioned the object\n            savedModelMatrix: { value: new Matrix4() },\n            widthScaled: { value: 1 },\n            heightScaled: { value: 1 },\n            textureOffset: { value: textureOffset },\n            frontFacesOnly: { value: frontFacesOnly },\n        };\n        if (camera)\n            this.camera = camera;\n        this.#saveDimensions();\n        // If the image texture passed hasn't loaded yet,\n        // wait for it to load and compute the correct proportions.\n        // This avoids rendering black while the texture is loading\n        addLoadListener(texture, () => {\n            this.uniforms.isTextureLoaded.value = true;\n            this.#saveDimensions();\n        });\n    }\n    #onBeforeCompilePerspective = (shader, ...args) => {\n        // @ts-expect-error material ✨\n        delete shader.defines.ORTHOGRAPHIC;\n        this.#onBeforeCompileCommon(shader, ...args);\n    };\n    #onBeforeCompileOrtho = (shader, ...args) => {\n        // @ts-expect-error material ✨\n        shader.defines.ORTHOGRAPHIC = '';\n        this.#onBeforeCompileCommon(shader, ...args);\n    };\n    #onBeforeCompileCommon = shader => {\n        // expose also the material's uniforms\n        Object.assign(this.uniforms, shader.uniforms);\n        shader.uniforms = this.uniforms;\n        shader.vertexShader = monkeyPatch(shader.vertexShader, {\n            header: /* glsl */ `\n\t\t\t\t\tuniform mat4 viewMatrixCamera;\n\t\t\t\t\tuniform mat4 projectionMatrixCamera;\n\n\t\t\t\t\t#ifdef USE_INSTANCING\n\t\t\t\t\tattribute vec4 savedModelMatrix0;\n\t\t\t\t\tattribute vec4 savedModelMatrix1;\n\t\t\t\t\tattribute vec4 savedModelMatrix2;\n\t\t\t\t\tattribute vec4 savedModelMatrix3;\n\t\t\t\t\t#else\n\t\t\t\t\tuniform mat4 savedModelMatrix;\n\t\t\t\t\t#endif\n\n\t\t\t\t\tvarying vec3 vSavedNormal;\n\t\t\t\t\tvarying vec4 vTexCoords;\n\t\t\t\t\t#ifndef ORTHOGRAPHIC\n\t\t\t\t\tvarying vec4 vWorldPosition;\n\t\t\t\t\t#endif\n\t\t\t\t`,\n            main: /* glsl */ `\n\t\t\t\t\t#ifdef USE_INSTANCING\n\t\t\t\t\tmat4 savedModelMatrix = mat4(\n\t\t\t\t\t\tsavedModelMatrix0,\n\t\t\t\t\t\tsavedModelMatrix1,\n\t\t\t\t\t\tsavedModelMatrix2,\n\t\t\t\t\t\tsavedModelMatrix3\n\t\t\t\t\t);\n\t\t\t\t\t#endif\n\n\t\t\t\t\tvSavedNormal = mat3(savedModelMatrix) * normal;\n\t\t\t\t\tvTexCoords = projectionMatrixCamera * viewMatrixCamera * savedModelMatrix * vec4(position, 1.0);\n\t\t\t\t\t#ifndef ORTHOGRAPHIC\n\t\t\t\t\tvWorldPosition = savedModelMatrix * vec4(position, 1.0);\n\t\t\t\t\t#endif\n\t\t\t\t`,\n        });\n        shader.fragmentShader = monkeyPatch(shader.fragmentShader, {\n            header: /* glsl */ `\n\t\t\t\t\tuniform sampler2D projectedTexture;\n\t\t\t\t\tuniform bool isTextureLoaded;\n\t\t\t\t\tuniform bool isTextureProjected;\n\t\t\t\t\tuniform float backgroundOpacity;\n\t\t\t\t\tuniform vec3 projPosition;\n\t\t\t\t\tuniform vec3 projDirection;\n\t\t\t\t\tuniform float widthScaled;\n\t\t\t\t\tuniform float heightScaled;\n\t\t\t\t\tuniform vec2 textureOffset;\n\t\t\t\t\tuniform bool frontFacesOnly;\n\n\t\t\t\t\tvarying vec3 vSavedNormal;\n\t\t\t\t\tvarying vec4 vTexCoords;\n\t\t\t\t\t#ifndef ORTHOGRAPHIC\n\t\t\t\t\tvarying vec4 vWorldPosition;\n\t\t\t\t\t#endif\n\n\t\t\t\t\tfloat mapRange(float value, float min1, float max1, float min2, float max2) {\n\t\t\t\t\t\treturn min2 + (value - min1) * (max2 - min2) / (max1 - min1);\n\t\t\t\t\t}\n\t\t\t\t`,\n            'vec4 diffuseColor = vec4( diffuse, opacity );': /* glsl */ `\n\t\t\t\t\t// clamp the w to make sure we don't project behind\n\t\t\t\t\tfloat w = max(vTexCoords.w, 0.0);\n\n\t\t\t\t\tvec2 uv = (vTexCoords.xy / w) * 0.5 + 0.5;\n\n\t\t\t\t\tuv += textureOffset;\n\n\t\t\t\t\t// apply the corrected width and height\n\t\t\t\t\tuv.x = mapRange(uv.x, 0.0, 1.0, 0.5 - widthScaled / 2.0, 0.5 + widthScaled / 2.0);\n\t\t\t\t\tuv.y = mapRange(uv.y, 0.0, 1.0, 0.5 - heightScaled / 2.0, 0.5 + heightScaled / 2.0);\n\n\t\t\t\t\t// this makes sure we don't sample out of the texture\n\t\t\t\t\tbool isInTexture = (max(uv.x, uv.y) <= 1.0 && min(uv.x, uv.y) >= 0.0);\n\n\t\t\t\t\t// this makes sure we don't render also the back of the object if frontFacesOnly is true\n\t\t\t\t\t// FIXME projection direction is wrong in some cases, namely\n\t\t\t\t\t// when the camera and the target are both a child and not at the\n\t\t\t\t\t// scene origin.\n\t\t\t\t\t#ifdef ORTHOGRAPHIC\n\t\t\t\t\tvec3 projectorDirection = projDirection;\n\t\t\t\t\t#else\n\t\t\t\t\tvec3 projectorDirection = normalize(projPosition - vWorldPosition.xyz);\n\t\t\t\t\t#endif\n\t\t\t\t\tfloat dotProduct = dot(vSavedNormal, projectorDirection);\n\t\t\t\t\tbool isFacingProjector = frontFacesOnly ? dotProduct > 0.0000001 : true;\n\n\n\t\t\t\t\tvec4 diffuseColor = vec4(diffuse, opacity * backgroundOpacity);\n\n\t\t\t\t\tif (isFacingProjector && isInTexture && isTextureLoaded && isTextureProjected) {\n\t\t\t\t\t\tvec4 textureColor = texture2D(projectedTexture, uv);\n\n\t\t\t\t\t\t// apply the material opacity\n\t\t\t\t\t\ttextureColor.a *= opacity;\n\n\t\t\t\t\t\t// https://learnopengl.com/Advanced-OpenGL/Blending\n\t\t\t\t\t\tdiffuseColor = textureColor * textureColor.a + diffuseColor * (1.0 - textureColor.a);\n\t\t\t\t\t}\n\t\t\t\t`,\n        });\n    };\n    /**\n     * Call this any time the camera-specific parameters have been updated\n     * externally. Non-camera-specific changes are otherwise covered by the project()\n     * method.\n     */\n    updateFromCamera() {\n        this.uniforms.projectionMatrixCamera.value.copy(this.camera.projectionMatrix);\n        this.#saveDimensions();\n    }\n    #saveDimensions() {\n        // scale to keep the image proportions and apply textureScale\n        computeScaledDimensions(this.texture, this.camera, this.textureScale, this.fitment, size);\n        this.uniforms.widthScaled.value = size.x;\n        this.uniforms.heightScaled.value = size.y;\n    }\n    #saveCameraMatrices(updateWorldMatrices = true) {\n        // make sure the camera matrices are updated\n        this.camera.updateProjectionMatrix(); // TODO move to updateFromCamera()\n        if (updateWorldMatrices) {\n            this.camera.updateMatrixWorld();\n            this.camera.updateWorldMatrix(true, false);\n        }\n        // update the uniforms from the camera so they're\n        // fixed in the camera's position at the projection time\n        const viewMatrixCamera = this.camera.matrixWorldInverse;\n        const projectionMatrixCamera = this.camera.projectionMatrix;\n        const modelMatrixCamera = this.camera.matrixWorld;\n        this.uniforms.viewMatrixCamera.value.copy(viewMatrixCamera); // TODO rename to cameraMatrixWorldInverse\n        this.uniforms.projectionMatrixCamera.value.copy(projectionMatrixCamera); // TODO move to updateFromCamera()\n        this.uniforms.projPosition.value.copy(this.camera.position);\n        this.uniforms.projDirection.value.set(0, 0, 1).applyMatrix4(modelMatrixCamera);\n        // tell the shader we've projected\n        this.uniforms.isTextureProjected.value = true;\n    }\n    /**\n     * Call this any time the projection camera or the object with the\n     * ProjectedMaterial have been transformed.\n     */\n    project(mesh, updateWorldMatrices = true) {\n        if (!isProjectedMaterial(mesh.material)) {\n            throw new Error(`The mesh material must be a ProjectedMaterial`);\n        }\n        if (!(Array.isArray(mesh.material) ? mesh.material.some(m => m === this) : mesh.material === this)) {\n            throw new Error(`The provided mesh doesn't have the same material as where project() has been called from`);\n        }\n        // make sure the matrix is updated\n        if (updateWorldMatrices)\n            mesh.updateWorldMatrix(true, false);\n        // we save the object model matrix so it's projected relative\n        // to that position, like a snapshot\n        this.uniforms.savedModelMatrix.value.copy(mesh.matrixWorld);\n        // if the material is not the first, output just the texture\n        if (Array.isArray(mesh.material)) {\n            const materialIndex = mesh.material.indexOf(this);\n            if (!mesh.material[materialIndex].transparent) {\n                throw new Error(`You have to pass \"transparent: true\" to the ProjectedMaterial if you're working with multiple materials.`);\n            }\n            if (materialIndex > 0) {\n                this.uniforms.backgroundOpacity.value = 0;\n            }\n        }\n        // persist also the current camera position and matrices\n        this.#saveCameraMatrices(updateWorldMatrices);\n    }\n    projectInstanceAt(index, instancedMesh, matrixWorld, { forceCameraSave = false } = {}) {\n        if (!instancedMesh.isInstancedMesh) {\n            throw new Error(`The provided mesh is not an InstancedMesh`);\n        }\n        if (!isProjectedMaterial(instancedMesh.material)) {\n            throw new Error(`The InstancedMesh material must be a ProjectedMaterial`);\n        }\n        if (!(Array.isArray(instancedMesh.material)\n            ? instancedMesh.material.some(m => m === this)\n            : instancedMesh.material === this)) {\n            throw new Error(`The provided InstancedMeshhave't i samenclude thas e material where project() has been called from`);\n        }\n        if (!instancedMesh.geometry.attributes[`savedModelMatrix0`] ||\n            !instancedMesh.geometry.attributes[`savedModelMatrix1`] ||\n            !instancedMesh.geometry.attributes[`savedModelMatrix2`] ||\n            !instancedMesh.geometry.attributes[`savedModelMatrix3`]) {\n            throw new Error(`No allocated data found on the geometry, please call 'allocateProjectionData(geometry, instancesCount)'`);\n        }\n        instancedMesh.geometry.attributes[`savedModelMatrix0`].setXYZW(index, matrixWorld.elements[0], matrixWorld.elements[1], matrixWorld.elements[2], matrixWorld.elements[3]);\n        instancedMesh.geometry.attributes[`savedModelMatrix1`].setXYZW(index, matrixWorld.elements[4], matrixWorld.elements[5], matrixWorld.elements[6], matrixWorld.elements[7]);\n        instancedMesh.geometry.attributes[`savedModelMatrix2`].setXYZW(index, matrixWorld.elements[8], matrixWorld.elements[9], matrixWorld.elements[10], matrixWorld.elements[11]);\n        instancedMesh.geometry.attributes[`savedModelMatrix3`].setXYZW(index, matrixWorld.elements[12], matrixWorld.elements[13], matrixWorld.elements[14], matrixWorld.elements[15]);\n        // if the material is not the first, output just the texture\n        if (Array.isArray(instancedMesh.material)) {\n            const materialIndex = instancedMesh.material.indexOf(this);\n            if (!instancedMesh.material[materialIndex].transparent) {\n                throw new Error(`You have to pass \"transparent: true\" to the ProjectedMaterial if you're working with multiple materials.`);\n            }\n            if (materialIndex > 0) {\n                this.uniforms.backgroundOpacity.value = 0;\n            }\n        }\n        // persist the current camera position and matrices\n        // only if it's the first instance since most surely\n        // in all other instances the camera won't change\n        if (index === 0 || forceCameraSave) {\n            this.#saveCameraMatrices();\n        }\n    }\n    copy(source) {\n        super.copy(source);\n        this.camera = source.camera;\n        this.texture = source.texture;\n        this.textureScale = source.textureScale;\n        this.textureOffset = source.textureOffset;\n        this.fitment = source.fitment;\n        return this;\n    }\n}\n// get camera ratio from different types of cameras\nfunction getCameraRatio(camera) {\n    switch (camera.type) {\n        case 'PerspectiveCamera': {\n            camera = camera; // Cast because Three.js .type property regressed to plain `string` type\n            return camera.aspect;\n        }\n        case 'OrthographicCamera': {\n            camera = camera; // Cast because Three.js .type property regressed to plain `string` type\n            const width = Math.abs(camera.right - camera.left);\n            const height = Math.abs(camera.top - camera.bottom);\n            return width / height;\n        }\n        default: {\n            throw new Error(`The given type of camera is currently not supported in ProjectedMaterial`);\n        }\n    }\n}\nconst size = { x: 1, y: 1 };\n// scale to keep the image proportions and apply textureScale\nfunction computeScaledDimensions(texture, camera, textureScale, fitment, outputSize) {\n    // return some default values if the image hasn't loaded yet\n    if (!texture.image) {\n        outputSize.x = 1;\n        outputSize.y = 1;\n        return;\n    }\n    // return if it's a video and if the video hasn't loaded yet\n    if (texture.image.videoWidth === 0 && texture.image.videoHeight === 0) {\n        outputSize.x = 1;\n        outputSize.y = 1;\n        return;\n    }\n    const sourceWidth = texture.image.naturalWidth || texture.image.videoWidth || texture.image.clientWidth;\n    const sourceHeight = texture.image.naturalHeight || texture.image.videoHeight || texture.image.clientHeight;\n    const cameraWidth = 1;\n    const ratioCamera = getCameraRatio(camera);\n    const cameraHeight = cameraWidth * (1 / ratioCamera);\n    const ratio = sourceWidth / sourceHeight;\n    if (fitment === 'cover' ? ratio > ratioCamera : ratio < ratioCamera) {\n        const width = cameraHeight * ratio;\n        outputSize.x = 1 / ((width / cameraWidth) * textureScale);\n        outputSize.y = 1 / textureScale;\n    }\n    else {\n        const height = cameraWidth * (1 / ratio);\n        outputSize.x = 1 / textureScale;\n        outputSize.y = 1 / ((height / cameraHeight) * textureScale);\n    }\n}\nexport function allocateProjectionData(geometry, instancesCount) {\n    geometry.setAttribute(`savedModelMatrix0`, new InstancedBufferAttribute(new Float32Array(instancesCount * 4), 4));\n    geometry.setAttribute(`savedModelMatrix1`, new InstancedBufferAttribute(new Float32Array(instancesCount * 4), 4));\n    geometry.setAttribute(`savedModelMatrix2`, new InstancedBufferAttribute(new Float32Array(instancesCount * 4), 4));\n    geometry.setAttribute(`savedModelMatrix3`, new InstancedBufferAttribute(new Float32Array(instancesCount * 4), 4));\n}\nexport function isOrthographicCamera(cam) {\n    return cam.isOrthographicCamera;\n}\nexport function isPerspectiveCamera(cam) {\n    return cam.isPerspectiveCamera;\n}\nexport function isProjectedMaterial(mat) {\n    const _mat = mat;\n    return Array.isArray(_mat) ? _mat.every(m => m.isProjectedMaterial) : _mat.isProjectedMaterial;\n}\n"]}