Buckets:
ktongue/docker_container / simsite /frontend /node_modules /three-stdlib /lights /LightProbeGenerator.js
| import { Vector3, Color, SphericalHarmonics3, LightProbe } from "three"; | |
| const LightProbeGenerator = { | |
| // https://www.ppsloan.org/publications/StupidSH36.pdf | |
| fromCubeTexture(cubeTexture) { | |
| let totalWeight = 0; | |
| const coord = new Vector3(); | |
| const dir = new Vector3(); | |
| const color = new Color(); | |
| const shBasis = [0, 0, 0, 0, 0, 0, 0, 0, 0]; | |
| const sh = new SphericalHarmonics3(); | |
| const shCoefficients = sh.coefficients; | |
| for (let faceIndex = 0; faceIndex < 6; faceIndex++) { | |
| const image = cubeTexture.image[faceIndex]; | |
| const width = image.width; | |
| const height = image.height; | |
| const canvas = document.createElement("canvas"); | |
| canvas.width = width; | |
| canvas.height = height; | |
| const context = canvas.getContext("2d"); | |
| context.drawImage(image, 0, 0, width, height); | |
| const imageData = context.getImageData(0, 0, width, height); | |
| const data = imageData.data; | |
| const imageWidth = imageData.width; | |
| const pixelSize = 2 / imageWidth; | |
| for (let i = 0, il = data.length; i < il; i += 4) { | |
| color.setRGB(data[i] / 255, data[i + 1] / 255, data[i + 2] / 255); | |
| if ("colorSpace" in cubeTexture) { | |
| if (cubeTexture.colorSpace === "srgb") { | |
| color.convertSRGBToLinear(); | |
| } | |
| } else if (cubeTexture.encoding === 3001) { | |
| color.convertSRGBToLinear(); | |
| } | |
| const pixelIndex = i / 4; | |
| const col = -1 + (pixelIndex % imageWidth + 0.5) * pixelSize; | |
| const row = 1 - (Math.floor(pixelIndex / imageWidth) + 0.5) * pixelSize; | |
| switch (faceIndex) { | |
| case 0: | |
| coord.set(-1, row, -col); | |
| break; | |
| case 1: | |
| coord.set(1, row, col); | |
| break; | |
| case 2: | |
| coord.set(-col, 1, -row); | |
| break; | |
| case 3: | |
| coord.set(-col, -1, row); | |
| break; | |
| case 4: | |
| coord.set(-col, row, 1); | |
| break; | |
| case 5: | |
| coord.set(col, row, -1); | |
| break; | |
| } | |
| const lengthSq = coord.lengthSq(); | |
| const weight = 4 / (Math.sqrt(lengthSq) * lengthSq); | |
| totalWeight += weight; | |
| dir.copy(coord).normalize(); | |
| SphericalHarmonics3.getBasisAt(dir, shBasis); | |
| for (let j = 0; j < 9; j++) { | |
| shCoefficients[j].x += shBasis[j] * color.r * weight; | |
| shCoefficients[j].y += shBasis[j] * color.g * weight; | |
| shCoefficients[j].z += shBasis[j] * color.b * weight; | |
| } | |
| } | |
| } | |
| const norm = 4 * Math.PI / totalWeight; | |
| for (let j = 0; j < 9; j++) { | |
| shCoefficients[j].x *= norm; | |
| shCoefficients[j].y *= norm; | |
| shCoefficients[j].z *= norm; | |
| } | |
| return new LightProbe(sh); | |
| }, | |
| fromCubeRenderTarget(renderer, cubeRenderTarget) { | |
| let totalWeight = 0; | |
| const coord = new Vector3(); | |
| const dir = new Vector3(); | |
| const color = new Color(); | |
| const shBasis = [0, 0, 0, 0, 0, 0, 0, 0, 0]; | |
| const sh = new SphericalHarmonics3(); | |
| const shCoefficients = sh.coefficients; | |
| for (let faceIndex = 0; faceIndex < 6; faceIndex++) { | |
| const imageWidth = cubeRenderTarget.width; | |
| const data = new Uint8Array(imageWidth * imageWidth * 4); | |
| renderer.readRenderTargetPixels(cubeRenderTarget, 0, 0, imageWidth, imageWidth, data, faceIndex); | |
| const pixelSize = 2 / imageWidth; | |
| for (let i = 0, il = data.length; i < il; i += 4) { | |
| color.setRGB(data[i] / 255, data[i + 1] / 255, data[i + 2] / 255); | |
| if ("colorSpace" in cubeRenderTarget.texture) { | |
| if (cubeRenderTarget.texture.colorSpace === "srgb") { | |
| color.convertSRGBToLinear(); | |
| } | |
| } else if (cubeRenderTarget.texture.encoding === 3001) { | |
| color.convertSRGBToLinear(); | |
| } | |
| const pixelIndex = i / 4; | |
| const col = -1 + (pixelIndex % imageWidth + 0.5) * pixelSize; | |
| const row = 1 - (Math.floor(pixelIndex / imageWidth) + 0.5) * pixelSize; | |
| switch (faceIndex) { | |
| case 0: | |
| coord.set(1, row, -col); | |
| break; | |
| case 1: | |
| coord.set(-1, row, col); | |
| break; | |
| case 2: | |
| coord.set(col, 1, -row); | |
| break; | |
| case 3: | |
| coord.set(col, -1, row); | |
| break; | |
| case 4: | |
| coord.set(col, row, 1); | |
| break; | |
| case 5: | |
| coord.set(-col, row, -1); | |
| break; | |
| } | |
| const lengthSq = coord.lengthSq(); | |
| const weight = 4 / (Math.sqrt(lengthSq) * lengthSq); | |
| totalWeight += weight; | |
| dir.copy(coord).normalize(); | |
| SphericalHarmonics3.getBasisAt(dir, shBasis); | |
| for (let j = 0; j < 9; j++) { | |
| shCoefficients[j].x += shBasis[j] * color.r * weight; | |
| shCoefficients[j].y += shBasis[j] * color.g * weight; | |
| shCoefficients[j].z += shBasis[j] * color.b * weight; | |
| } | |
| } | |
| } | |
| const norm = 4 * Math.PI / totalWeight; | |
| for (let j = 0; j < 9; j++) { | |
| shCoefficients[j].x *= norm; | |
| shCoefficients[j].y *= norm; | |
| shCoefficients[j].z *= norm; | |
| } | |
| return new LightProbe(sh); | |
| } | |
| }; | |
| export { | |
| LightProbeGenerator | |
| }; | |
| //# sourceMappingURL=LightProbeGenerator.js.map | |
Xet Storage Details
- Size:
- 5.28 kB
- Xet hash:
- 23b5dbcf05a1db6e5b75cb2fb9c48e0c14f0915d28bebdea694c66cc5eb4eefa
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.