2016-02-29 23:04:07 +00:00
|
|
|
import EventEmitter from 'eventemitter3';
|
|
|
|
import THREE from 'three';
|
|
|
|
import Scene from './Scene';
|
2016-03-03 17:05:06 +00:00
|
|
|
import DOMScene3D from './DOMScene3D';
|
|
|
|
import DOMScene2D from './DOMScene2D';
|
2016-02-29 23:04:07 +00:00
|
|
|
import Renderer from './Renderer';
|
2016-03-03 17:05:06 +00:00
|
|
|
import DOMRenderer3D from './DOMRenderer3D';
|
|
|
|
import DOMRenderer2D from './DOMRenderer2D';
|
2016-02-29 23:04:07 +00:00
|
|
|
import Camera from './Camera';
|
|
|
|
import Picking from './Picking';
|
2016-03-11 18:10:36 +00:00
|
|
|
import EffectComposer from './EffectComposer';
|
2016-03-11 11:38:08 +00:00
|
|
|
import RenderPass from '../vendor/RenderPass';
|
2016-03-11 12:01:34 +00:00
|
|
|
import ShaderPass from '../vendor/ShaderPass';
|
|
|
|
import CopyShader from '../vendor/CopyShader';
|
|
|
|
import HorizontalTiltShiftShader from '../vendor/HorizontalTiltShiftShader';
|
|
|
|
import VerticalTiltShiftShader from '../vendor/VerticalTiltShiftShader';
|
2016-03-11 12:43:50 +00:00
|
|
|
import FXAAShader from '../vendor/FXAAShader';
|
2016-02-29 23:04:07 +00:00
|
|
|
|
|
|
|
class Engine extends EventEmitter {
|
|
|
|
constructor(container, world) {
|
|
|
|
console.log('Init Engine');
|
|
|
|
|
|
|
|
super();
|
|
|
|
|
|
|
|
this._world = world;
|
2016-03-03 17:05:06 +00:00
|
|
|
|
2016-02-29 23:04:07 +00:00
|
|
|
this._scene = Scene;
|
2016-03-03 17:05:06 +00:00
|
|
|
this._domScene3D = DOMScene3D;
|
|
|
|
this._domScene2D = DOMScene2D;
|
|
|
|
|
2016-03-11 18:10:36 +00:00
|
|
|
var antialias = (this._world.options.postProcessing) ? false : true;
|
|
|
|
this._renderer = Renderer(container, antialias);
|
2016-03-03 17:05:06 +00:00
|
|
|
this._domRenderer3D = DOMRenderer3D(container);
|
|
|
|
this._domRenderer2D = DOMRenderer2D(container);
|
|
|
|
|
2016-02-29 23:04:07 +00:00
|
|
|
this._camera = Camera(container);
|
|
|
|
|
2016-03-11 18:10:36 +00:00
|
|
|
this._container = container;
|
|
|
|
|
2016-02-29 23:04:07 +00:00
|
|
|
// TODO: Make this optional
|
|
|
|
this._picking = Picking(this._world, this._renderer, this._camera);
|
|
|
|
|
|
|
|
this.clock = new THREE.Clock();
|
|
|
|
|
|
|
|
this._frustum = new THREE.Frustum();
|
2016-03-11 11:38:08 +00:00
|
|
|
|
2016-03-11 18:10:36 +00:00
|
|
|
if (this._world.options.postProcessing) {
|
|
|
|
this._initPostProcessing();
|
|
|
|
}
|
2016-03-11 11:38:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Set up composer to automatically resize on viewport change
|
2016-03-11 12:43:50 +00:00
|
|
|
// TODO: Update passes that rely on width / height on resize
|
2016-03-11 14:16:35 +00:00
|
|
|
// TODO: Merge default passes into a single shader / pass for performance
|
2016-03-11 11:38:08 +00:00
|
|
|
_initPostProcessing() {
|
|
|
|
var renderPass = new RenderPass(this._scene, this._camera);
|
|
|
|
|
2016-03-11 12:43:50 +00:00
|
|
|
// TODO: Look at using @mattdesl's optimised FXAA shader
|
|
|
|
// https://github.com/mattdesl/three-shader-fxaa
|
|
|
|
var fxaaPass = new ShaderPass(FXAAShader);
|
|
|
|
|
|
|
|
var hblurPass = new ShaderPass(HorizontalTiltShiftShader);
|
|
|
|
var vblurPass = new ShaderPass(VerticalTiltShiftShader);
|
2016-03-11 12:01:34 +00:00
|
|
|
var bluriness = 5;
|
2016-03-11 11:38:08 +00:00
|
|
|
|
2016-03-11 12:43:50 +00:00
|
|
|
hblurPass.uniforms.r.value = vblurPass.uniforms.r.value = 0.6;
|
2016-03-11 12:01:34 +00:00
|
|
|
|
|
|
|
var copyPass = new ShaderPass(CopyShader);
|
|
|
|
copyPass.renderToScreen = true;
|
2016-03-11 11:38:08 +00:00
|
|
|
|
2016-03-11 18:10:36 +00:00
|
|
|
this._composer = EffectComposer(this._renderer, this._container);
|
2016-03-11 11:38:08 +00:00
|
|
|
|
|
|
|
this._composer.addPass(renderPass);
|
2016-03-11 12:43:50 +00:00
|
|
|
this._composer.addPass(fxaaPass);
|
|
|
|
this._composer.addPass(hblurPass);
|
|
|
|
this._composer.addPass(vblurPass);
|
2016-03-11 12:01:34 +00:00
|
|
|
this._composer.addPass(copyPass);
|
2016-03-11 18:10:36 +00:00
|
|
|
|
|
|
|
var self = this;
|
|
|
|
var updatePostProcessingSize = function() {
|
|
|
|
var width = self._container.clientWidth;
|
|
|
|
var height = self._container.clientHeight;
|
|
|
|
|
2016-03-22 10:55:31 +00:00
|
|
|
// TODO: Re-enable this when perf issues can be solved
|
|
|
|
//
|
|
|
|
// Rendering double the resolution of the screen can be really slow
|
|
|
|
// var pixelRatio = window.devicePixelRatio;
|
|
|
|
var pixelRatio = 1;
|
2016-03-11 18:10:36 +00:00
|
|
|
|
|
|
|
fxaaPass.uniforms.resolution.value.set(1 / (width * pixelRatio), 1 / (height * pixelRatio));
|
|
|
|
|
|
|
|
hblurPass.uniforms.h.value = bluriness / (width * pixelRatio);
|
|
|
|
vblurPass.uniforms.v.value = bluriness / (height * pixelRatio);
|
|
|
|
};
|
|
|
|
|
|
|
|
updatePostProcessingSize();
|
|
|
|
window.addEventListener('resize', updatePostProcessingSize, false);
|
2016-02-29 23:04:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
update(delta) {
|
|
|
|
this.emit('preRender');
|
|
|
|
|
2016-03-11 18:10:36 +00:00
|
|
|
if (this._world.options.postProcessing) {
|
|
|
|
this._composer.render(delta);
|
|
|
|
} else {
|
|
|
|
this._renderer.render(this._scene, this._camera);
|
|
|
|
}
|
2016-02-29 23:04:07 +00:00
|
|
|
|
|
|
|
// Render picking scene
|
|
|
|
// this._renderer.render(this._picking._pickingScene, this._camera);
|
|
|
|
|
2016-03-03 17:05:06 +00:00
|
|
|
// Render DOM scenes
|
|
|
|
this._domRenderer3D.render(this._domScene3D, this._camera);
|
|
|
|
this._domRenderer2D.render(this._domScene2D, this._camera);
|
|
|
|
|
2016-02-29 23:04:07 +00:00
|
|
|
this.emit('postRender');
|
|
|
|
}
|
|
|
|
|
|
|
|
destroy() {
|
|
|
|
// Remove any remaining objects from scene
|
|
|
|
var child;
|
2016-03-03 17:05:06 +00:00
|
|
|
for (var i = this._scene.children.length - 1; i >= 0; i--) {
|
2016-02-29 23:04:07 +00:00
|
|
|
child = this._scene.children[i];
|
|
|
|
|
|
|
|
if (!child) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._scene.remove(child);
|
|
|
|
|
|
|
|
if (child.geometry) {
|
|
|
|
// Dispose of mesh and materials
|
|
|
|
child.geometry.dispose();
|
|
|
|
child.geometry = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (child.material) {
|
|
|
|
if (child.material.map) {
|
|
|
|
child.material.map.dispose();
|
|
|
|
child.material.map = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
child.material.dispose();
|
|
|
|
child.material = null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-03-03 17:05:06 +00:00
|
|
|
for (var i = this._domScene3D.children.length - 1; i >= 0; i--) {
|
|
|
|
child = this._domScene3D.children[i];
|
|
|
|
|
|
|
|
if (!child) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._domScene3D.remove(child);
|
|
|
|
};
|
|
|
|
|
|
|
|
for (var i = this._domScene2D.children.length - 1; i >= 0; i--) {
|
|
|
|
child = this._domScene2D.children[i];
|
|
|
|
|
|
|
|
if (!child) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._domScene2D.remove(child);
|
|
|
|
};
|
|
|
|
|
2016-02-29 23:04:07 +00:00
|
|
|
this._picking.destroy();
|
|
|
|
this._picking = null;
|
|
|
|
|
|
|
|
this._world = null;
|
|
|
|
this._scene = null;
|
2016-03-03 17:05:06 +00:00
|
|
|
this._domScene3D = null;
|
|
|
|
this._domScene2D = null;
|
2016-03-11 18:10:36 +00:00
|
|
|
|
|
|
|
this._composer = null;
|
2016-02-29 23:04:07 +00:00
|
|
|
this._renderer = null;
|
2016-03-11 18:10:36 +00:00
|
|
|
|
2016-03-03 17:05:06 +00:00
|
|
|
this._domRenderer3D = null;
|
|
|
|
this._domRenderer2D = null;
|
2016-02-29 23:04:07 +00:00
|
|
|
this._camera = null;
|
|
|
|
this._clock = null;
|
|
|
|
this._frustum = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-01 20:34:53 +00:00
|
|
|
export default Engine;
|
|
|
|
|
|
|
|
// // Initialise without requiring new keyword
|
|
|
|
// export default function(container, world) {
|
|
|
|
// return new Engine(container, world);
|
|
|
|
// };
|