UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

146 lines (113 loc) 4.65 kB
import { Mesh, OrthographicCamera, Scene } from "three"; import { assert } from "../../../../core/assert.js"; import { isValueBetweenInclusive } from "../../../../core/math/interval/isValueBetweenInclusive.js"; import { FULL_SCREEN_TRIANGLE_GEOMETRY } from "../../../graphics/geometry/FULL_SCREEN_TRIANGLE_GEOMETRY.js"; import { buildScreenSpaceFogOfWarShader } from "./screenSpaceFogOfWarShader.js"; /** * * @param {FogOfWar} fow * @param {function(number, number, number, number)} callback */ export function computeUvTransformFromFogOfWar(fow, callback) { const sampler = fow.sampler; const samplerWidth = sampler.width; const samplerHeight = sampler.height; const scaleX = (fow.scale * fow.size.x) * (samplerWidth / (samplerWidth - 3)); const scaleY = (fow.scale * fow.size.y) * (samplerHeight / (samplerHeight - 3)); const offsetX = 1.5 / samplerWidth; const offsetY = 1.5 / samplerHeight; callback(offsetX, offsetY, 1 / scaleX, 1 / scaleY); } export class FogOfWarRenderer { constructor() { /** * * @type {ShaderMaterial} */ this.material = buildScreenSpaceFogOfWarShader(); this.quad = new Mesh(FULL_SCREEN_TRIANGLE_GEOMETRY, this.material); this.camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1); this.scene = new Scene(); this.scene.add(this.quad); } /** * * @param {FogOfWar} fow */ setUvTransformFromFog(fow) { computeUvTransformFromFogOfWar(fow, (offsetX, offsetY, scaleX, scaleY) => { this.setUvTransform(offsetX, offsetY, scaleX, scaleY); }); } /** * * @param {number} offsetX UV u offset, between 0 and 1 * @param {number} offsetY UV v offset, between 0 and 1 * @param {number} scaleX Transform scale from world coordinate position to UV u coordinate, minus offsetX * @param {number} scaleY Transform scale from world coordinate position to UV v coordinate, minus offsetY */ setUvTransform(offsetX, offsetY, scaleX, scaleY) { assert.isNumber(offsetX, 'offsetX'); assert.notNaN(offsetX, 'offsetX'); assert.ok(isValueBetweenInclusive(offsetX, 0, 1), `expected offsetX to be between 0 and 1, instead was '${offsetX}'`); assert.isNumber(offsetY, 'offsetY'); assert.notNaN(offsetY, 'offsetY'); assert.ok(isValueBetweenInclusive(offsetY, 0, 1), `expected offsetY to be between 0 and 1, instead was '${offsetY}'`); assert.isNumber(scaleX, 'scaleX'); assert.notNaN(scaleX, 'scaleX'); assert.isFiniteNumber(scaleX, 'scaleX'); assert.isNumber(scaleY, 'scaleY'); assert.notNaN(scaleY, 'scaleY'); assert.isFiniteNumber(scaleY, 'scaleY'); this.material.uniforms.uFogUvTransform.value.set(offsetX, offsetY, scaleX, scaleY); } /** * * @param {Texture} texture */ setDepthBuffer(texture) { // assert.equal(texture.type, UnsignedShortType, `expected texture type to be UnsignedShort(=${UnsignedShortType}), instead got something else (=${texture.type})`) this.material.uniforms.tDepth.value = texture; } /** * * @param {Texture} buffer */ setFogBuffer(buffer) { this.material.uniforms.tFog.value = buffer; } /** * Resolution of the fog texture * @param {number} x * @param {number} y */ setResolution(x, y) { this.material.uniforms.uResolution.value.set(x, y); } /** * * @param {Vector4} color */ setFogColor(color) { this.material.uniforms.uColor.value.copy(color); } /** * * @param {WebGLRenderer} renderer * @param {PerspectiveCamera|OrthographicCamera} camera * @param {Scene} scene * @param {WebGLRenderTarget} target */ render(renderer, camera, scene, target) { assert.ok(camera.isCamera, 'Not a camera'); assert.ok(camera.isPerspectiveCamera || camera.isOrthographicCamera, 'Unsupported Camera type. Expected PerspectiveCamera or OrthographicCamera'); //set up uniforms const uniforms = this.material.uniforms; uniforms.uProjectionInverse.value.copy(camera.projectionMatrixInverse); uniforms.uViewInverse.value.copy(camera.matrixWorld); renderer.setRenderTarget(target); renderer.clearColor(); renderer.render(this.scene, this.camera); renderer.setRenderTarget(null); } }