@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
83 lines (64 loc) • 2.65 kB
JavaScript
import { ClampToEdgeWrapping, DataTexture, RGBAFormat, UnsignedByteType, Vector2 } from 'three';
import ImageFilter from '../../graphics/filter/ImageFilter.js';
import AmbientOcclusionShader from '../../graphics/shaders/AmbientOcclusionShader.js';
import { DenoiseShader } from "../../graphics/shaders/DenoiseShader.js";
import { Sampler2D } from '../../graphics/texture/sampler/Sampler2D.js';
import { sampler2d_to_float32_texture } from "../../graphics/texture/sampler/sampler2d_to_float32_texture.js";
function filterResult2Texture(data, width, height) {
const result = new DataTexture();
result.format = RGBAFormat;
result.type = UnsignedByteType;
result.flipY = false;
result.image = { data: data, width: width, height: height };
result.wrapS = ClampToEdgeWrapping;
result.wrapT = ClampToEdgeWrapping;
result.repeat.set(1, 1);
result.needsUpdate = true;
result.anisotropy = 4;
return result;
}
/**
*
* @param {WebGLRenderer} renderer
* @param {Sampler2D} heightMap
* @param {Sampler2D} normalMap
* @param {Vector2} resultSize
* @param worldSize
* @param {number} [rayLength]
* @returns {Sampler2D}
*/
function normalMap2OcclusionMap(
renderer,
heightMap,
normalMap,
resultSize,
worldSize = new Vector2(heightMap.width, heightMap.width),
rayLength = 17
) {
const width = resultSize.x;
const height = resultSize.y;
//
const normalTexture = sampler2d_to_float32_texture(normalMap);
const heightTexture = sampler2d_to_float32_texture(heightMap);
//construct shader
const shaderAO = new AmbientOcclusionShader();
shaderAO.uniforms.heightMap.value = heightTexture;
shaderAO.uniforms.normalMap.value = normalTexture;
shaderAO.uniforms.world_size.value.set(worldSize.x, worldSize.y);
shaderAO.uniforms.rayLength.value = rayLength;
//perform filtering
const rawAO = ImageFilter(renderer, width, height, shaderAO);
const shaderDenoise = new DenoiseShader(2);
shaderDenoise.uniforms.source.value = filterResult2Texture(rawAO.array, width, height);
shaderDenoise.uniforms.pixelOffset.value.set(1 / width, 1 / height);
const smoothAO = ImageFilter(renderer, width, height, shaderDenoise);
//create the sampler
const result = new Sampler2D(new Uint8ClampedArray(width * height), 1, width, height);
//populate samples
const size = width * height;
for (let i = 0; i < size; i++) {
result.data[i] = smoothAO.array[i * 4];
}
return result;
}
export default normalMap2OcclusionMap;