@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
194 lines (149 loc) • 5.44 kB
JavaScript
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);
}
}