cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
143 lines (142 loc) • 4.33 kB
JavaScript
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 };