UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

238 lines (184 loc) 5.24 kB
import { LinearFilter, OrthographicCamera, RGBAFormat, Scene, WebGLMultisampleRenderTarget, WebGLRenderTarget } from 'three'; import { assert } from "../../../core/assert.js"; import Vector2 from "../../../core/geom/Vector2.js"; import { BlendingType } from "../texture/sampler/BlendingType.js"; import { CompositLayer } from "./CompositLayer.js"; class LayerCompositer { constructor() { /** * * @type {CompositLayer[]} */ this.layerTargets = []; // this.camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1); this.scene = new Scene(); this.size = new Vector2(0, 0); /** * @private * @type {number} */ this.__pixelRatio = 1; } /** * * @param {CompositLayer} layer * @returns {boolean} */ remove(layer) { const i = this.layerTargets.indexOf(layer); if (i === -1) { // not found return false; } this.layerTargets.splice(i, 1); // cleanup memory layer.renderTarget.dispose(); return true; } /** * * @param param * @param {BlendingType} blending * @return {CompositLayer} */ createLayer(param, blending = BlendingType.Normal) { let renderTarget; if (param instanceof WebGLRenderTarget || param instanceof WebGLMultisampleRenderTarget) { // A render target was specified renderTarget = param; } else { const renderTargetParameters = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat, depthBuffer: false, stencilBuffer: false, generateMipmaps: false }; for (let p in param) { if (param.hasOwnProperty(p)) { renderTargetParameters[p] = param[p]; } } renderTarget = new WebGLMultisampleRenderTarget(1, 1, renderTargetParameters); } const layer = new CompositLayer({ renderTarget, blending }); this.addLayer(layer); return layer; } /** * * @param {CompositLayer} layer * @returns {boolean} */ addLayer(layer) { if (this.layerTargets.includes(layer)) { // already added return false; } layer.setSize(this.size.x, this.size.y); this.layerTargets.push(layer); return true; } /** * @returns {boolean} */ hasActiveLayers() { const layerTargets = this.layerTargets; const n = layerTargets.length; for (let i = 0; i < n; i++) { const layer = layerTargets[i]; if (layer.enabled) { return true; } } return false; } /** * * @param {number} stage * @private */ __prepare_scene_for_stage(stage) { const layers = this.layerTargets; const layer_count = layers.length; const scene = this.scene; let child_count = 0; for (let i = 0; i < layer_count; i++) { const layer = layers[i]; if (layer.stage !== stage) { continue; } scene.children[child_count++] = layer.object; layer.on.preRender.send0(); } scene.children.length = child_count; } /** * * @param {THREE.WebGLRenderer} renderer * @param {number} stage */ composite(renderer, stage) { assert.isNonNegativeInteger(stage, 'stage'); if (!this.hasActiveLayers()) { return; } this.__prepare_scene_for_stage(stage); const camera = this.camera; const scene = this.scene; renderer.autoClear = false; renderer.render(scene, camera); } /** * * @param {number} value */ setPixelRatio(value) { if (this.__pixelRatio === value) { return; } assert.greaterThanOrEqual(value, 0, 'value'); this.__pixelRatio = value; this.__updateResolution(); } /** * * @returns {number} */ getPixelRatio() { return this.__pixelRatio; } __updateResolution() { const x = this.size.x; const y = this.size.y; const h = y * this.__pixelRatio; const w = x * this.__pixelRatio; const layerTargets = this.layerTargets; for (let i = 0; i < layerTargets.length; i++) { const layerTarget = layerTargets[i]; layerTarget.setSize(w, h); } } /** * * @param {number} x * @param {number} y */ setSize(x, y) { this.size.set(x, y); this.__updateResolution(x, y); } } export default LayerCompositer;