3d-core-raub
Version:
An extensible Node3D core for desktop applications
141 lines (111 loc) • 3.19 kB
JavaScript
'use strict';
const Vec2 = require('../math/vec2');
const Drawable = require('./drawable');
class Brush extends Drawable {
constructor(opts) {
super({ screen: opts.screen, color: opts.color });
this._size = opts.size || 100;
this._pos = opts.pos || new Vec2();
if (opts.visible !== undefined && !opts.visible) {
this.visible = false;
}
this.screen.on('resize', () => {
this._mesh.material.uniforms.aspect.value = this.screen.w / this.screen.h;
this._mesh.material.uniforms.size.value = this._size / this.screen.h;
});
}
get size() { return this._size; }
set size(v) {
this._size = v;
if (this.visible) {
this._mesh.material.uniforms.size.value = this._size;
}
}
get pos() { return this._pos; }
set pos(v) {
this._pos.copy(v);
if (this.visible) {
this._mesh.material.uniforms.pos.value = new this.screen.three.Vector2(
(this._pos.x / this.screen.w - 0.5) * 2,
(-this._pos.y / this.screen.h + 0.5) * 2
);
}
}
get visible() { return super.visible; }
set visible(v) {
super.visible = v;
if (this.visible) {
this._mesh.material.uniforms.pos.value = new this.screen.three.Vector2(
this._pos.x,
this._pos.y
);
this._mesh.material.uniforms.size.value = this._size / this.screen.h;
this._mesh.material.uniforms.color.value = new this.screen.three.Vector3(
this._color.r,
this._color.g,
this._color.b
);
}
}
get color() { return this._color; }
set color(v) {
this._color = v;
if (this.visible) {
this.mat.uniforms.color.value = new this.screen.three.Vector3(
this._color.r,
this._color.g,
this._color.b
);
}
}
_geo() {
const geo = new this.screen.three.PlaneGeometry(2, 2);
geo.computeBoundingSphere =
() => geo.boundingSphere = new this.screen.three.Sphere(
undefined, Infinity
);
geo.computeBoundingSphere();
geo.computeBoundingBox = () => geo.boundingBox = new this.screen.three.Box3();
geo.computeBoundingBox();
return geo;
}
_mat() {
return new this.screen.three.ShaderMaterial({
side: this.screen.three.DoubleSide,
uniforms: {
aspect : { type: 'f', value: this.screen.w / this.screen.h },
size : { type: 'f', value: 100 / this.screen.h },
pos : { type: 'v2', value: new this.screen.three.Vector2(0, 0) },
color : { type: 'v3', value: new this.screen.three.Vector3(0, 1, 1) },
},
vertexShader: `
varying vec3 projPos;
void main() {
projPos = position.xyz;
gl_Position = vec4(position.xyz, 1.0);
}
`,
fragmentShader: `
varying vec3 projPos;
uniform vec2 pos;
uniform float size;
uniform vec3 color;
uniform float aspect;
void main() {
vec2 diff = projPos.xy - pos;
diff.x *= aspect;
float dist = length(diff);
float opacity = pow(1.0 - min(1.0, abs(dist - size)), 100.0);
gl_FragColor = vec4(color, opacity);
}
`,
blending : this.screen.three.AdditiveBlending,
depthTest : false,
transparent: true,
});
}
_build(opts) {
return new this.screen.three.Mesh(this._geo(opts), this._mat(opts));
}
}
module.exports = Brush;