UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

194 lines (149 loc) 5.44 kB
import { Scene as ThreeScene } from "three"; import { noop } from "../../../../../core/function/noop.js"; import { max2 } from "../../../../../core/math/max2.js"; import { ObjectPoolFactory } from "../../../../../core/model/object/ObjectPoolFactory.js"; import { ProcessState } from "../../../../../core/process/ProcessState.js"; import { EnginePlugin } from "../../../../plugin/EnginePlugin.js"; import { CompositingStages } from "../../../composit/CompositingStages.js"; import { BlendingType } from "../../../texture/sampler/BlendingType.js"; import { HighlightRenderElement } from "../renderer/HighlightRenderElement.js"; import { HighlightRenderGroup } from "../renderer/HighlightRenderGroup.js"; import { OutlineRenderer } from "../renderer/OutlineRenderer.js"; export class OutlineRenderPlugin extends EnginePlugin { constructor() { super(); this.id = "outline-renderer"; this.__renderer = new OutlineRenderer(); this.__scene = new ThreeScene(); /** * * @type {CompositLayer} * @private */ this.__compositing_layer = null; /** * * @type {HighlightRenderGroup} * @private */ this.__highlight_render_group = new HighlightRenderGroup(); /** * * @type {HighlightRenderElementSource[]} * @private */ this.__sources = []; /** * * @type {ObjectPoolFactory<HighlightRenderElement>} * @private */ this.__element_pool = new ObjectPoolFactory( () => { return new HighlightRenderElement(); }, noop, (element) => { element.definitions = []; element.object = null; } ); } /** * * @param {HighlightRenderElementSource} source * @returns {boolean} */ addSource(source) { this.__sources.push(source); return true; } /** * * @param {HighlightRenderElementSource} source * @returns {boolean} */ removeSource(source) { const i = this.__sources.indexOf(source); if (i === -1) { return false; } this.__sources.splice(i, 1); return true; } /** * * @param {number} x * @param {number} y * @private */ __set_viewport_size(x, y) { const width = max2(0, x); const height = max2(0, y); this.__renderer.resize(width, height); } /** * * @private */ __render() { const engine = this.engine; const graphics = engine.graphics; const camera = graphics.camera; // collect elements const source_count = this.__sources.length; for (let i = 0; i < source_count; i++) { const source = this.__sources[i]; source.collect(this.__element_pool, this.__highlight_render_group); } if (this.__highlight_render_group.isEmpty()) { //nothing to render this.__renderer.clearRenderTarget(); // disable rendering of compositing layer this.__compositing_layer.disable(); } else { // enabled rendering of the compositing layer this.__compositing_layer.enable(); this.__renderer.setCamera(camera); this.__renderer.render(this.__highlight_render_group); // release elements back into the object pool this.__highlight_render_group.elements.forEach(this.__element_pool.release, this.__element_pool); this.__highlight_render_group.clear(); } } async startup() { if (this.getState().getValue() === ProcessState.Running) { //already running return; } const graphics = this.engine.graphics; const viewport_size = graphics.viewport.size; viewport_size.process(this.__set_viewport_size, this); // create compositing layer this.__compositing_layer = graphics.layerComposer.createLayer(this.__renderer.__renderTargetFinal, BlendingType.MultiplyAdd); this.__compositing_layer.name = "Silhouette Outline"; this.__compositing_layer.stage = CompositingStages.POST_TRANSPARENT; graphics.on.preRender.add(this.__render, this); // set rendering resolution this.__compositing_layer.setRenderTargetScale(1); await super.startup(); } async shutdown() { const graphics = this.engine.graphics; graphics.on.preRender.remove(this.__render, this); graphics.viewport.size.onChanged.remove(this.__set_viewport_size, this); graphics.layerComposer.remove(this.__compositing_layer); await super.shutdown(); } async initialize(engine) { /** * * @type {GraphicsEngine} */ const graphicsEngine = engine.graphics; this.__renderer.setWebGLRenderer(graphicsEngine.renderer); this.__renderer.setCamera(graphicsEngine.camera); this.__renderer.setScene(this.__scene); await super.initialize(engine); } }