UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

143 lines (142 loc) 4.33 kB
import Texture from "../Texture.mjs"; import FrameBuffer from "../FrameBuffer.mjs"; import Texture2D from "../Texture2D.mjs"; import vendor from "../core/vendor.mjs"; import Skybox from "../plugin/Skybox.mjs"; import EnvironmentMapPass from "../prePass/EnvironmentMap.mjs"; import Scene from "../Scene.mjs"; import vec3 from "../glmatrix/vec3.mjs"; var sh = {}; var targets = ["px", "nx", "py", "ny", "pz", "nz"]; function harmonics(normal, index) { var x = normal[0]; var y = normal[1]; var z = normal[2]; if (index === 0) { return 1; } else if (index === 1) { return x; } else if (index === 2) { return y; } else if (index === 3) { return z; } else if (index === 4) { return x * z; } else if (index === 5) { return y * z; } else if (index === 6) { return x * y; } else if (index === 7) { return 3 * z * z - 1; } else { return x * x - y * y; } } var normalTransform = { px: [2, 1, 0, -1, -1, 1], nx: [2, 1, 0, 1, -1, -1], py: [0, 2, 1, 1, -1, -1], ny: [0, 2, 1, 1, 1, 1], pz: [0, 1, 2, -1, -1, -1], nz: [0, 1, 2, 1, -1, 1] }; function projectEnvironmentMapCPU(renderer, cubePixels, width, height) { var coeff = new vendor.Float32Array(9 * 3); var normal = vec3.create(); var texel = vec3.create(); var fetchNormal = vec3.create(); for (var m = 0; m < 9; m++) { var result = vec3.create(); for (var k = 0; k < targets.length; k++) { var pixels = cubePixels[targets[k]]; var sideResult = vec3.create(); var divider = 0; var i = 0; var transform = normalTransform[targets[k]]; for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { normal[0] = x / (width - 1) * 2 - 1; normal[1] = y / (height - 1) * 2 - 1; normal[2] = -1; vec3.normalize(normal, normal); fetchNormal[0] = normal[transform[0]] * transform[3]; fetchNormal[1] = normal[transform[1]] * transform[4]; fetchNormal[2] = normal[transform[2]] * transform[5]; texel[0] = pixels[i++] / 255; texel[1] = pixels[i++] / 255; texel[2] = pixels[i++] / 255; var scale = pixels[i++] / 255 * 8.12; texel[0] *= scale; texel[1] *= scale; texel[2] *= scale; vec3.scaleAndAdd(sideResult, sideResult, texel, harmonics(fetchNormal, m) * -normal[2]); divider += -normal[2]; } } vec3.scaleAndAdd(result, result, sideResult, 1 / divider); } coeff[m * 3] = result[0] / 6; coeff[m * 3 + 1] = result[1] / 6; coeff[m * 3 + 2] = result[2] / 6; } return coeff; } sh.projectEnvironmentMap = function(renderer, envMap, opts) { opts = opts || {}; opts.lod = opts.lod || 0; var skybox; var dummyScene = new Scene(); var size = 64; if (envMap.textureType === "texture2D") { skybox = new Skybox({ scene: dummyScene, environmentMap: envMap }); } else { size = envMap.image && envMap.image.px ? envMap.image.px.width : envMap.width; skybox = new Skybox({ scene: dummyScene, environmentMap: envMap }); } var width = Math.ceil(size / Math.pow(2, opts.lod)); var height = Math.ceil(size / Math.pow(2, opts.lod)); var rgbmTexture = new Texture2D({ width, height }); var framebuffer = new FrameBuffer(); skybox.material.define("fragment", "RGBM_ENCODE"); if (opts.decodeRGBM) { skybox.material.define("fragment", "RGBM_DECODE"); } skybox.material.set("lod", opts.lod); var envMapPass = new EnvironmentMapPass({ texture: rgbmTexture }); var cubePixels = {}; for (var i = 0; i < targets.length; i++) { cubePixels[targets[i]] = new Uint8Array(width * height * 4); var camera = envMapPass.getCamera(targets[i]); camera.fov = 90; framebuffer.attach(rgbmTexture); framebuffer.bind(renderer); renderer.render(dummyScene, camera); renderer.gl.readPixels( 0, 0, width, height, Texture.RGBA, Texture.UNSIGNED_BYTE, cubePixels[targets[i]] ); framebuffer.unbind(renderer); } skybox.dispose(renderer); framebuffer.dispose(renderer); rgbmTexture.dispose(renderer); return projectEnvironmentMapCPU(renderer, cubePixels, width, height); }; var shUtil = sh; export { shUtil as default };