whs
Version:
Super-fast 3D framework for Web Applications & Games. Based on Three.js
173 lines (143 loc) • 4.2 kB
JavaScript
import {EffectComposer} from 'postprocessing/src/core/EffectComposer';
import {RenderPass} from 'postprocessing/src/passes/RenderPass';
import {ShaderPass} from 'postprocessing/src/passes/ShaderPass';
import {Loop} from '../../core/Loop';
const polyfill = (object, method, showWarn = true) => {
if (object[method]) return;
if (showWarn) console.warn(`: pass.${method}() was not found.`, object);
object[method] = () => {};
};
/**
* @class PostProcessorModule
* @category modules/app
* @param {Object} [params]
* @memberof module:modules/app
* @example <caption> Creating a rendering module and passing it to App's modules</caption>
* new App([
* new ElementModule(),
* new SceneModule(),
* new DefineModule('camera', new WHS.PerspectiveCamera({
* position: new THREE.Vector3(0, 6, 18),
* far: 10000
* })),
* new RenderingModule(),
* new PostProcessorModule()
* ]);
*
* const processor = app.use('postprocessor');
*
* processor
* .render()
* .pass(new GlitchPass())
* .renderToScreen()
*/
export class PostProcessorModule {
currentPass = null;
defer = new Promise(resolve => {
this.resolve = resolve;
});
static defaults = {
debug: true
};
constructor(params = PostProcessorModule.defaults) {
this.debug = params.debug;
this.params = params;
}
manager(manager) {
manager.define('postprocessor');
this.effects = manager.use('rendering').effects;
this.renderer = manager.get('renderer');
this.scene = manager.get('scene');
this.camera = manager.get('camera');
this.composer = new EffectComposer(this.renderer, this.params);
manager.use('rendering').stop();
const composer = this.composer;
this.renderLoop = new Loop(clock => composer.render(clock.getDelta())).start(manager.handler);
manager.update({
renderer: renderer => {
this.composer.replaceRenderer(renderer);
},
scene: scene => {
this.scene = scene;
},
camera: camera => {
this.camera = camera;
}
});
this.resolve();
}
/**
* @method render
* @description Adds RenderPass
* @return {this}
* @memberof module:modules/app.PostProcessorModule
*/
render() {
this.defer.then(() => {
const pass = new RenderPass(this.scene, this.camera.native);
// TODO: Support for effects.
this.composer.addPass(pass);
this.currentPass = pass;
});
return this;
}
/**
* @method pass
* @description Adds your custom pass
* @param {Pass} pass A custom pass
* @return {this}
* @memberof module:modules/app.PostProcessorModule
*/
pass(pass) {
this.defer.then(() => {
polyfill(pass, 'setSize', this.debug);
polyfill(pass, 'initialise', this.debug);
this.composer.addPass(pass);
this.currentPass = pass;
});
return this;
}
/**
* @method shader
* @description Adds a pass made from shader material
* @param {Material} material A ShaderMaterial
* @param {String} textureID Name of the readBuffer uniform
* @return {this}
* @memberof module:modules/app.PostProcessorModule
*/
shader(material, textureID = 'readBuffer') {
this.defer.then(() => {
if (!material.uniforms[textureID])
material.uniforms[textureID] = {value: null};
const pass = new ShaderPass(material, textureID);
this.composer.addPass(pass);
this.currentPass = pass;
});
return this;
}
/**
* @method get
* @description Returns a pass by the given name
* @param {String} name The name of the pass
* @return {this}
* @memberof module:modules/app.PostProcessorModule
*/
get(name) {
return name
? this.composer.passes.filter(pass => pass.name === name)[0]
: this.currentPass;
}
/**
* @method renderToScreen
* @description Sets the renderToScreen property of currentPass
* @param {String} [name=true] The name of the pass
* @return {this}
* @memberof module:modules/app.PostProcessorModule
*/
renderToScreen(bool = true) {
this.defer.then(() => {
this.currentPass.renderToScreen = bool;
});
return this;
}
}