3d-core-raub
Version:
An extensible Node3D core for desktop applications
159 lines (110 loc) • 3.38 kB
JavaScript
'use strict';
const EventEmitter = require('events');
const Rect = require('./rect');
const Vec2 = require('../math/vec2');
class Surface extends Rect {
constructor(opts) {
opts.pos = opts.pos || new Vec2(-300, -300);
opts.size = opts.size || new Vec2(600, 600);
super(opts);
this._events = new EventEmitter();
// Create a different scene to hold our buffer objects
if (!opts.camera ) {
this._camera = new this.screen.three.PerspectiveCamera(
70,
this.width / this.height,
0.1,
1000
);
this._camera.position.z = 10;
} else {
this._camera = opts.camera;
}
if (!opts.scene ) {
this._scene = new this.screen.three.Scene();
} else {
this._scene = opts.scene;
}
// Init RTT
this._target = this._newTarget();
this.draw();
this.mesh.material = new this.screen.three.ShaderMaterial({
side: this.screen.three.DoubleSide,
uniforms : { type: 't', t: { value: this._target.texture } },
vertexShader : `
varying vec2 tc;
void main() {
tc = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
`,
fragmentShader: `
varying vec2 tc;
uniform sampler2D t;
void main() {
// gl_FragColor = (vec4(1.0, 0.0, 1.0, 1.0) + texture2D(t, tc)) * 0.5;
gl_FragColor = texture2D(t, tc);
}
`,
depthWrite : true,
depthTest : true,
transparent : true,
});
this.mesh.onBeforeRender = () => setTimeout(() => this.draw(), 0);
this.mesh.geometry.computeBoundingSphere = () => {
this.mesh.geometry.boundingSphere = new this.screen.three.Sphere(undefined, Infinity);
};
this.mesh.geometry.computeBoundingSphere();
this.mesh.geometry.computeBoundingBox = () => {
this.mesh.geometry.boundingBox = new this.screen.three.Box3();
};
this.mesh.geometry.computeBoundingBox();
this.mesh.material.needsUpdate = true;
}
on(event, cb) {
this[event === 'resize' ? '_events' : 'screen'].on(event, cb);
}
get canvas() { return this.screen.canvas; }
get camera() { return this._camera; }
get scene() { return this._scene; }
get renderer() { return this.screen.renderer; }
get context() { return this.screen.context; }
get document() { return this.screen.document; }
get title() { return this.screen.title; }
set title(v) { this.screen.title = v; }
get fov() { return this.screen.fov; }
set fov(v) { this.screen.fov = v; }
get size() { return super.size; }
set size(v) {
super.size = v;
this.reset();
this._events.emit('resize', { w: this.width, h: this.height });
}
get texture() {
return this._target.texture;
}
reset() {
this._target = this._newTarget();
this.draw();
this.mesh.material.uniforms.t.value = this._target.texture;
this._events.emit('reset', this._target.texture);
}
draw() {
const rt = this.renderer.getRenderTarget();
this.renderer.setRenderTarget(this._target);
this.screen.renderer.render(this._scene, this._camera);
this.renderer.setRenderTarget(rt);
}
_newTarget() {
return new this.screen.three.WebGLRenderTarget(
this.w * 2,
this.h * 2,
{
minFilter : this.screen.three.LinearFilter,
magFilter : this.screen.three.NearestFilter,
format : this.screen.three.RGBAFormat,
}
);
}
}
module.exports = Surface;