UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

83 lines (64 loc) 2.65 kB
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;