{"version":3,"file":"LightProbeGenerator.cjs","sources":["../../src/lights/LightProbeGenerator.js"],"sourcesContent":["import { Color, LightProbe, SphericalHarmonics3, Vector3 } from 'three'\n\nclass LightProbeGenerator {\n  // https://www.ppsloan.org/publications/StupidSH36.pdf\n  static fromCubeTexture(cubeTexture) {\n    let totalWeight = 0\n\n    const coord = new Vector3()\n\n    const dir = new Vector3()\n\n    const color = new Color()\n\n    const shBasis = [0, 0, 0, 0, 0, 0, 0, 0, 0]\n\n    const sh = new SphericalHarmonics3()\n    const shCoefficients = sh.coefficients\n\n    for (let faceIndex = 0; faceIndex < 6; faceIndex++) {\n      const image = cubeTexture.image[faceIndex]\n\n      const width = image.width\n      const height = image.height\n\n      const canvas = document.createElement('canvas')\n\n      canvas.width = width\n      canvas.height = height\n\n      const context = canvas.getContext('2d')\n\n      context.drawImage(image, 0, 0, width, height)\n\n      const imageData = context.getImageData(0, 0, width, height)\n\n      const data = imageData.data\n\n      const imageWidth = imageData.width // assumed to be square\n\n      const pixelSize = 2 / imageWidth\n\n      for (let i = 0, il = data.length; i < il; i += 4) {\n        // RGBA assumed\n\n        // pixel color\n        color.setRGB(data[i] / 255, data[i + 1] / 255, data[i + 2] / 255)\n\n        // convert to linear color space\n        if ('colorSpace' in cubeTexture) {\n          if (cubeTexture.colorSpace === 'srgb') {\n            color.convertSRGBToLinear()\n          }\n        } else if (cubeTexture.encoding === 3001) {\n          // sRGBEncoding\n          color.convertSRGBToLinear()\n        }\n\n        // pixel coordinate on unit cube\n\n        const pixelIndex = i / 4\n\n        const col = -1 + ((pixelIndex % imageWidth) + 0.5) * pixelSize\n\n        const row = 1 - (Math.floor(pixelIndex / imageWidth) + 0.5) * pixelSize\n\n        switch (faceIndex) {\n          case 0:\n            coord.set(-1, row, -col)\n            break\n\n          case 1:\n            coord.set(1, row, col)\n            break\n\n          case 2:\n            coord.set(-col, 1, -row)\n            break\n\n          case 3:\n            coord.set(-col, -1, row)\n            break\n\n          case 4:\n            coord.set(-col, row, 1)\n            break\n\n          case 5:\n            coord.set(col, row, -1)\n            break\n        }\n\n        // weight assigned to this pixel\n\n        const lengthSq = coord.lengthSq()\n\n        const weight = 4 / (Math.sqrt(lengthSq) * lengthSq)\n\n        totalWeight += weight\n\n        // direction vector to this pixel\n        dir.copy(coord).normalize()\n\n        // evaluate SH basis functions in direction dir\n        SphericalHarmonics3.getBasisAt(dir, shBasis)\n\n        // accummuulate\n        for (let j = 0; j < 9; j++) {\n          shCoefficients[j].x += shBasis[j] * color.r * weight\n          shCoefficients[j].y += shBasis[j] * color.g * weight\n          shCoefficients[j].z += shBasis[j] * color.b * weight\n        }\n      }\n    }\n\n    // normalize\n    const norm = (4 * Math.PI) / totalWeight\n\n    for (let j = 0; j < 9; j++) {\n      shCoefficients[j].x *= norm\n      shCoefficients[j].y *= norm\n      shCoefficients[j].z *= norm\n    }\n\n    return new LightProbe(sh)\n  }\n\n  static fromCubeRenderTarget(renderer, cubeRenderTarget) {\n    // The renderTarget must be set to RGBA in order to make readRenderTargetPixels works\n    let totalWeight = 0\n\n    const coord = new Vector3()\n\n    const dir = new Vector3()\n\n    const color = new Color()\n\n    const shBasis = [0, 0, 0, 0, 0, 0, 0, 0, 0]\n\n    const sh = new SphericalHarmonics3()\n    const shCoefficients = sh.coefficients\n\n    for (let faceIndex = 0; faceIndex < 6; faceIndex++) {\n      const imageWidth = cubeRenderTarget.width // assumed to be square\n      const data = new Uint8Array(imageWidth * imageWidth * 4)\n      renderer.readRenderTargetPixels(cubeRenderTarget, 0, 0, imageWidth, imageWidth, data, faceIndex)\n\n      const pixelSize = 2 / imageWidth\n\n      for (let i = 0, il = data.length; i < il; i += 4) {\n        // RGBA assumed\n\n        // pixel color\n        color.setRGB(data[i] / 255, data[i + 1] / 255, data[i + 2] / 255)\n\n        // convert to linear color space\n        if ('colorSpace' in cubeRenderTarget.texture) {\n          if (cubeRenderTarget.texture.colorSpace === 'srgb') {\n            color.convertSRGBToLinear()\n          }\n        } else if (cubeRenderTarget.texture.encoding === 3001) {\n          // sRGBEncoding\n          color.convertSRGBToLinear()\n        }\n\n        // pixel coordinate on unit cube\n\n        const pixelIndex = i / 4\n\n        const col = -1 + ((pixelIndex % imageWidth) + 0.5) * pixelSize\n\n        const row = 1 - (Math.floor(pixelIndex / imageWidth) + 0.5) * pixelSize\n\n        switch (faceIndex) {\n          case 0:\n            coord.set(1, row, -col)\n            break\n\n          case 1:\n            coord.set(-1, row, col)\n            break\n\n          case 2:\n            coord.set(col, 1, -row)\n            break\n\n          case 3:\n            coord.set(col, -1, row)\n            break\n\n          case 4:\n            coord.set(col, row, 1)\n            break\n\n          case 5:\n            coord.set(-col, row, -1)\n            break\n        }\n\n        // weight assigned to this pixel\n\n        const lengthSq = coord.lengthSq()\n\n        const weight = 4 / (Math.sqrt(lengthSq) * lengthSq)\n\n        totalWeight += weight\n\n        // direction vector to this pixel\n        dir.copy(coord).normalize()\n\n        // evaluate SH basis functions in direction dir\n        SphericalHarmonics3.getBasisAt(dir, shBasis)\n\n        // accummuulate\n        for (let j = 0; j < 9; j++) {\n          shCoefficients[j].x += shBasis[j] * color.r * weight\n          shCoefficients[j].y += shBasis[j] * color.g * weight\n          shCoefficients[j].z += shBasis[j] * color.b * weight\n        }\n      }\n    }\n\n    // normalize\n    const norm = (4 * Math.PI) / totalWeight\n\n    for (let j = 0; j < 9; j++) {\n      shCoefficients[j].x *= norm\n      shCoefficients[j].y *= norm\n      shCoefficients[j].z *= norm\n    }\n\n    return new LightProbe(sh)\n  }\n}\n\nexport { LightProbeGenerator }\n"],"names":["Vector3","Color","SphericalHarmonics3","LightProbe"],"mappings":"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"}