@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
66 lines (49 loc) • 2.22 kB
JavaScript
import { max2 } from "../../../core/math/max2.js";
import { min2 } from "../../../core/math/min2.js";
import { Sampler2D } from '../../graphics/texture/sampler/Sampler2D.js';
/**
* Uses sobel filter to compute normals for a given height map
* @param {Sampler2D} heightSampler
* @return {Sampler2D}
*/
export function convertHeightMap2NormalMap(heightSampler) {
//
const height = heightSampler.height;
const width = heightSampler.width;
const heightData = heightSampler.data;
const data = new Float32Array(width * height * 3);
const maxY = height - 1;
const maxX = width - 1;
for (let y = 0; y < height; y++) {
const rowIndex = y * width;
const rowIndexTop = max2(y - 1, 0) * width;
const rowIndexBottom = min2(y + 1, maxY) * width;
for (let x = 0; x < width; x++) {
const i = rowIndex + x;
const j = i * 3;
const columnLeft = max2(x - 1, 0);
const columnRight = min2(x + 1, maxX);
// read surrounding points
const topLeft = heightData[rowIndexTop + columnLeft];
const top = heightData[rowIndexTop + x];
const topRight = heightData[rowIndexTop + columnRight];
const left = heightData[rowIndex + columnLeft];
const right = heightData[rowIndex + columnRight];
const bottomLeft = heightData[rowIndexBottom + columnLeft];
const bottom = heightData[rowIndexBottom + x];
const bottomRight = heightData[rowIndexBottom + columnRight];
//
const dX = (topRight + 2.0 * right + bottomRight) - (topLeft + 2.0 * left + bottomLeft);
const dY = (bottomLeft + 2.0 * bottom + bottomRight) - (topLeft + 2.0 * top + topRight);
//normalize vector
const magnitude = Math.sqrt(dX * dX + dY * dY + 0.25);
const _x = dX / magnitude;
const _y = dY / magnitude;
const _z = 0.5 / magnitude;
data[j] = _x;
data[j + 1] = _y;
data[j + 2] = _z;
}
}
return new Sampler2D(data, 3, width, height);
}