@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
73 lines (60 loc) • 1.97 kB
JavaScript
import ImageFilter from '../../graphics/filter/ImageFilter.js';
import NormalMapShader from '../../graphics/shaders/NormalMapShader2.js';
import { Sampler2D } from '../../graphics/texture/sampler/Sampler2D.js';
import { sampler2d_to_float32_texture } from "../../graphics/texture/sampler/sampler2d_to_float32_texture.js";
function convertChannel(v) {
return (v) / 255 - 0.5;
}
/**
*
* @param {number[]|Uint8Array} source
* @returns {Float32Array}
*/
function rgbaArray2RGB(source) {
const length = source.length;
const numPixels = Math.floor(length / 4);
const target = new Float32Array(numPixels * 3);
//
let h;
for (let i = 0; i < numPixels; i++) {
const j = i * 4;
const k = i * 3;
//normalize source to normal vectors
let x = convertChannel(source[j]);
let y = convertChannel(source[j + 1]);
let z = convertChannel(source[j + 2]);
//
h = Math.sqrt(x * x + y * y + z * z);
x /= h;
y /= h;
z /= h;
//
target[k] = x;
target[k + 1] = y;
target[k + 2] = z;
}
return target;
}
/**
*
* @param {WebGLRenderer} renderer
* @param {Sampler2D} sampler
* @returns {Sampler2D}
*/
function heightMap2NormalMap(renderer, sampler) {
const width = sampler.width;
const height = sampler.height;
const texture = sampler2d_to_float32_texture(sampler);
//construct shader
const shader = new NormalMapShader();
shader.uniforms.heightMap.value = texture;
shader.uniforms.resolution.value.set(width, height);
//perform filtering
const result = ImageFilter(renderer, width, height, shader);
//create the sampler
const array = result.array;
const rgb = rgbaArray2RGB(array);
//reduce array's alpha component
return new Sampler2D(rgb, 3, width, height);
}
export default heightMap2NormalMap;