UNPKG

oxygen-core

Version:

Oxygen game engine (Xenon Core for browsers)

415 lines (342 loc) 9.26 kB
import Component from '../systems/EntitySystem/Component'; import { Command, Pipeline, RenderFullscreenCommand } from '../systems/RenderSystem'; import Camera from './Camera'; export class DeferredPipeline extends Command { get gBufferId() { return this._gBufferId; } set gBufferId(value) { if (typeof value !== 'string') { throw new Error('`value` is not type of String!'); } this._gBufferId = value; this._dirty = true; } get lBufferId() { return this._lBufferId; } set lBufferId(value) { if (typeof value !== 'string') { throw new Error('`value` is not type of String!'); } this._lBufferId = value; this._dirty = true; } get gBufferTargets() { return this._gBufferTargets; } set gBufferTargets(value) { if (typeof value === 'number') { this._gBufferTargets = value | 0; } else if (Array.isArray(value)) { this._gBufferTargets = value; } else { throw new Error('`value` is not type of either Number or Array!'); } this._dirty = true; } get lBufferTargets() { return this._lBufferTargets; } set lBufferTargets(value) { if (typeof value === 'number') { this._lBufferTargets = value | 0; } else if (Array.isArray(value)) { this._lBufferTargets = value; } else { throw new Error('`value` is not type of either Number or Array!'); } this._dirty = true; } get gBufferLayer() { return this._gBufferLayer; } set gBufferLayer(value) { if (!value) { this._gBufferLayer = null; return; } if (typeof value !== 'string') { throw new Error('`value` is not type of String!'); } this._gBufferLayer = value; } get lBufferLayer() { return this._lBufferLayer; } set lBufferLayer(value) { if (!value) { this._lBufferLayer = null; return; } if (typeof value !== 'string') { throw new Error('`value` is not type of String!'); } this._lBufferLayer = value; } get fullscreen() { return this._fullscreen; } constructor(owner) { super(); this._owner = owner; this._renderer = null; this._gBuffer = null; this._lBuffer = null; this._gBufferId = '#deferred-g-buffer'; this._lBufferId = '#deferred-l-buffer'; this._gBufferIdUsed = null; this._lBufferIdUsed = null; this._gBufferTargets = 2; this._lBufferTargets = 2; this._gBufferLayer = 'g-buffer'; this._lBufferLayer = 'l-buffer'; this._fullscreen = new RenderFullscreenCommand(); this._dirty = true; } dispose() { super.dispose(); const { _renderer, _gBufferIdUsed, _lBufferIdUsed, _fullscreen } = this; if (!!_renderer) { if (!!_gBufferIdUsed) { _renderer.unregisterRenderTarget(_gBufferIdUsed); } if (!!_lBufferIdUsed) { _renderer.unregisterRenderTarget(_lBufferIdUsed); } } if (!!_fullscreen) { _fullscreen.dispose(); } this._owner = null; this._renderer = null; this._gBufferId = null; this._lBufferId = null; this._gBufferIdUsed = null; this._lBufferIdUsed = null; this._gBufferLayer = null; this._lBufferLayer = null; this._fullscreen = null; } onRender(gl, renderer, deltaTime, layer) { this._ensureState(renderer); const { _owner, _gBufferLayer, _lBufferLayer } = this; const { captureEntity, entity } = _owner; const target = !!captureEntity ? entity.findEntity(captureEntity) : entity; const rtt = renderer.activeRenderTarget; if (!!_gBufferLayer) { renderer.enableRenderTarget(this._gBufferIdUsed); target.performAction('render-layer', gl, renderer, deltaTime, _gBufferLayer); renderer.disableRenderTarget(); } if (!!_lBufferLayer) { renderer.enableRenderTarget(this._lBufferIdUsed); target.performAction('render-layer', gl, renderer, deltaTime, _lBufferLayer); renderer.disableRenderTarget(); } if (!!rtt) { renderer.enableRenderTarget(rtt, false); } this._fullscreen.onRender(gl, renderer, deltaTime, layer); } onResize(width, height) { this._dirty = true; } _ensureState(renderer) { if (!this._dirty) { return; } const { _gBufferId, _lBufferId } = this; if (!_gBufferId) { throw new Error('`gBufferId` cannot be null!'); } if (!_lBufferId) { throw new Error('`lBufferId` cannot be null!'); } if (!!this._gBufferIdUsed) { renderer.unregisterRenderTarget(this._gBufferIdUsed); } this._gBufferIdUsed = this._gBufferId; renderer.registerRenderTargetMulti( this._gBufferIdUsed, renderer.canvas.width, renderer.canvas.height, this._gBufferTargets ); if (!!this._lBufferIdUsed) { renderer.unregisterRenderTarget(this._lBufferIdUsed); } this._lBufferIdUsed = this._lBufferId; renderer.registerRenderTarget( this._lBufferIdUsed, renderer.canvas.width, renderer.canvas.height, this._lBufferTargets ); this._renderer = renderer; this._dirty = false; } } /** * Deferred pipeline renderer. */ export default class DeferredRenderer extends Component { static get propsTypes() { return { shader: 'string_null', overrideUniforms: 'map(any)', overrideSamplers: 'map(any)', gBufferId: 'string', lBufferid: 'string', gBufferTargets: 'number|array(any)', lBufferTargets: 'number|array(any)', gBufferLayer: 'string_null', lBufferLayer: 'string_null' }; } static factory() { return new DeferredRenderer(); } /** @type {String|null} */ get shader() { return this._pipeline.fullscreen.shader; } /** @type {String|null} */ set shader(value) { this._pipeline.fullscreen.shader = value; } /** @type {*} */ get overrideUniforms() { const { fullscreen } = this._pipeline; const result = {}; for (const [key, value] of fullscreen.overrideUniforms) { result[key] = value; } return result; } /** @type {*} */ set overrideUniforms(value) { const { overrideUniforms } = this._pipeline.fullscreen; overrideUniforms.clear(); if (!value) { return; } for (const name in value) { overrideUniforms.set(name, value[name]); } } /** @type {*} */ get overrideSamplers() { const { fullscreen } = this._pipeline; const result = {}; for (const [key, value] of fullscreen.overrideSamplers) { result[key] = value; } return result; } /** @type {*} */ set overrideSamplers(value) { const { overrideSamplers } = this._pipeline.fullscreen; overrideSamplers.clear(); if (!value) { return; } for (const name in value) { overrideSamplers.set(name, value[name]); } } /** @type {String} */ get gBufferId() { return this._pipeline.gBufferId; } /** @type {String} */ set gBufferId(value) { this._pipeline.gBufferId = value; } /** @type {String} */ get lBufferId() { return this._pipeline.lBufferId; } /** @type {String} */ set lBufferId(value) { this._pipeline.lBufferId = value; } /** @type {Number} */ get gBufferTargets() { return this._pipeline.gBufferTargets; } /** @type {Number} */ set gBufferTargets(value) { this._pipeline.gBufferTargets = value; } /** @type {Number} */ get lBufferTargets() { return this._pipeline.lBufferTargets; } /** @type {Number} */ set lBufferTargets(value) { this._pipeline.lBufferTargets = value; } /** @type {String|null} */ get gBufferLayer() { return this._pipeline.gBufferLayer; } /** @type {String|null} */ set gBufferLayer(value) { this._pipeline.gBufferLayer = value; } /** @type {String|null} */ get lBufferLayer() { return this._pipeline.lBufferLayer; } /** @type {String|null} */ set lBufferLayer(value) { this._pipeline.lBufferLayer = value; } get gBuffer() { return this._pipeline.gBuffer; } get lBuffer() { return this._pipeline.lBuffer; } /** * Constructor. */ constructor() { super(); this._camera = null; this._pipeline = new DeferredPipeline(this); } /** * @override */ dispose() { if (!!this._pipeline) { this._pipeline.dispose(); this._pipeline = null; } this._camera = null; super.dispose(); } /** * @override */ onAttach() { const camera = this._camera = this.entity.getComponent(Camera); if (!camera) { throw new Error('There is no component of Camera type!'); } camera.command = this._pipeline; } /** * @override */ onDetach() { if (!!this._camera) { this._camera.command = null; this._camera = null; } } }