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