mirror of
https://github.com/openglobus/openglobus.git
synced 2025-12-08 19:25:27 +00:00
Merge pull request #379 from tbo47/refactor-es6-class
refactor to use es6 classes
This commit is contained in:
commit
94db508392
@ -12,20 +12,495 @@ import { Vec3 } from './Vec3.js';
|
||||
* @param {number} [x] - First value.
|
||||
* @param {number} [y] - Second value.
|
||||
*/
|
||||
const Vec2 = function (x, y) {
|
||||
export class Vec2 {
|
||||
|
||||
constructor(x, y) {
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @type {number}
|
||||
*/
|
||||
this.x = x || 0.0;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @type {number}
|
||||
*/
|
||||
this.y = y || 0.0;
|
||||
};
|
||||
/** @const */
|
||||
static get UP() { return new Vec2(0, 1) };
|
||||
/** @const */
|
||||
static get DOWN() { return new Vec2(0, -1) };
|
||||
/** @const */
|
||||
static get RIGHT() { return new Vec2(1, 0) };
|
||||
/** @const */
|
||||
static get LEFT() { return new Vec2(-1, 0) };
|
||||
/** @const */
|
||||
static get ZERO() { return new Vec2() };
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @type {number}
|
||||
* Returns summary vector.
|
||||
* @static
|
||||
* @param {og.math.Vec2} a - First vector.
|
||||
* @param {og.math.Vec2} b - Second vector.
|
||||
* @returns {og.math.Vec2} - Summary vector.
|
||||
*/
|
||||
this.x = x || 0.0;
|
||||
static add(a, b) {
|
||||
var res = new Vec2(a.x, a.y);
|
||||
res.addA(b);
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @type {number}
|
||||
* Returns two vectors subtraction.
|
||||
* @static
|
||||
* @param {og.math.Vec2} a - First vector.
|
||||
* @param {og.math.Vec2} b - Second vector.
|
||||
* @returns {og.math.Vec2} - Vectors subtraction.
|
||||
*/
|
||||
this.y = y || 0.0;
|
||||
};
|
||||
static sub(a, b) {
|
||||
var res = new Vec2(a.x, a.y);
|
||||
res.subA(b);
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns scaled vector.
|
||||
* @static
|
||||
* @param {og.math.Vec2} a - Input vector.
|
||||
* @param {number} scale - Scale value.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
static scale(a, scale) {
|
||||
var res = new Vec2(a.x, a.y);
|
||||
res.scale(scale);
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns two vectors production.
|
||||
* @static
|
||||
* @param {og.math.Vec2} a - First vector.
|
||||
* @param {og.math.Vec2} b - Second vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
static mul(a, b) {
|
||||
var res = new Vec2(a.x, a.y);
|
||||
res.mulA(b);
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns vector components division product one to another.
|
||||
* @static
|
||||
* @param {og.math.Vec2} a - First vector.
|
||||
* @param {og.math.Vec2} b - Second vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
static div(a, b) {
|
||||
var res = new Vec2(a.x, a.y);
|
||||
res.divA(b);
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get projection of the first vector to the second.
|
||||
* @static
|
||||
* @param {og.math.Vec2} b - First vector.
|
||||
* @param {og.math.Vec2} a - Second vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
static proj_b_to_a(b, a) {
|
||||
return a.scaleTo(a.dot(b) / a.dot(a));
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets angle between two vectors.
|
||||
* @static
|
||||
* @param {og.math.Vec2} a - First vector.
|
||||
* @param {og.math.Vec2} b - Second vector.
|
||||
* @returns {number}
|
||||
*/
|
||||
static angle(a, b) {
|
||||
return Math.acos(a.dot(b) / Math.sqrt(a.length2() * b.length2()));
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes vectors normalized and orthogonal to each other.
|
||||
* @static
|
||||
* @param {og.math.Vec2} normal - Normal vector.
|
||||
* @param {og.math.Vec2} tangent - Tangent vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
static orthoNormalize(normal, tangent) {
|
||||
normal = normal.norm();
|
||||
normal.scale(tangent.dot(normal));
|
||||
return tangent.sub(normal).normalize();
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts to 3d vector, third value is 0.0.
|
||||
* @public
|
||||
* @returns {og.Vec3}
|
||||
*/
|
||||
toVector3() {
|
||||
return new Vec3(this.x, this.y, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns clone vector.
|
||||
* @public
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
clone() {
|
||||
return new Vec2(this.x, this.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Compares with vector. Returns true if it equals another.
|
||||
* @public
|
||||
* @param {og.math.Vec2} p - Vector to compare.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equal(p) {
|
||||
return this.x === p.x && this.y === p.y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy input vector's values.
|
||||
* @param {og.math.Vec2} point2 - Vector to copy.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
copy(point2) {
|
||||
this.x = point2.x;
|
||||
this.y = point2.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets vector's length.
|
||||
* @public
|
||||
* @returns {number}
|
||||
*/
|
||||
length() {
|
||||
return Math.sqrt(this.x * this.x + this.y * this.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns squared vector's length.
|
||||
* @public
|
||||
* @returns {number}
|
||||
*/
|
||||
length2() {
|
||||
return this.x * this.x + this.y * this.y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds vector to the current.
|
||||
* @public
|
||||
* @param {og.math.Vec2}
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
addA(v) {
|
||||
this.x += v.x;
|
||||
this.y += v.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Summarize two vectors.
|
||||
* @public
|
||||
* @param {og.math.Vec2}
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
add(v) {
|
||||
return new Vec2(this.x + v.x, this.y + v.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Subtract vector from the current where results saved on the current instance.
|
||||
* @public
|
||||
* @param {og.math.Vec2} v - Subtract vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
subA(v) {
|
||||
this.x -= v.x;
|
||||
this.y -= v.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Subtract vector from the current.
|
||||
* @public
|
||||
* @param {og.math.Vec2} v - Subtract vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
sub(v) {
|
||||
return new Vec2(this.x - v.x, this.y - v.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Scale current vector.
|
||||
* @public
|
||||
* @param {number} scale - Scale value.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
scale(scale) {
|
||||
this.x *= scale;
|
||||
this.y *= scale;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scale current vector to another instance.
|
||||
* @public
|
||||
* @param {number} scale - Scale value.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
scaleTo(scale) {
|
||||
return new Vec2(this.x * scale, this.y * scale);
|
||||
};
|
||||
|
||||
/**
|
||||
* Multiply current vector object to another and store result in the current instance.
|
||||
* @public
|
||||
* @param {og.math.Vec2} vec - Multiply vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
mulA(vec) {
|
||||
this.x *= vec.x;
|
||||
this.y *= vec.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Multiply current vector object to another and returns new vector instance.
|
||||
* @public
|
||||
* @param {og.math.Vec2} vec - Multiply vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
mul(vec) {
|
||||
return new Vec2(this.x * vec.x, this.y * vec.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Divide current vector's components to another. Results stores in the current vector object.
|
||||
* @public
|
||||
* @param {og.math.Vec2}
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
divA(vec) {
|
||||
this.x /= vec.x;
|
||||
this.y /= vec.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets vectors dot production.
|
||||
* @public
|
||||
* @param {og.math.Vec2} v - Another vector.
|
||||
* @returns {number}
|
||||
*/
|
||||
dot(v) {
|
||||
return v.x * this.x + v.y * this.y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets vectors dot production.
|
||||
* @public
|
||||
* @param {Array.<number,number>} arr - Array vector.
|
||||
* @returns {number}
|
||||
*/
|
||||
dotArr(arr) {
|
||||
return arr[0] * this.x + arr[1] * this.y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets vectors cross production.
|
||||
* @public
|
||||
* @param {og.math.Vec2} v - Another vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
cross(v) {
|
||||
return this.x * v.y - this.y * v.x;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets vector to zero.
|
||||
* @public
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
clear() {
|
||||
this.x = this.y = 0;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns normalized vector.
|
||||
* @public
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
normal() {
|
||||
var res = new Vec2();
|
||||
res.copy(this);
|
||||
|
||||
var length = 1.0 / res.length();
|
||||
|
||||
res.x *= length;
|
||||
res.y *= length;
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalize current vector.
|
||||
* @public
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
normalize() {
|
||||
var length = 1.0 / this.length();
|
||||
|
||||
this.x *= length;
|
||||
this.y *= length;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts vector to a number array.
|
||||
* @public
|
||||
* @returns {Array.<number,number>}
|
||||
*/
|
||||
toVec() {
|
||||
return [this.x, this.y];
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets distance to point.
|
||||
* @public
|
||||
* @param {og.math.Vec2} p - Distant point.
|
||||
* @returns {number}
|
||||
*/
|
||||
distance(p) {
|
||||
var vec = Vec2.sub(this, p);
|
||||
return vec.length();
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets vector's values.
|
||||
* @public
|
||||
* @param {number} x - Value X.
|
||||
* @param {number} y - Value Y.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
set(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Negate current vector.
|
||||
* @public
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
negate() {
|
||||
this.x = -this.x;
|
||||
this.y = -this.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Negate current vector to another instance.
|
||||
* @public
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
negateTo() {
|
||||
return new Vec2(-this.x, -this.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets projected point coordinates of the current vector on the ray.
|
||||
* @public
|
||||
* @param {og.math.Vec2} pos - Ray position.
|
||||
* @param {og.math.Vec2} direction - Ray direction.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
projToRay(pos, direction) {
|
||||
var v = Vec2.proj_b_to_a(Vec2.sub(this, pos), direction);
|
||||
v.add(pos);
|
||||
return v;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets angle between two vectors.
|
||||
* @public
|
||||
* @param {og.math.Vec2} a - Another vector.
|
||||
* @returns {number}
|
||||
*/
|
||||
angle(a) {
|
||||
return Vec2.angle(this, a);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns two vectors linear interpolation.
|
||||
* @public
|
||||
* @param {og.math.Vec2} v2 - End vector.
|
||||
* @param {number} l - Interpolate value.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
lerp(v1, v2, l) {
|
||||
var res = Vec2.clone(this);
|
||||
if (l <= 0.0) {
|
||||
res.copy(v1);
|
||||
} else if (l >= 1.0) {
|
||||
res.copy(v2);
|
||||
} else {
|
||||
res = Vec2.add(v1, Vec2.sub(v2, v1).scale(l));
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
static get LERP_DELTA() { return 1e-6 };
|
||||
|
||||
/**
|
||||
* Spherically interpolates between two vectors.
|
||||
* Interpolates between current and v2 vector by amount t. The difference between this and linear interpolation (aka, "lerp") is that
|
||||
* the vectors are treated as directions rather than points in space. The direction of the returned vector is interpolated
|
||||
* by the angle and its magnitude is interpolated between the magnitudes of from and to.
|
||||
* @public
|
||||
* @param {og.math.Vec2} v2 -
|
||||
* @param {number} t - The parameter t is clamped to the range [0, 1].
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
slerp(v2, t) {
|
||||
var res = new Vec2();
|
||||
|
||||
if (t <= 0.0) {
|
||||
res.copy(this);
|
||||
return;
|
||||
} else if (t >= 1.0) {
|
||||
res.copy(v2);
|
||||
return;
|
||||
}
|
||||
|
||||
var omega, sinom, scale0, scale1;
|
||||
var cosom = this.dot(v2);
|
||||
|
||||
if ((1.0 - cosom) > Vec2.LERP_DELTA) {
|
||||
omega = Math.acos(cosom);
|
||||
sinom = Math.sin(omega);
|
||||
scale0 = Math.sin((1.0 - t) * omega) / sinom;
|
||||
scale1 = Math.sin(t * omega) / sinom;
|
||||
} else {
|
||||
scale0 = 1.0 - t;
|
||||
scale1 = t;
|
||||
}
|
||||
|
||||
return Vec2.add(this.scale(scale0), v2.scale(scale1));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Vector 2d object creator.
|
||||
@ -37,478 +512,3 @@ const Vec2 = function (x, y) {
|
||||
export function vec2(x, y) {
|
||||
return new Vec2(x, y);
|
||||
};
|
||||
|
||||
/** @const */
|
||||
Vec2.UP = new Vec2(0, 1);
|
||||
/** @const */
|
||||
Vec2.DOWN = new Vec2(0, -1);
|
||||
/** @const */
|
||||
Vec2.RIGHT = new Vec2(1, 0);
|
||||
/** @const */
|
||||
Vec2.LEFT = new Vec2(-1, 0);
|
||||
/** @const */
|
||||
Vec2.ZERO = new Vec2();
|
||||
|
||||
/**
|
||||
* Returns summary vector.
|
||||
* @static
|
||||
* @param {og.math.Vec2} a - First vector.
|
||||
* @param {og.math.Vec2} b - Second vector.
|
||||
* @returns {og.math.Vec2} - Summary vector.
|
||||
*/
|
||||
Vec2.add = function (a, b) {
|
||||
var res = new Vec2(a.x, a.y);
|
||||
res.addA(b);
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns two vectors subtraction.
|
||||
* @static
|
||||
* @param {og.math.Vec2} a - First vector.
|
||||
* @param {og.math.Vec2} b - Second vector.
|
||||
* @returns {og.math.Vec2} - Vectors subtraction.
|
||||
*/
|
||||
Vec2.sub = function (a, b) {
|
||||
var res = new Vec2(a.x, a.y);
|
||||
res.subA(b);
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns scaled vector.
|
||||
* @static
|
||||
* @param {og.math.Vec2} a - Input vector.
|
||||
* @param {number} scale - Scale value.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.scale = function (a, scale) {
|
||||
var res = new Vec2(a.x, a.y);
|
||||
res.scale(scale);
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns two vectors production.
|
||||
* @static
|
||||
* @param {og.math.Vec2} a - First vector.
|
||||
* @param {og.math.Vec2} b - Second vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.mul = function (a, b) {
|
||||
var res = new Vec2(a.x, a.y);
|
||||
res.mulA(b);
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns vector components division product one to another.
|
||||
* @static
|
||||
* @param {og.math.Vec2} a - First vector.
|
||||
* @param {og.math.Vec2} b - Second vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.div = function (a, b) {
|
||||
var res = new Vec2(a.x, a.y);
|
||||
res.divA(b);
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get projection of the first vector to the second.
|
||||
* @static
|
||||
* @param {og.math.Vec2} b - First vector.
|
||||
* @param {og.math.Vec2} a - Second vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.proj_b_to_a = function (b, a) {
|
||||
return a.scaleTo(a.dot(b) / a.dot(a));
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets angle between two vectors.
|
||||
* @static
|
||||
* @param {og.math.Vec2} a - First vector.
|
||||
* @param {og.math.Vec2} b - Second vector.
|
||||
* @returns {number}
|
||||
*/
|
||||
Vec2.angle = function (a, b) {
|
||||
return Math.acos(a.dot(b) / Math.sqrt(a.length2() * b.length2()));
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes vectors normalized and orthogonal to each other.
|
||||
* @static
|
||||
* @param {og.math.Vec2} normal - Normal vector.
|
||||
* @param {og.math.Vec2} tangent - Tangent vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.orthoNormalize = function (normal, tangent) {
|
||||
normal = normal.norm();
|
||||
normal.scale(tangent.dot(normal));
|
||||
return tangent.sub(normal).normalize();
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts to 3d vector, third value is 0.0.
|
||||
* @public
|
||||
* @returns {og.Vec3}
|
||||
*/
|
||||
Vec2.prototype.toVector3 = function () {
|
||||
return new Vec3(this.x, this.y, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns clone vector.
|
||||
* @public
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.clone = function () {
|
||||
return new Vec2(this.x, this.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Compares with vector. Returns true if it equals another.
|
||||
* @public
|
||||
* @param {og.math.Vec2} p - Vector to compare.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Vec2.prototype.equal = function (p) {
|
||||
return this.x === p.x && this.y === p.y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy input vector's values.
|
||||
* @param {og.math.Vec2} point2 - Vector to copy.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.copy = function (point2) {
|
||||
this.x = point2.x;
|
||||
this.y = point2.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets vector's length.
|
||||
* @public
|
||||
* @returns {number}
|
||||
*/
|
||||
Vec2.prototype.length = function () {
|
||||
return Math.sqrt(this.x * this.x + this.y * this.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns squared vector's length.
|
||||
* @public
|
||||
* @returns {number}
|
||||
*/
|
||||
Vec2.prototype.length2 = function () {
|
||||
return this.x * this.x + this.y * this.y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds vector to the current.
|
||||
* @public
|
||||
* @param {og.math.Vec2}
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.addA = function (v) {
|
||||
this.x += v.x;
|
||||
this.y += v.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Summarize two vectors.
|
||||
* @public
|
||||
* @param {og.math.Vec2}
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.add = function (v) {
|
||||
return new Vec2(this.x + v.x, this.y + v.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Subtract vector from the current where results saved on the current instance.
|
||||
* @public
|
||||
* @param {og.math.Vec2} v - Subtract vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.subA = function (v) {
|
||||
this.x -= v.x;
|
||||
this.y -= v.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Subtract vector from the current.
|
||||
* @public
|
||||
* @param {og.math.Vec2} v - Subtract vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.sub = function (v) {
|
||||
return new Vec2(this.x - v.x, this.y - v.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Scale current vector.
|
||||
* @public
|
||||
* @param {number} scale - Scale value.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.scale = function (scale) {
|
||||
this.x *= scale;
|
||||
this.y *= scale;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scale current vector to another instance.
|
||||
* @public
|
||||
* @param {number} scale - Scale value.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.scaleTo = function (scale) {
|
||||
return new Vec2(this.x * scale, this.y * scale);
|
||||
};
|
||||
|
||||
/**
|
||||
* Multiply current vector object to another and store result in the current instance.
|
||||
* @public
|
||||
* @param {og.math.Vec2} vec - Multiply vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.mulA = function (vec) {
|
||||
this.x *= vec.x;
|
||||
this.y *= vec.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Multiply current vector object to another and returns new vector instance.
|
||||
* @public
|
||||
* @param {og.math.Vec2} vec - Multiply vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.mul = function (vec) {
|
||||
return new Vec2(this.x * vec.x, this.y * vec.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Divide current vector's components to another. Results stores in the current vector object.
|
||||
* @public
|
||||
* @param {og.math.Vec2}
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.divA = function (vec) {
|
||||
this.x /= vec.x;
|
||||
this.y /= vec.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets vectors dot production.
|
||||
* @public
|
||||
* @param {og.math.Vec2} v - Another vector.
|
||||
* @returns {number}
|
||||
*/
|
||||
Vec2.prototype.dot = function (v) {
|
||||
return v.x * this.x + v.y * this.y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets vectors dot production.
|
||||
* @public
|
||||
* @param {Array.<number,number>} arr - Array vector.
|
||||
* @returns {number}
|
||||
*/
|
||||
Vec2.prototype.dotArr = function (arr) {
|
||||
return arr[0] * this.x + arr[1] * this.y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets vectors cross production.
|
||||
* @public
|
||||
* @param {og.math.Vec2} v - Another vector.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.cross = function (v) {
|
||||
return this.x * v.y - this.y * v.x;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets vector to zero.
|
||||
* @public
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.clear = function () {
|
||||
this.x = this.y = 0;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns normalized vector.
|
||||
* @public
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.normal = function () {
|
||||
var res = new Vec2();
|
||||
res.copy(this);
|
||||
|
||||
var length = 1.0 / res.length();
|
||||
|
||||
res.x *= length;
|
||||
res.y *= length;
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalize current vector.
|
||||
* @public
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.normalize = function () {
|
||||
var length = 1.0 / this.length();
|
||||
|
||||
this.x *= length;
|
||||
this.y *= length;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts vector to a number array.
|
||||
* @public
|
||||
* @returns {Array.<number,number>}
|
||||
*/
|
||||
Vec2.prototype.toVec = function () {
|
||||
return [this.x, this.y];
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets distance to point.
|
||||
* @public
|
||||
* @param {og.math.Vec2} p - Distant point.
|
||||
* @returns {number}
|
||||
*/
|
||||
Vec2.prototype.distance = function (p) {
|
||||
var vec = Vec2.sub(this, p);
|
||||
return vec.length();
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets vector's values.
|
||||
* @public
|
||||
* @param {number} x - Value X.
|
||||
* @param {number} y - Value Y.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.set = function (x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Negate current vector.
|
||||
* @public
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.negate = function () {
|
||||
this.x = -this.x;
|
||||
this.y = -this.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Negate current vector to another instance.
|
||||
* @public
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.negateTo = function () {
|
||||
return new Vec2(-this.x, -this.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets projected point coordinates of the current vector on the ray.
|
||||
* @public
|
||||
* @param {og.math.Vec2} pos - Ray position.
|
||||
* @param {og.math.Vec2} direction - Ray direction.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.projToRay = function (pos, direction) {
|
||||
var v = Vec2.proj_b_to_a(Vec2.sub(this, pos), direction);
|
||||
v.add(pos);
|
||||
return v;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets angle between two vectors.
|
||||
* @public
|
||||
* @param {og.math.Vec2} a - Another vector.
|
||||
* @returns {number}
|
||||
*/
|
||||
Vec2.prototype.angle = function (a) {
|
||||
return Vec2.angle(this, a);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns two vectors linear interpolation.
|
||||
* @public
|
||||
* @param {og.math.Vec2} v2 - End vector.
|
||||
* @param {number} l - Interpolate value.
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.lerp = function (v1, v2, l) {
|
||||
var res = Vec2.clone(this);
|
||||
if (l <= 0.0) {
|
||||
res.copy(v1);
|
||||
} else if (l >= 1.0) {
|
||||
res.copy(v2);
|
||||
} else {
|
||||
res = Vec2.add(v1, Vec2.sub(v2, v1).scale(l));
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
Vec2.LERP_DELTA = 1e-6;
|
||||
|
||||
/**
|
||||
* Spherically interpolates between two vectors.
|
||||
* Interpolates between current and v2 vector by amount t. The difference between this and linear interpolation (aka, "lerp") is that
|
||||
* the vectors are treated as directions rather than points in space. The direction of the returned vector is interpolated
|
||||
* by the angle and its magnitude is interpolated between the magnitudes of from and to.
|
||||
* @public
|
||||
* @param {og.math.Vec2} v2 -
|
||||
* @param {number} t - The parameter t is clamped to the range [0, 1].
|
||||
* @returns {og.math.Vec2}
|
||||
*/
|
||||
Vec2.prototype.slerp = function (v2, t) {
|
||||
var res = new Vec2();
|
||||
|
||||
if (t <= 0.0) {
|
||||
res.copy(this);
|
||||
return;
|
||||
} else if (t >= 1.0) {
|
||||
res.copy(v2);
|
||||
return;
|
||||
}
|
||||
|
||||
var omega, sinom, scale0, scale1;
|
||||
var cosom = this.dot(v2);
|
||||
|
||||
if ((1.0 - cosom) > Vec2.LERP_DELTA) {
|
||||
omega = Math.acos(cosom);
|
||||
sinom = Math.sin(omega);
|
||||
scale0 = Math.sin((1.0 - t) * omega) / sinom;
|
||||
scale1 = Math.sin(t * omega) / sinom;
|
||||
} else {
|
||||
scale0 = 1.0 - t;
|
||||
scale1 = t;
|
||||
}
|
||||
|
||||
return Vec2.add(this.scale(scale0), v2.scale(scale1));
|
||||
};
|
||||
|
||||
export { Vec2 };
|
||||
1650
src/og/math/Vec3.js
1650
src/og/math/Vec3.js
File diff suppressed because it is too large
Load Diff
@ -14,39 +14,242 @@ import { Vec3 } from './Vec3.js';
|
||||
* @param {number} [z] - Third value.
|
||||
* @param {number} [w] - Fourth value.
|
||||
*/
|
||||
const Vec4 = function (x, y, z, w) {
|
||||
export class Vec4 {
|
||||
|
||||
constructor(x, y, z, w) {
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @type {number}
|
||||
*/
|
||||
this.x = x || 0.0;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @type {number}
|
||||
*/
|
||||
this.y = y || 0.0;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @type {number}
|
||||
*/
|
||||
this.z = z || 0.0;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @type {number}
|
||||
*/
|
||||
this.w = w || 0.0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @type {number}
|
||||
* Identity vector [0,0,0,1].
|
||||
* @const
|
||||
* @type {og.math.Vec4}
|
||||
*/
|
||||
this.x = x || 0.0;
|
||||
static get identity() { return new Vec4(0, 0, 0, 1) };
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @type {number}
|
||||
* Creates 4d vector from array.
|
||||
* @function
|
||||
* @param {Array.<number,number,number,number>}
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
this.y = y || 0.0;
|
||||
static fromVec(arr) {
|
||||
return new Vec4(arr[0], arr[1], arr[2], arr[3]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts to 3d vector, without fourth value.
|
||||
* @public
|
||||
* @type {number}
|
||||
* @returns {og.Vec3}
|
||||
*/
|
||||
this.z = z || 0.0;
|
||||
toVec3() {
|
||||
return new Vec3(this.x, this.y, this.z);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns clone vector.
|
||||
* @public
|
||||
* @type {number}
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
this.w = w || 0.0;
|
||||
};
|
||||
clone(v) {
|
||||
return new Vec4(this.x, this.y, this.z, this.w);
|
||||
};
|
||||
|
||||
/**
|
||||
* Identity vector [0,0,0,1].
|
||||
* @const
|
||||
* @type {og.math.Vec4}
|
||||
*/
|
||||
Vec4.identity = new Vec4(0, 0, 0, 1);
|
||||
/**
|
||||
* Compares with vector. Returns true if it equals another.
|
||||
* @public
|
||||
* @param {og.math.Vec4} p - Vector to compare.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equal(v) {
|
||||
return this.x === v.x && this.y === v.y && this.z === v.z && this.w === v.w;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy input vector's values.
|
||||
* @param {og.math.Vec4} v - Vector to copy.
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
copy(v) {
|
||||
this.x = v.x;
|
||||
this.y = v.y;
|
||||
this.z = v.z;
|
||||
this.w = v.w;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts vector to a number array.
|
||||
* @public
|
||||
* @returns {Array.<number,number,number,number>}
|
||||
* @deprecated
|
||||
*/
|
||||
toVec() {
|
||||
return [this.x, this.y, this.z, this.w];
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts vector to a number array.
|
||||
* @public
|
||||
* @returns {Array.<number,number,number,number>}
|
||||
*/
|
||||
toArray() {
|
||||
return [this.x, this.y, this.z, this.w];
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets vector's values.
|
||||
* @public
|
||||
* @param {number} x - Value X.
|
||||
* @param {number} y - Value Y.
|
||||
* @param {number} z - Value Z.
|
||||
* @param {number} w - Value W.
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
set(x, y, z, w) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds vector to the current.
|
||||
* @public
|
||||
* @param {og.math.Vec4}
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
addA(v) {
|
||||
this.x += v.x;
|
||||
this.y += v.y;
|
||||
this.z += v.z;
|
||||
this.w += v.w;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Subtract vector from the current.
|
||||
* @public
|
||||
* @param {og.math.Vec4} v - Subtract vector.
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
subA(v) {
|
||||
this.x -= v.x;
|
||||
this.y -= v.y;
|
||||
this.z -= v.z;
|
||||
this.w -= v.w;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scale current vector.
|
||||
* @public
|
||||
* @param {number} scale - Scale value.
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
scale(scale) {
|
||||
this.x *= scale;
|
||||
this.y *= scale;
|
||||
this.z *= scale;
|
||||
this.w *= scale;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes vector affinity. Thereby fourh component becomes to 1.0.
|
||||
* @public
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
affinity() {
|
||||
var iw = 1 / this.w;
|
||||
this.x *= iw;
|
||||
this.y *= iw;
|
||||
this.z *= iw;
|
||||
this.w = 1.0;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scale current vector to another instance.
|
||||
* @public
|
||||
* @param {number} scale - Scale value.
|
||||
* @returns {og.Vec3}
|
||||
*/
|
||||
scaleTo(scale) {
|
||||
return new Vec4(this.x * scale, this.y * scale, this.z * scale, this.w * scale);
|
||||
};
|
||||
|
||||
/**
|
||||
* Vector's edge function that returns vector where each component is 0.0 if it's smaller then edge and otherwise 1.0.
|
||||
* @public
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
getStep(edge) {
|
||||
return new Vec4(
|
||||
this.x < edge ? 0.0 : 1.0,
|
||||
this.y < edge ? 0.0 : 1.0,
|
||||
this.z < edge ? 0.0 : 1.0,
|
||||
this.w < edge ? 0.0 : 1.0
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* The vector fract function returns the vector of fractional parts of each value, i.e. x minus floor(x).
|
||||
* @public
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
getFrac(v) {
|
||||
return new Vec4(
|
||||
og.math.frac(v.x),
|
||||
og.math.frac(v.y),
|
||||
og.math.frac(v.z),
|
||||
og.math.frac(v.w)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets vectors dot production.
|
||||
* @public
|
||||
* @param {og.math.Vec4} v - Another vector.
|
||||
* @returns {number} - Dot product.
|
||||
*/
|
||||
dot(v) {
|
||||
return v.x * this.x + v.y * this.y + v.z * this.z + v.w * this.w;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if vector's values are zero.
|
||||
* @public
|
||||
* @returns {boolean} -
|
||||
*/
|
||||
isZero() {
|
||||
return !(this.x || this.y || this.z || this.w);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Vector 4d object creator.
|
||||
@ -60,205 +263,3 @@ Vec4.identity = new Vec4(0, 0, 0, 1);
|
||||
export function vec4(x, y, z, w) {
|
||||
return new og.math.Vec4(x, y, z, w);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates 4d vector from array.
|
||||
* @function
|
||||
* @param {Array.<number,number,number,number>}
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
Vec4.fromVec = function (arr) {
|
||||
return new Vec4(arr[0], arr[1], arr[2], arr[3]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts to 3d vector, without fourth value.
|
||||
* @public
|
||||
* @returns {og.Vec3}
|
||||
*/
|
||||
Vec4.prototype.toVec3 = function () {
|
||||
return new Vec3(this.x, this.y, this.z);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns clone vector.
|
||||
* @public
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
Vec4.prototype.clone = function (v) {
|
||||
return new Vec4(this.x, this.y, this.z, this.w);
|
||||
};
|
||||
|
||||
/**
|
||||
* Compares with vector. Returns true if it equals another.
|
||||
* @public
|
||||
* @param {og.math.Vec4} p - Vector to compare.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Vec4.prototype.equal = function (v) {
|
||||
return this.x === v.x && this.y === v.y && this.z === v.z && this.w === v.w;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy input vector's values.
|
||||
* @param {og.math.Vec4} v - Vector to copy.
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
Vec4.prototype.copy = function (v) {
|
||||
this.x = v.x;
|
||||
this.y = v.y;
|
||||
this.z = v.z;
|
||||
this.w = v.w;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts vector to a number array.
|
||||
* @public
|
||||
* @returns {Array.<number,number,number,number>}
|
||||
* @deprecated
|
||||
*/
|
||||
Vec4.prototype.toVec = function () {
|
||||
return [this.x, this.y, this.z, this.w];
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts vector to a number array.
|
||||
* @public
|
||||
* @returns {Array.<number,number,number,number>}
|
||||
*/
|
||||
Vec4.prototype.toArray = function () {
|
||||
return [this.x, this.y, this.z, this.w];
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets vector's values.
|
||||
* @public
|
||||
* @param {number} x - Value X.
|
||||
* @param {number} y - Value Y.
|
||||
* @param {number} z - Value Z.
|
||||
* @param {number} w - Value W.
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
Vec4.prototype.set = function (x, y, z, w) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds vector to the current.
|
||||
* @public
|
||||
* @param {og.math.Vec4}
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
Vec4.prototype.addA = function (v) {
|
||||
this.x += v.x;
|
||||
this.y += v.y;
|
||||
this.z += v.z;
|
||||
this.w += v.w;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Subtract vector from the current.
|
||||
* @public
|
||||
* @param {og.math.Vec4} v - Subtract vector.
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
Vec4.prototype.subA = function (v) {
|
||||
this.x -= v.x;
|
||||
this.y -= v.y;
|
||||
this.z -= v.z;
|
||||
this.w -= v.w;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scale current vector.
|
||||
* @public
|
||||
* @param {number} scale - Scale value.
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
Vec4.prototype.scale = function (scale) {
|
||||
this.x *= scale;
|
||||
this.y *= scale;
|
||||
this.z *= scale;
|
||||
this.w *= scale;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes vector affinity. Thereby fourh component becomes to 1.0.
|
||||
* @public
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
Vec4.prototype.affinity = function () {
|
||||
var iw = 1 / this.w;
|
||||
this.x *= iw;
|
||||
this.y *= iw;
|
||||
this.z *= iw;
|
||||
this.w = 1.0;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scale current vector to another instance.
|
||||
* @public
|
||||
* @param {number} scale - Scale value.
|
||||
* @returns {og.Vec3}
|
||||
*/
|
||||
Vec4.prototype.scaleTo = function (scale) {
|
||||
return new Vec4(this.x * scale, this.y * scale, this.z * scale, this.w * scale);
|
||||
};
|
||||
|
||||
/**
|
||||
* Vector's edge function that returns vector where each component is 0.0 if it's smaller then edge and otherwise 1.0.
|
||||
* @public
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
Vec4.prototype.getStep = function (edge) {
|
||||
return new Vec4(
|
||||
this.x < edge ? 0.0 : 1.0,
|
||||
this.y < edge ? 0.0 : 1.0,
|
||||
this.z < edge ? 0.0 : 1.0,
|
||||
this.w < edge ? 0.0 : 1.0
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* The vector fract function returns the vector of fractional parts of each value, i.e. x minus floor(x).
|
||||
* @public
|
||||
* @returns {og.math.Vec4}
|
||||
*/
|
||||
Vec4.prototype.getFrac = function (v) {
|
||||
return new Vec4(
|
||||
og.math.frac(v.x),
|
||||
og.math.frac(v.y),
|
||||
og.math.frac(v.z),
|
||||
og.math.frac(v.w)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets vectors dot production.
|
||||
* @public
|
||||
* @param {og.math.Vec4} v - Another vector.
|
||||
* @returns {number} - Dot product.
|
||||
*/
|
||||
Vec4.prototype.dot = function (v) {
|
||||
return v.x * this.x + v.y * this.y + v.z * this.z + v.w * this.w;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if vector's values are zero.
|
||||
* @public
|
||||
* @returns {boolean} -
|
||||
*/
|
||||
Vec4.prototype.isZero = function () {
|
||||
return !(this.x || this.y || this.z || this.w);
|
||||
};
|
||||
|
||||
export { Vec4 };
|
||||
@ -100,7 +100,7 @@ const EVENT_NAMES = [
|
||||
* @fires og.scene.Planet#layervisibilitychange
|
||||
* @fires og.scene.Planet#geoimageadd
|
||||
*/
|
||||
class Planet extends RenderNode {
|
||||
export class Planet extends RenderNode {
|
||||
constructor(options = {}) {
|
||||
super(options.name);
|
||||
|
||||
@ -1716,6 +1716,9 @@ class Planet extends RenderNode {
|
||||
* @param {og.Vec3} [look] - Camera "look at" point on the end of a flying.
|
||||
* @param {og.Vec3} [up] - Camera UP vector on the end of a flying.
|
||||
* @param {Number} [ampl] - Altitude amplitude factor.
|
||||
* @param [completeCallback]
|
||||
* @param [startCallback]
|
||||
* @param [frameCallback]
|
||||
*/
|
||||
flyLonLat(lonlat, look, up, ampl, completeCallback, startCallback, frameCallback) {
|
||||
this.renderer.activeCamera.flyLonLat(
|
||||
@ -1766,5 +1769,3 @@ class Planet extends RenderNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { Planet };
|
||||
|
||||
@ -51,6 +51,10 @@ const EVENT_NAMES = [
|
||||
* @fires og.terrain.GlobusTerrain#loadend
|
||||
*/
|
||||
class GlobusTerrain extends EmptyTerrain {
|
||||
/**
|
||||
* @param {string} [name]
|
||||
* @param {*} [options]
|
||||
*/
|
||||
constructor(name, options) {
|
||||
super();
|
||||
|
||||
|
||||
@ -1,143 +1,145 @@
|
||||
'use strict';
|
||||
|
||||
import { LonLat } from '../LonLat.js';
|
||||
import * as utils from '../utils/shared.js';
|
||||
import { Framebuffer } from '../webgl/Framebuffer.js';
|
||||
import { LonLat } from '../LonLat.js';
|
||||
import { Program } from '../webgl/Program.js';
|
||||
import { types } from '../webgl/types.js';
|
||||
|
||||
const GeoImageCreator = function (planet, maxFrames) {
|
||||
this._gridSize = 64;
|
||||
this._planet = planet;
|
||||
this._framebuffer = null;
|
||||
this._texCoordsBuffer = null;
|
||||
this._indexBuffer = null;
|
||||
this.MAX_FRAMES = maxFrames || 5;
|
||||
this._currentFrame = 0;
|
||||
this._queue = [];
|
||||
this._animate = [];
|
||||
this._initialize();
|
||||
};
|
||||
export class GeoImageCreator {
|
||||
|
||||
GeoImageCreator.prototype._initialize = function () {
|
||||
this._initShaders();
|
||||
this._initBuffers();
|
||||
};
|
||||
constructor(planet, maxFrames) {
|
||||
this._gridSize = 64;
|
||||
this._planet = planet;
|
||||
this._framebuffer = null;
|
||||
this._texCoordsBuffer = null;
|
||||
this._indexBuffer = null;
|
||||
this.MAX_FRAMES = maxFrames || 5;
|
||||
this._currentFrame = 0;
|
||||
this._queue = [];
|
||||
this._animate = [];
|
||||
this._initialize();
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates geoImage corners coordinates grid buffer.
|
||||
* @public
|
||||
* @param{Array.<og.LonLat>} c - GeoImage corners coordinates.
|
||||
* @return{WebGLBuffer} Grid coordinates buffer.
|
||||
*/
|
||||
GeoImageCreator.prototype.createGridBuffer = function (c, toMerc) {
|
||||
var gs = this._gridSize;
|
||||
_initialize() {
|
||||
this._initShaders();
|
||||
this._initBuffers();
|
||||
};
|
||||
|
||||
var v03 = new LonLat((c[3].lon - c[0].lon) / gs, (c[3].lat - c[0].lat) / gs),
|
||||
v12 = new LonLat((c[2].lon - c[1].lon) / gs, (c[2].lat - c[1].lat) / gs),
|
||||
v01 = new LonLat((c[1].lon - c[0].lon) / gs, (c[1].lat - c[0].lat) / gs),
|
||||
v32 = new LonLat((c[2].lon - c[3].lon) / gs, (c[2].lat - c[3].lat) / gs);
|
||||
/**
|
||||
* Creates geoImage corners coordinates grid buffer.
|
||||
* @public
|
||||
* @param{Array.<og.LonLat>} c - GeoImage corners coordinates.
|
||||
* @return{WebGLBuffer} Grid coordinates buffer.
|
||||
*/
|
||||
createGridBuffer(c, toMerc) {
|
||||
var gs = this._gridSize;
|
||||
|
||||
var grid = new Float32Array((gs + 1) * (gs + 1) * 2);
|
||||
var k = 0;
|
||||
for (let i = 0; i <= gs; i++) {
|
||||
var P03i = new LonLat(c[0].lon + i * v03.lon, c[0].lat + i * v03.lat),
|
||||
P12i = new LonLat(c[1].lon + i * v12.lon, c[1].lat + i * v12.lat);
|
||||
for (let j = 0; j <= gs; j++) {
|
||||
var P01j = new LonLat(c[0].lon + j * v01.lon, c[0].lat + j * v01.lat),
|
||||
P32j = new LonLat(c[3].lon + j * v32.lon, c[3].lat + j * v32.lat);
|
||||
var xx = utils.getLinesIntersectionLonLat(P03i, P12i, P01j, P32j);
|
||||
grid[k++] = xx.lon;
|
||||
grid[k++] = xx.lat;
|
||||
}
|
||||
}
|
||||
var v03 = new LonLat((c[3].lon - c[0].lon) / gs, (c[3].lat - c[0].lat) / gs),
|
||||
v12 = new LonLat((c[2].lon - c[1].lon) / gs, (c[2].lat - c[1].lat) / gs),
|
||||
v01 = new LonLat((c[1].lon - c[0].lon) / gs, (c[1].lat - c[0].lat) / gs),
|
||||
v32 = new LonLat((c[2].lon - c[3].lon) / gs, (c[2].lat - c[3].lat) / gs);
|
||||
|
||||
if (toMerc) {
|
||||
for (let i = 0; i < grid.length; i += 2) {
|
||||
let c = new LonLat(grid[i], grid[i + 1]).forwardMercator();
|
||||
grid[i] = c.lon;
|
||||
grid[i + 1] = c.lat;
|
||||
}
|
||||
}
|
||||
return this._planet.renderer.handler.createArrayBuffer(grid, 2, grid.length / 2);
|
||||
};
|
||||
|
||||
GeoImageCreator.prototype.frame = function () {
|
||||
var i = this.MAX_FRAMES;
|
||||
while (i-- && this._queue.length) {
|
||||
var q = this._queue.shift();
|
||||
q._isRendering = false;
|
||||
q.rendering();
|
||||
}
|
||||
|
||||
i = this._animate.length;
|
||||
while (i--) {
|
||||
this._animate[i].rendering();
|
||||
}
|
||||
};
|
||||
|
||||
GeoImageCreator.prototype.add = function (geoImage) {
|
||||
if (!geoImage._isRendering) {
|
||||
geoImage._isRendering = true;
|
||||
if (geoImage._animate) {
|
||||
this._animate.push(geoImage);
|
||||
} else {
|
||||
this._queue.push(geoImage);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
GeoImageCreator.prototype.remove = function (geoImage) {
|
||||
if (geoImage._isRendering) {
|
||||
geoImage._creationProceeding = false;
|
||||
geoImage._isRendering = false;
|
||||
var arr;
|
||||
if (geoImage._animate) {
|
||||
arr = this._animate;
|
||||
} else {
|
||||
arr = this._queue;
|
||||
}
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (arr[i].isEqual(geoImage)) {
|
||||
arr.splice(i, 1);
|
||||
return;
|
||||
var grid = new Float32Array((gs + 1) * (gs + 1) * 2);
|
||||
var k = 0;
|
||||
for (let i = 0; i <= gs; i++) {
|
||||
var P03i = new LonLat(c[0].lon + i * v03.lon, c[0].lat + i * v03.lat),
|
||||
P12i = new LonLat(c[1].lon + i * v12.lon, c[1].lat + i * v12.lat);
|
||||
for (let j = 0; j <= gs; j++) {
|
||||
var P01j = new LonLat(c[0].lon + j * v01.lon, c[0].lat + j * v01.lat),
|
||||
P32j = new LonLat(c[3].lon + j * v32.lon, c[3].lat + j * v32.lat);
|
||||
var xx = utils.getLinesIntersectionLonLat(P03i, P12i, P01j, P32j);
|
||||
grid[k++] = xx.lon;
|
||||
grid[k++] = xx.lat;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
GeoImageCreator.prototype._initBuffers = function () {
|
||||
if (toMerc) {
|
||||
for (let i = 0; i < grid.length; i += 2) {
|
||||
let c = new LonLat(grid[i], grid[i + 1]).forwardMercator();
|
||||
grid[i] = c.lon;
|
||||
grid[i + 1] = c.lat;
|
||||
}
|
||||
}
|
||||
return this._planet.renderer.handler.createArrayBuffer(grid, 2, grid.length / 2);
|
||||
};
|
||||
|
||||
let h = this._planet.renderer.handler;
|
||||
frame() {
|
||||
var i = this.MAX_FRAMES;
|
||||
while (i-- && this._queue.length) {
|
||||
var q = this._queue.shift();
|
||||
q._isRendering = false;
|
||||
q.rendering();
|
||||
}
|
||||
|
||||
this._framebuffer = new Framebuffer(h, { width: 2, height: 2, useDepth: false });
|
||||
this._framebuffer.init();
|
||||
i = this._animate.length;
|
||||
while (i--) {
|
||||
this._animate[i].rendering();
|
||||
}
|
||||
};
|
||||
|
||||
this._framebufferMercProj = new Framebuffer(h, { width: 2, height: 2, useDepth: false });
|
||||
this._framebufferMercProj.init();
|
||||
add(geoImage) {
|
||||
if (!geoImage._isRendering) {
|
||||
geoImage._isRendering = true;
|
||||
if (geoImage._animate) {
|
||||
this._animate.push(geoImage);
|
||||
} else {
|
||||
this._queue.push(geoImage);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let gs = Math.log2(this._gridSize);
|
||||
remove(geoImage) {
|
||||
if (geoImage._isRendering) {
|
||||
geoImage._creationProceeding = false;
|
||||
geoImage._isRendering = false;
|
||||
var arr;
|
||||
if (geoImage._animate) {
|
||||
arr = this._animate;
|
||||
} else {
|
||||
arr = this._queue;
|
||||
}
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (arr[i].isEqual(geoImage)) {
|
||||
arr.splice(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this._texCoordsBuffer = this._planet._textureCoordsBufferCache[gs];
|
||||
_initBuffers() {
|
||||
|
||||
this._indexBuffer = this._planet._indexesCache[gs][gs][gs][gs][gs].buffer;
|
||||
let h = this._planet.renderer.handler;
|
||||
|
||||
this._quadTexCoordsBuffer = h.createArrayBuffer(new Float32Array([0, 1, 1, 1, 0, 0, 1, 0]), 2, 4);
|
||||
this._quadVertexBuffer = h.createArrayBuffer(new Float32Array([-1, 1, 1, 1, -1, -1, 1, -1]), 2, 4);
|
||||
};
|
||||
this._framebuffer = new Framebuffer(h, { width: 2, height: 2, useDepth: false });
|
||||
this._framebuffer.init();
|
||||
|
||||
GeoImageCreator.prototype._initShaders = function () {
|
||||
this._framebufferMercProj = new Framebuffer(h, { width: 2, height: 2, useDepth: false });
|
||||
this._framebufferMercProj.init();
|
||||
|
||||
this._planet.renderer.handler.addProgram(new Program("geoImageTransform", {
|
||||
uniforms: {
|
||||
sourceTexture: { type: types.SAMPLER2D },
|
||||
extentParams: { type: types.VEC4 }
|
||||
},
|
||||
attributes: {
|
||||
corners: { type: types.VEC2, enableArray: true },
|
||||
texCoords: { type: types.VEC2, enableArray: true }
|
||||
},
|
||||
vertexShader: `attribute vec2 corners;
|
||||
let gs = Math.log2(this._gridSize);
|
||||
|
||||
this._texCoordsBuffer = this._planet._textureCoordsBufferCache[gs];
|
||||
|
||||
this._indexBuffer = this._planet._indexesCache[gs][gs][gs][gs][gs].buffer;
|
||||
|
||||
this._quadTexCoordsBuffer = h.createArrayBuffer(new Float32Array([0, 1, 1, 1, 0, 0, 1, 0]), 2, 4);
|
||||
this._quadVertexBuffer = h.createArrayBuffer(new Float32Array([-1, 1, 1, 1, -1, -1, 1, -1]), 2, 4);
|
||||
};
|
||||
|
||||
_initShaders() {
|
||||
|
||||
this._planet.renderer.handler.addProgram(new Program("geoImageTransform", {
|
||||
uniforms: {
|
||||
sourceTexture: { type: types.SAMPLER2D },
|
||||
extentParams: { type: types.VEC4 }
|
||||
},
|
||||
attributes: {
|
||||
corners: { type: types.VEC2, enableArray: true },
|
||||
texCoords: { type: types.VEC2, enableArray: true }
|
||||
},
|
||||
vertexShader: `attribute vec2 corners;
|
||||
attribute vec2 texCoords;
|
||||
varying vec2 v_texCoords;
|
||||
uniform vec4 extentParams;
|
||||
@ -145,14 +147,14 @@ GeoImageCreator.prototype._initShaders = function () {
|
||||
v_texCoords = texCoords;
|
||||
gl_Position = vec4((-1.0 + (corners - extentParams.xy) * extentParams.zw) * vec2(1.0, -1.0), 0.0, 1.0);
|
||||
}`,
|
||||
fragmentShader:
|
||||
`precision highp float;
|
||||
fragmentShader:
|
||||
`precision highp float;
|
||||
uniform sampler2D sourceTexture;
|
||||
varying vec2 v_texCoords;
|
||||
void main () {
|
||||
gl_FragColor = texture2D(sourceTexture, v_texCoords);
|
||||
}`
|
||||
}));
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
export { GeoImageCreator };
|
||||
}
|
||||
@ -14,99 +14,100 @@ if (window && !('createImageBitmap' in window)) {
|
||||
};
|
||||
};
|
||||
|
||||
const Loader = function (maxRequests = 12) {
|
||||
export class Loader {
|
||||
|
||||
this.MAX_REQUESTS = maxRequests;
|
||||
constructor(maxRequests = 12) {
|
||||
|
||||
this.events = new Events(["loadend"]);
|
||||
this.MAX_REQUESTS = maxRequests;
|
||||
|
||||
this._loading = 0;
|
||||
this.events = new Events(["loadend"]);
|
||||
|
||||
this._queue = [];//new QueueArray();
|
||||
this._loading = 0;
|
||||
|
||||
this._promises = {
|
||||
'json': r => r.json(),
|
||||
'blob': r => r.blob(),
|
||||
'arrayBuffer': r => r.arrayBuffer(),
|
||||
'imageBitmap': r => r.blob().then(createImageBitmap),
|
||||
'text': r => r.text()
|
||||
this._queue = [];//new QueueArray();
|
||||
|
||||
this._promises = {
|
||||
'json': r => r.json(),
|
||||
'blob': r => r.blob(),
|
||||
'arrayBuffer': r => r.arrayBuffer(),
|
||||
'imageBitmap': r => r.blob().then(createImageBitmap),
|
||||
'text': r => r.text()
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Loader.prototype.load = function (params, callback) {
|
||||
this._queue.push({ 'params': params, 'callback': callback });
|
||||
this._exec();
|
||||
};
|
||||
load(params, callback) {
|
||||
this._queue.push({ 'params': params, 'callback': callback });
|
||||
this._exec();
|
||||
};
|
||||
|
||||
Loader.prototype.fetch = function (params) {
|
||||
return fetch(
|
||||
params.src,
|
||||
params.options || {})
|
||||
fetch(params) {
|
||||
return fetch(
|
||||
params.src,
|
||||
params.options || {})
|
||||
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw Error(`Unable to load '${params.src}'`);
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw Error(`Unable to load '${params.src}'`);
|
||||
}
|
||||
return this._promises[params.type || "blob"](response);
|
||||
})
|
||||
|
||||
.then(data => {
|
||||
return { 'status': "ready", 'data': data };
|
||||
|
||||
})
|
||||
|
||||
.catch(err => {
|
||||
return { 'status': "error", 'msg': err.toString() };
|
||||
});
|
||||
};
|
||||
|
||||
_exec() {
|
||||
|
||||
if (this._queue.length > 0 && this._loading < this.MAX_REQUESTS) {
|
||||
|
||||
let q = this._queue.pop(),
|
||||
p = q.params;
|
||||
|
||||
if (!p.filter || p.filter(p)) {
|
||||
|
||||
this._loading++;
|
||||
|
||||
return fetch(p.src, p.options || {})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw Error(`Unable to load '${p.src}'`);
|
||||
}
|
||||
return this._promises[p.type || "blob"](response);
|
||||
})
|
||||
.then(data => {
|
||||
this._loading--;
|
||||
q.callback({ 'status': "ready", 'data': data });
|
||||
this._exec();
|
||||
})
|
||||
.catch(err => {
|
||||
this._loading--;
|
||||
q.callback({ 'status': "error", 'msg': err.toString() });
|
||||
this._exec();
|
||||
});
|
||||
|
||||
} else {
|
||||
q.callback({ 'status': "abort" });
|
||||
this._exec();
|
||||
}
|
||||
return this._promises[params.type || "blob"](response);
|
||||
})
|
||||
|
||||
.then(data => {
|
||||
return { 'status': "ready", 'data': data };
|
||||
|
||||
})
|
||||
|
||||
.catch(err => {
|
||||
return { 'status': "error", 'msg': err.toString() };
|
||||
});
|
||||
};
|
||||
|
||||
Loader.prototype._exec = function () {
|
||||
|
||||
if (this._queue.length > 0 && this._loading < this.MAX_REQUESTS) {
|
||||
|
||||
let q = this._queue.pop(),
|
||||
p = q.params;
|
||||
|
||||
if (!p.filter || p.filter(p)) {
|
||||
|
||||
this._loading++;
|
||||
|
||||
return fetch(p.src, p.options || {})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw Error(`Unable to load '${p.src}'`);
|
||||
}
|
||||
return this._promises[p.type || "blob"](response);
|
||||
})
|
||||
.then(data => {
|
||||
this._loading--;
|
||||
q.callback({ 'status': "ready", 'data': data });
|
||||
this._exec();
|
||||
})
|
||||
.catch(err => {
|
||||
this._loading--;
|
||||
q.callback({ 'status': "error", 'msg': err.toString() });
|
||||
this._exec();
|
||||
});
|
||||
|
||||
} else {
|
||||
q.callback({ 'status': "abort" });
|
||||
this._exec();
|
||||
} else if (this._loading === 0) {
|
||||
this.events.dispatch(this.events.loadend);
|
||||
}
|
||||
} else if (this._loading === 0) {
|
||||
this.events.dispatch(this.events.loadend);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Loader.prototype.abort = function () {
|
||||
//this._queue.each(e => e.callback({ 'status': "abort" }));
|
||||
//this._queue.clear();
|
||||
abort() {
|
||||
//this._queue.each(e => e.callback({ 'status': "abort" }));
|
||||
//this._queue.clear();
|
||||
|
||||
for (let i = 0, len = this._queue.length; i < len; i++) {
|
||||
this._queue[i].callback({ 'status': "abort" });
|
||||
this._queue[i] = null;
|
||||
}
|
||||
this._queue = [];
|
||||
};
|
||||
|
||||
export { Loader };
|
||||
for (let i = 0, len = this._queue.length; i < len; i++) {
|
||||
this._queue[i].callback({ 'status': "abort" });
|
||||
this._queue[i] = null;
|
||||
}
|
||||
this._queue = [];
|
||||
};
|
||||
}
|
||||
@ -11,68 +11,70 @@ import { Program } from "../webgl/Program.js";
|
||||
import { types } from "../webgl/types.js";
|
||||
import { QueueArray } from "../QueueArray.js";
|
||||
|
||||
const NormalMapCreator = function (planet, options) {
|
||||
options = options || {};
|
||||
export class NormalMapCreator {
|
||||
|
||||
this._minTabelSize = options.minTableSize || 1;
|
||||
this._maxTableSize = options.maxTableSize || 8;
|
||||
constructor(planet, options) {
|
||||
options = options || {};
|
||||
|
||||
this._planet = planet;
|
||||
this._handler = planet.renderer.handler;
|
||||
this._verticesBufferArray = [];
|
||||
this._indexBufferArray = [];
|
||||
this._positionBuffer = null;
|
||||
this._framebuffer = null;
|
||||
this._normalMapVerticesTexture = null;
|
||||
this._minTabelSize = options.minTableSize || 1;
|
||||
this._maxTableSize = options.maxTableSize || 8;
|
||||
|
||||
this._width = options.width || 128;
|
||||
this._height = options.height || 128;
|
||||
this._planet = planet;
|
||||
this._handler = planet.renderer.handler;
|
||||
this._verticesBufferArray = [];
|
||||
this._indexBufferArray = [];
|
||||
this._positionBuffer = null;
|
||||
this._framebuffer = null;
|
||||
this._normalMapVerticesTexture = null;
|
||||
|
||||
this._queue = new QueueArray(1024);
|
||||
this._width = options.width || 128;
|
||||
this._height = options.height || 128;
|
||||
|
||||
this._lock = new Lock();
|
||||
this._queue = new QueueArray(1024);
|
||||
|
||||
this._init();
|
||||
};
|
||||
this._lock = new Lock();
|
||||
|
||||
NormalMapCreator.prototype._init = function () {
|
||||
var isWebkit = false; //('WebkitAppearance' in document.documentElement.style) && !/^((?!chrome).)*safari/i.test(navigator.userAgent);
|
||||
this._init();
|
||||
};
|
||||
|
||||
/*==================================================================================
|
||||
* http://www.sunsetlakesoftware.com/2013/10/21/optimizing-gaussian-blurs-mobile-gpu
|
||||
*=================================================================================*/
|
||||
var normalMapBlur = new Program("normalMapBlur", {
|
||||
attributes: {
|
||||
a_position: { type: types.VEC2, enableArray: true }
|
||||
},
|
||||
uniforms: {
|
||||
s_texture: { type: types.SAMPLER2D }
|
||||
},
|
||||
vertexShader:
|
||||
`attribute vec2 a_position;
|
||||
_init() {
|
||||
var isWebkit = false; //('WebkitAppearance' in document.documentElement.style) && !/^((?!chrome).)*safari/i.test(navigator.userAgent);
|
||||
|
||||
/*==================================================================================
|
||||
* http://www.sunsetlakesoftware.com/2013/10/21/optimizing-gaussian-blurs-mobile-gpu
|
||||
*=================================================================================*/
|
||||
var normalMapBlur = new Program("normalMapBlur", {
|
||||
attributes: {
|
||||
a_position: { type: types.VEC2, enableArray: true }
|
||||
},
|
||||
uniforms: {
|
||||
s_texture: { type: types.SAMPLER2D }
|
||||
},
|
||||
vertexShader:
|
||||
`attribute vec2 a_position;
|
||||
attribute vec2 a_texCoord;
|
||||
|
||||
varying vec2 blurCoordinates[5];
|
||||
|
||||
void main() {
|
||||
vec2 vt = a_position * 0.5 + 0.5;` +
|
||||
(isWebkit ? "vt.y = 1.0 - vt.y; " : " ") +
|
||||
`gl_Position = vec4(a_position, 0.0, 1.0);
|
||||
(isWebkit ? "vt.y = 1.0 - vt.y; " : " ") +
|
||||
`gl_Position = vec4(a_position, 0.0, 1.0);
|
||||
blurCoordinates[0] = vt;
|
||||
blurCoordinates[1] = vt + ` +
|
||||
(1.0 / this._width) * 1.407333 +
|
||||
";" +
|
||||
"blurCoordinates[2] = vt - " +
|
||||
(1.0 / this._height) * 1.407333 +
|
||||
";" +
|
||||
"blurCoordinates[3] = vt + " +
|
||||
(1.0 / this._width) * 3.294215 +
|
||||
";" +
|
||||
"blurCoordinates[4] = vt - " +
|
||||
(1.0 / this._height) * 3.294215 +
|
||||
";" +
|
||||
"}",
|
||||
fragmentShader: `precision lowp float;
|
||||
(1.0 / this._width) * 1.407333 +
|
||||
";" +
|
||||
"blurCoordinates[2] = vt - " +
|
||||
(1.0 / this._height) * 1.407333 +
|
||||
";" +
|
||||
"blurCoordinates[3] = vt + " +
|
||||
(1.0 / this._width) * 3.294215 +
|
||||
";" +
|
||||
"blurCoordinates[4] = vt - " +
|
||||
(1.0 / this._height) * 3.294215 +
|
||||
";" +
|
||||
"}",
|
||||
fragmentShader: `precision lowp float;
|
||||
uniform sampler2D s_texture;
|
||||
|
||||
varying vec2 blurCoordinates[5];
|
||||
@ -91,14 +93,14 @@ NormalMapCreator.prototype._init = function () {
|
||||
//}
|
||||
gl_FragColor = sum;
|
||||
}`
|
||||
});
|
||||
});
|
||||
|
||||
var normalMap = new Program("normalMap", {
|
||||
attributes: {
|
||||
a_position: { type: types.VEC2, enableArray: true },
|
||||
a_normal: { type: types.VEC3, enableArray: true }
|
||||
},
|
||||
vertexShader: `attribute vec2 a_position;
|
||||
var normalMap = new Program("normalMap", {
|
||||
attributes: {
|
||||
a_position: { type: types.VEC2, enableArray: true },
|
||||
a_normal: { type: types.VEC3, enableArray: true }
|
||||
},
|
||||
vertexShader: `attribute vec2 a_position;
|
||||
attribute vec3 a_normal;
|
||||
|
||||
varying vec3 v_color;
|
||||
@ -107,238 +109,212 @@ NormalMapCreator.prototype._init = function () {
|
||||
gl_Position = vec4(a_position, 0, 1);
|
||||
v_color = normalize(a_normal) * 0.5 + 0.5;
|
||||
}`,
|
||||
fragmentShader: `precision highp float;
|
||||
fragmentShader: `precision highp float;
|
||||
|
||||
varying vec3 v_color;
|
||||
|
||||
void main () {
|
||||
gl_FragColor = vec4(v_color, 1.0);
|
||||
}`
|
||||
});
|
||||
});
|
||||
|
||||
this._handler.addProgram(normalMapBlur);
|
||||
this._handler.addProgram(normalMap);
|
||||
this._handler.addProgram(normalMapBlur);
|
||||
this._handler.addProgram(normalMap);
|
||||
|
||||
//create hidden handler buffer
|
||||
this._framebuffer = new Framebuffer(this._handler, {
|
||||
width: this._width,
|
||||
height: this._height,
|
||||
useDepth: false
|
||||
});
|
||||
//create hidden handler buffer
|
||||
this._framebuffer = new Framebuffer(this._handler, {
|
||||
width: this._width,
|
||||
height: this._height,
|
||||
useDepth: false
|
||||
});
|
||||
|
||||
this._framebuffer.init();
|
||||
this._framebuffer.init();
|
||||
|
||||
this._normalMapVerticesTexture = this._handler.createEmptyTexture_l(this._width, this._height);
|
||||
this._normalMapVerticesTexture = this._handler.createEmptyTexture_l(this._width, this._height);
|
||||
|
||||
//create vertices hasharray for different grid size segments from 2^4(16) to 2^7(128)
|
||||
for (var p = this._minTabelSize; p <= this._maxTableSize; p++) {
|
||||
var gs = Math.pow(2, p);
|
||||
var gs2 = gs / 2;
|
||||
var vertices = new Float32Array((gs + 1) * (gs + 1) * 2);
|
||||
//create vertices hasharray for different grid size segments from 2^4(16) to 2^7(128)
|
||||
for (var p = this._minTabelSize; p <= this._maxTableSize; p++) {
|
||||
var gs = Math.pow(2, p);
|
||||
var gs2 = gs / 2;
|
||||
var vertices = new Float32Array((gs + 1) * (gs + 1) * 2);
|
||||
|
||||
for (var i = 0; i <= gs; i++) {
|
||||
for (var j = 0; j <= gs; j++) {
|
||||
let ind = (i * (gs + 1) + j) * 2;
|
||||
vertices[ind] = -1 + j / gs2;
|
||||
vertices[ind + 1] = -1 + i / gs2;
|
||||
for (var i = 0; i <= gs; i++) {
|
||||
for (var j = 0; j <= gs; j++) {
|
||||
let ind = (i * (gs + 1) + j) * 2;
|
||||
vertices[ind] = -1 + j / gs2;
|
||||
vertices[ind + 1] = -1 + i / gs2;
|
||||
}
|
||||
}
|
||||
|
||||
this._verticesBufferArray[gs] = this._handler.createArrayBuffer(
|
||||
vertices,
|
||||
2,
|
||||
vertices.length / 2
|
||||
);
|
||||
this._indexBufferArray[gs] =
|
||||
this._planet._indexesCache[Math.log2(gs)][Math.log2(gs)][Math.log2(gs)][Math.log2(gs)][
|
||||
Math.log2(gs)
|
||||
].buffer;
|
||||
}
|
||||
|
||||
this._verticesBufferArray[gs] = this._handler.createArrayBuffer(
|
||||
vertices,
|
||||
2,
|
||||
vertices.length / 2
|
||||
);
|
||||
this._indexBufferArray[gs] =
|
||||
this._planet._indexesCache[Math.log2(gs)][Math.log2(gs)][Math.log2(gs)][Math.log2(gs)][
|
||||
Math.log2(gs)
|
||||
].buffer;
|
||||
}
|
||||
//create 2d screen square buffer
|
||||
var positions = new Float32Array([-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0]);
|
||||
|
||||
//create 2d screen square buffer
|
||||
var positions = new Float32Array([-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0]);
|
||||
this._positionBuffer = this._handler.createArrayBuffer(positions, 2, positions.length / 2);
|
||||
};
|
||||
|
||||
this._positionBuffer = this._handler.createArrayBuffer(positions, 2, positions.length / 2);
|
||||
};
|
||||
_drawNormalMapBlur(segment) {
|
||||
var normals = segment.normalMapNormals;
|
||||
if (
|
||||
segment.node &&
|
||||
segment.node.getState() !== quadTree.NOTRENDERING &&
|
||||
normals &&
|
||||
normals.length
|
||||
) {
|
||||
var size = normals.length / 3;
|
||||
var gridSize = Math.sqrt(size) - 1;
|
||||
|
||||
NormalMapCreator.prototype._drawNormalMapBlur = function (segment) {
|
||||
var normals = segment.normalMapNormals;
|
||||
if (
|
||||
segment.node &&
|
||||
segment.node.getState() !== quadTree.NOTRENDERING &&
|
||||
normals &&
|
||||
normals.length
|
||||
) {
|
||||
var size = normals.length / 3;
|
||||
var gridSize = Math.sqrt(size) - 1;
|
||||
let indBuf = this._verticesBufferArray[gridSize];
|
||||
|
||||
let indBuf = this._verticesBufferArray[gridSize];
|
||||
if (indBuf) {
|
||||
if (segment.planet.terrain.equalizeNormals) {
|
||||
segment._normalMapEdgeEqualize(quadTree.N);
|
||||
segment._normalMapEdgeEqualize(quadTree.S);
|
||||
segment._normalMapEdgeEqualize(quadTree.W);
|
||||
segment._normalMapEdgeEqualize(quadTree.E);
|
||||
}
|
||||
|
||||
if (indBuf) {
|
||||
if (segment.planet.terrain.equalizeNormals) {
|
||||
segment._normalMapEdgeEqualize(quadTree.N);
|
||||
segment._normalMapEdgeEqualize(quadTree.S);
|
||||
segment._normalMapEdgeEqualize(quadTree.W);
|
||||
segment._normalMapEdgeEqualize(quadTree.E);
|
||||
var outTexture = segment.normalMapTexturePtr;
|
||||
|
||||
var h = this._handler;
|
||||
var gl = h.gl;
|
||||
|
||||
var _normalsBuffer = h.createArrayBuffer(normals, 3, size, gl.DYNAMIC_DRAW);
|
||||
|
||||
var f = this._framebuffer;
|
||||
var p = h.programs.normalMap;
|
||||
var sha = p._program.attributes;
|
||||
|
||||
f.bindOutputTexture(this._normalMapVerticesTexture);
|
||||
|
||||
p.activate();
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, indBuf);
|
||||
gl.vertexAttribPointer(sha.a_position, indBuf.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, _normalsBuffer);
|
||||
gl.vertexAttribPointer(sha.a_normal, _normalsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBufferArray[gridSize]);
|
||||
gl.drawElements(
|
||||
gl.TRIANGLE_STRIP,
|
||||
this._indexBufferArray[gridSize].numItems,
|
||||
gl.UNSIGNED_INT,
|
||||
0
|
||||
);
|
||||
|
||||
gl.deleteBuffer(_normalsBuffer);
|
||||
|
||||
//
|
||||
// blur pass
|
||||
//
|
||||
f.bindOutputTexture(outTexture);
|
||||
|
||||
p = h.programs.normalMapBlur;
|
||||
|
||||
p.activate();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
|
||||
gl.vertexAttribPointer(
|
||||
p._program.attributes.a_position,
|
||||
this._positionBuffer.itemSize,
|
||||
gl.FLOAT,
|
||||
false,
|
||||
0,
|
||||
0
|
||||
);
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this._normalMapVerticesTexture);
|
||||
gl.uniform1i(p._program.uniforms.s_texture, 0);
|
||||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, this._positionBuffer.numItems);
|
||||
return true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
var outTexture = segment.normalMapTexturePtr;
|
||||
_drawNormalMapNoBlur(segment) {
|
||||
var normals = segment.normalMapNormals;
|
||||
if (
|
||||
segment.node &&
|
||||
segment.node.getState() !== quadTree.NOTRENDERING &&
|
||||
normals &&
|
||||
normals.length
|
||||
) {
|
||||
var size = normals.length / 3;
|
||||
var gridSize = Math.sqrt(size) - 1;
|
||||
|
||||
var h = this._handler;
|
||||
var gl = h.gl;
|
||||
let indBuf = this._verticesBufferArray[gridSize];
|
||||
|
||||
var _normalsBuffer = h.createArrayBuffer(normals, 3, size, gl.DYNAMIC_DRAW);
|
||||
if (indBuf) {
|
||||
if (segment.planet.terrain.equalizeNormals) {
|
||||
segment._normalMapEdgeEqualize(quadTree.N);
|
||||
segment._normalMapEdgeEqualize(quadTree.S);
|
||||
segment._normalMapEdgeEqualize(quadTree.W);
|
||||
segment._normalMapEdgeEqualize(quadTree.E);
|
||||
}
|
||||
|
||||
var f = this._framebuffer;
|
||||
var p = h.programs.normalMap;
|
||||
var sha = p._program.attributes;
|
||||
var outTexture = segment.normalMapTexturePtr;
|
||||
|
||||
f.bindOutputTexture(this._normalMapVerticesTexture);
|
||||
var h = this._handler;
|
||||
var gl = h.gl;
|
||||
|
||||
p.activate();
|
||||
var _normalsBuffer = h.createArrayBuffer(normals, 3, size, gl.DYNAMIC_DRAW);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, indBuf);
|
||||
gl.vertexAttribPointer(sha.a_position, indBuf.itemSize, gl.FLOAT, false, 0, 0);
|
||||
var f = this._framebuffer;
|
||||
var p = h.programs.normalMap;
|
||||
var sha = p._program.attributes;
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, _normalsBuffer);
|
||||
gl.vertexAttribPointer(sha.a_normal, _normalsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
f.bindOutputTexture(outTexture);
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBufferArray[gridSize]);
|
||||
gl.drawElements(
|
||||
gl.TRIANGLE_STRIP,
|
||||
this._indexBufferArray[gridSize].numItems,
|
||||
gl.UNSIGNED_INT,
|
||||
0
|
||||
);
|
||||
p.activate();
|
||||
|
||||
gl.deleteBuffer(_normalsBuffer);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, indBuf);
|
||||
gl.vertexAttribPointer(sha.a_position, indBuf.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
//
|
||||
// blur pass
|
||||
//
|
||||
f.bindOutputTexture(outTexture);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, _normalsBuffer);
|
||||
gl.vertexAttribPointer(sha.a_normal, _normalsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
p = h.programs.normalMapBlur;
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBufferArray[gridSize]);
|
||||
gl.drawElements(
|
||||
gl.TRIANGLE_STRIP,
|
||||
this._indexBufferArray[gridSize].numItems,
|
||||
gl.UNSIGNED_INT,
|
||||
0
|
||||
);
|
||||
|
||||
p.activate();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
|
||||
gl.vertexAttribPointer(
|
||||
p._program.attributes.a_position,
|
||||
this._positionBuffer.itemSize,
|
||||
gl.FLOAT,
|
||||
false,
|
||||
0,
|
||||
0
|
||||
);
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this._normalMapVerticesTexture);
|
||||
gl.uniform1i(p._program.uniforms.s_texture, 0);
|
||||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, this._positionBuffer.numItems);
|
||||
return true;
|
||||
gl.deleteBuffer(_normalsBuffer);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
_drawNormalMap(segment) {
|
||||
let t = segment.planet.terrain;
|
||||
|
||||
if (t.isBlur(segment)) {
|
||||
return this._drawNormalMapBlur(segment);
|
||||
} else {
|
||||
return true;
|
||||
return this._drawNormalMapNoBlur(segment);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
};
|
||||
|
||||
NormalMapCreator.prototype._drawNormalMapNoBlur = function (segment) {
|
||||
var normals = segment.normalMapNormals;
|
||||
if (
|
||||
segment.node &&
|
||||
segment.node.getState() !== quadTree.NOTRENDERING &&
|
||||
normals &&
|
||||
normals.length
|
||||
) {
|
||||
var size = normals.length / 3;
|
||||
var gridSize = Math.sqrt(size) - 1;
|
||||
|
||||
let indBuf = this._verticesBufferArray[gridSize];
|
||||
|
||||
if (indBuf) {
|
||||
if (segment.planet.terrain.equalizeNormals) {
|
||||
segment._normalMapEdgeEqualize(quadTree.N);
|
||||
segment._normalMapEdgeEqualize(quadTree.S);
|
||||
segment._normalMapEdgeEqualize(quadTree.W);
|
||||
segment._normalMapEdgeEqualize(quadTree.E);
|
||||
}
|
||||
|
||||
var outTexture = segment.normalMapTexturePtr;
|
||||
|
||||
var h = this._handler;
|
||||
var gl = h.gl;
|
||||
|
||||
var _normalsBuffer = h.createArrayBuffer(normals, 3, size, gl.DYNAMIC_DRAW);
|
||||
|
||||
var f = this._framebuffer;
|
||||
var p = h.programs.normalMap;
|
||||
var sha = p._program.attributes;
|
||||
|
||||
f.bindOutputTexture(outTexture);
|
||||
|
||||
p.activate();
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, indBuf);
|
||||
gl.vertexAttribPointer(sha.a_position, indBuf.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, _normalsBuffer);
|
||||
gl.vertexAttribPointer(sha.a_normal, _normalsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBufferArray[gridSize]);
|
||||
gl.drawElements(
|
||||
gl.TRIANGLE_STRIP,
|
||||
this._indexBufferArray[gridSize].numItems,
|
||||
gl.UNSIGNED_INT,
|
||||
0
|
||||
);
|
||||
|
||||
gl.deleteBuffer(_normalsBuffer);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
NormalMapCreator.prototype._drawNormalMap = function (segment) {
|
||||
let t = segment.planet.terrain;
|
||||
|
||||
if (t.isBlur(segment)) {
|
||||
return this._drawNormalMapBlur(segment);
|
||||
} else {
|
||||
return this._drawNormalMapNoBlur(segment);
|
||||
}
|
||||
};
|
||||
|
||||
NormalMapCreator.prototype.drawSingle = function (segment) {
|
||||
var h = this._handler,
|
||||
gl = h.gl;
|
||||
|
||||
this._framebuffer.activate();
|
||||
|
||||
gl.disable(gl.CULL_FACE);
|
||||
gl.disable(gl.DEPTH_TEST);
|
||||
|
||||
if (segment.terrainReady && this._drawNormalMap(segment)) {
|
||||
segment.normalMapReady = true;
|
||||
segment.normalMapTexture = segment.normalMapTexturePtr;
|
||||
segment.normalMapTextureBias[0] = 0;
|
||||
segment.normalMapTextureBias[1] = 0;
|
||||
segment.normalMapTextureBias[2] = 1;
|
||||
}
|
||||
segment._inTheQueue = false;
|
||||
|
||||
gl.disable(gl.BLEND);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.enable(gl.CULL_FACE);
|
||||
|
||||
this._framebuffer.deactivate();
|
||||
};
|
||||
|
||||
NormalMapCreator.prototype.frame = function () {
|
||||
if (this._queue.length) {
|
||||
drawSingle(segment) {
|
||||
var h = this._handler,
|
||||
gl = h.gl;
|
||||
|
||||
@ -347,65 +323,91 @@ NormalMapCreator.prototype.frame = function () {
|
||||
gl.disable(gl.CULL_FACE);
|
||||
gl.disable(gl.DEPTH_TEST);
|
||||
|
||||
var deltaTime = 0,
|
||||
startTime = window.performance.now();
|
||||
|
||||
while (this._lock.isFree() && this._queue.length && deltaTime < 0.25) {
|
||||
var segment = this._queue.shift();
|
||||
if (segment.terrainReady && this._drawNormalMap(segment)) {
|
||||
segment.normalMapReady = true;
|
||||
segment.normalMapTexture = segment.normalMapTexturePtr;
|
||||
segment.normalMapTextureBias[0] = 0;
|
||||
segment.normalMapTextureBias[1] = 0;
|
||||
segment.normalMapTextureBias[2] = 1;
|
||||
}
|
||||
segment._inTheQueue = false;
|
||||
deltaTime = window.performance.now() - startTime;
|
||||
if (segment.terrainReady && this._drawNormalMap(segment)) {
|
||||
segment.normalMapReady = true;
|
||||
segment.normalMapTexture = segment.normalMapTexturePtr;
|
||||
segment.normalMapTextureBias[0] = 0;
|
||||
segment.normalMapTextureBias[1] = 0;
|
||||
segment.normalMapTextureBias[2] = 1;
|
||||
}
|
||||
segment._inTheQueue = false;
|
||||
|
||||
gl.disable(gl.BLEND);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.enable(gl.CULL_FACE);
|
||||
|
||||
this._framebuffer.deactivate();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
NormalMapCreator.prototype.queue = function (segment) {
|
||||
segment._inTheQueue = true;
|
||||
this._queue.push(segment);
|
||||
};
|
||||
frame() {
|
||||
if (this._queue.length) {
|
||||
var h = this._handler,
|
||||
gl = h.gl;
|
||||
|
||||
NormalMapCreator.prototype.unshift = function (segment) {
|
||||
segment._inTheQueue = true;
|
||||
this._queue.unshift(segment);
|
||||
};
|
||||
this._framebuffer.activate();
|
||||
|
||||
NormalMapCreator.prototype.remove = function (segment) {
|
||||
//...
|
||||
};
|
||||
gl.disable(gl.CULL_FACE);
|
||||
gl.disable(gl.DEPTH_TEST);
|
||||
|
||||
NormalMapCreator.prototype.clear = function () {
|
||||
while (this._queue.length) {
|
||||
var s = this._queue.pop();
|
||||
s._inTheQueue = false;
|
||||
}
|
||||
};
|
||||
var deltaTime = 0,
|
||||
startTime = window.performance.now();
|
||||
|
||||
/**
|
||||
* Set activity off
|
||||
* @public
|
||||
*/
|
||||
NormalMapCreator.prototype.lock = function (key) {
|
||||
this._lock.lock(key);
|
||||
};
|
||||
while (this._lock.isFree() && this._queue.length && deltaTime < 0.25) {
|
||||
var segment = this._queue.shift();
|
||||
if (segment.terrainReady && this._drawNormalMap(segment)) {
|
||||
segment.normalMapReady = true;
|
||||
segment.normalMapTexture = segment.normalMapTexturePtr;
|
||||
segment.normalMapTextureBias[0] = 0;
|
||||
segment.normalMapTextureBias[1] = 0;
|
||||
segment.normalMapTextureBias[2] = 1;
|
||||
}
|
||||
segment._inTheQueue = false;
|
||||
deltaTime = window.performance.now() - startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set activity on
|
||||
* @public
|
||||
*/
|
||||
NormalMapCreator.prototype.free = function (key) {
|
||||
this._lock.free(key);
|
||||
};
|
||||
gl.disable(gl.BLEND);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.enable(gl.CULL_FACE);
|
||||
|
||||
export { NormalMapCreator };
|
||||
this._framebuffer.deactivate();
|
||||
}
|
||||
};
|
||||
|
||||
queue(segment) {
|
||||
segment._inTheQueue = true;
|
||||
this._queue.push(segment);
|
||||
};
|
||||
|
||||
unshift(segment) {
|
||||
segment._inTheQueue = true;
|
||||
this._queue.unshift(segment);
|
||||
};
|
||||
|
||||
remove(segment) {
|
||||
//...
|
||||
};
|
||||
|
||||
clear() {
|
||||
while (this._queue.length) {
|
||||
var s = this._queue.pop();
|
||||
s._inTheQueue = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set activity off
|
||||
* @public
|
||||
*/
|
||||
lock(key) {
|
||||
this._lock.lock(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set activity on
|
||||
* @public
|
||||
*/
|
||||
free(key) {
|
||||
this._lock.free(key);
|
||||
};
|
||||
|
||||
}
|
||||
@ -4,53 +4,55 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import { doubleToTwoFloats2 } from '../math/coder.js';
|
||||
import * as quadTree from '../quadTree/quadTree.js';
|
||||
import { Framebuffer } from '../webgl/Framebuffer.js';
|
||||
import { Program } from '../webgl/Program.js';
|
||||
import { doubleToTwoFloats2 } from '../math/coder.js';
|
||||
|
||||
let tempArr = new Float32Array(2);
|
||||
|
||||
const VectorTileCreator = function (planet, maxFrames, width, height) {
|
||||
export class VectorTileCreator {
|
||||
|
||||
this._width = width || 256;
|
||||
this._height = height || 256;
|
||||
this._handler = planet.renderer.handler;
|
||||
this._planet = planet;
|
||||
this._framebuffer = null;
|
||||
this.MAX_FRAMES = maxFrames || 5;
|
||||
this._currentFrame = 0;
|
||||
this._queue = [];
|
||||
this._initialize();
|
||||
};
|
||||
constructor(planet, maxFrames, width, height) {
|
||||
|
||||
VectorTileCreator.prototype._initialize = function () {
|
||||
this._width = width || 256;
|
||||
this._height = height || 256;
|
||||
this._handler = planet.renderer.handler;
|
||||
this._planet = planet;
|
||||
this._framebuffer = null;
|
||||
this.MAX_FRAMES = maxFrames || 5;
|
||||
this._currentFrame = 0;
|
||||
this._queue = [];
|
||||
this._initialize();
|
||||
};
|
||||
|
||||
//Line
|
||||
if (!this._handler.programs.vectorTileLineRasterization) {
|
||||
this._handler.addProgram(new Program("vectorTileLineRasterization", {
|
||||
uniforms: {
|
||||
'viewport': "vec2",
|
||||
'thicknessOutline': "float",
|
||||
'alpha': "float",
|
||||
'extentParamsHigh': "vec4",
|
||||
'extentParamsLow': "vec4"
|
||||
},
|
||||
attributes: {
|
||||
'prevHigh': "vec2",
|
||||
'currentHigh': "vec2",
|
||||
'nextHigh': "vec2",
|
||||
_initialize() {
|
||||
|
||||
'prevLow': "vec2",
|
||||
'currentLow': "vec2",
|
||||
'nextLow': "vec2",
|
||||
//Line
|
||||
if (!this._handler.programs.vectorTileLineRasterization) {
|
||||
this._handler.addProgram(new Program("vectorTileLineRasterization", {
|
||||
uniforms: {
|
||||
'viewport': "vec2",
|
||||
'thicknessOutline': "float",
|
||||
'alpha': "float",
|
||||
'extentParamsHigh': "vec4",
|
||||
'extentParamsLow': "vec4"
|
||||
},
|
||||
attributes: {
|
||||
'prevHigh': "vec2",
|
||||
'currentHigh': "vec2",
|
||||
'nextHigh': "vec2",
|
||||
|
||||
'order': "float",
|
||||
'color': "vec4",
|
||||
'thickness': "float"
|
||||
},
|
||||
vertexShader:
|
||||
`attribute vec2 prevHigh;
|
||||
'prevLow': "vec2",
|
||||
'currentLow': "vec2",
|
||||
'nextLow': "vec2",
|
||||
|
||||
'order': "float",
|
||||
'color': "vec4",
|
||||
'thickness': "float"
|
||||
},
|
||||
vertexShader:
|
||||
`attribute vec2 prevHigh;
|
||||
attribute vec2 currentHigh;
|
||||
attribute vec2 nextHigh;
|
||||
|
||||
@ -133,29 +135,29 @@ VectorTileCreator.prototype._initialize = function () {
|
||||
}
|
||||
gl_Position = vec4(m.x, m.y, 0.0, 1.0);
|
||||
}`,
|
||||
fragmentShader: `precision highp float;
|
||||
fragmentShader: `precision highp float;
|
||||
uniform float alpha;
|
||||
varying vec4 vColor;
|
||||
void main() {
|
||||
gl_FragColor = vec4(vColor.rgb, alpha * vColor.a);
|
||||
}`
|
||||
}));
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
//Polygon
|
||||
if (!this._handler.programs.vectorTilePolygonRasterization) {
|
||||
this._handler.addProgram(new Program("vectorTilePolygonRasterization", {
|
||||
uniforms: {
|
||||
'extentParamsHigh': "vec4",
|
||||
'extentParamsLow': "vec4"
|
||||
},
|
||||
attributes: {
|
||||
'coordinatesHigh': "vec2",
|
||||
'coordinatesLow': "vec2",
|
||||
'colors': "vec4"
|
||||
},
|
||||
vertexShader:
|
||||
`attribute vec2 coordinatesHigh;
|
||||
//Polygon
|
||||
if (!this._handler.programs.vectorTilePolygonRasterization) {
|
||||
this._handler.addProgram(new Program("vectorTilePolygonRasterization", {
|
||||
uniforms: {
|
||||
'extentParamsHigh': "vec4",
|
||||
'extentParamsLow': "vec4"
|
||||
},
|
||||
attributes: {
|
||||
'coordinatesHigh': "vec2",
|
||||
'coordinatesLow': "vec2",
|
||||
'colors': "vec4"
|
||||
},
|
||||
vertexShader:
|
||||
`attribute vec2 coordinatesHigh;
|
||||
attribute vec2 coordinatesLow;
|
||||
attribute vec4 colors;
|
||||
uniform vec4 extentParamsHigh;
|
||||
@ -172,244 +174,243 @@ VectorTileCreator.prototype._initialize = function () {
|
||||
color = colors;
|
||||
gl_Position = vec4(proj(coordinatesHigh, coordinatesLow), 0.0, 1.0);
|
||||
}`,
|
||||
fragmentShader:
|
||||
`precision highp float;
|
||||
fragmentShader:
|
||||
`precision highp float;
|
||||
varying vec4 color;
|
||||
void main () {
|
||||
gl_FragColor = color;
|
||||
}`
|
||||
}));
|
||||
}
|
||||
|
||||
this._framebuffer = new Framebuffer(this._handler, {
|
||||
width: this._width,
|
||||
height: this._height,
|
||||
useDepth: false
|
||||
});
|
||||
this._framebuffer.init();
|
||||
};
|
||||
|
||||
VectorTileCreator.prototype.frame = function () {
|
||||
if (this._planet.layerLock.isFree() && this._queue.length) {
|
||||
var h = this._handler,
|
||||
gl = h.gl;
|
||||
|
||||
gl.disable(gl.CULL_FACE);
|
||||
gl.disable(gl.DEPTH_TEST);
|
||||
gl.enable(gl.BLEND);
|
||||
gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
|
||||
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
var hLine = h.programs.vectorTileLineRasterization,
|
||||
hPoly = h.programs.vectorTilePolygonRasterization;
|
||||
|
||||
var _w = this._width,
|
||||
_h = this._height,
|
||||
width = _w,
|
||||
height = _h,
|
||||
_w2 = width << 1,
|
||||
_h2 = height << 1;
|
||||
|
||||
var pickingMask = null,
|
||||
texture = null;
|
||||
|
||||
// var prevLayerId = -1;
|
||||
|
||||
var extentParams = new Float32Array(4);
|
||||
|
||||
var extentParamsHigh = new Float32Array(4);
|
||||
var extentParamsLow = new Float32Array(4);
|
||||
|
||||
var f = this._framebuffer.activate();
|
||||
|
||||
var deltaTime = 0,
|
||||
startTime = window.performance.now();
|
||||
|
||||
while (this._planet.layerLock.isFree() && this._queue.length && deltaTime < 0.25) {
|
||||
var material = this._queue.shift();
|
||||
if (material.isLoading && material.segment.node.getState() === quadTree.RENDERING) {
|
||||
|
||||
if (material.segment.tileZoom <= 3) {
|
||||
width = _w2;
|
||||
height = _h2;
|
||||
} else {
|
||||
width = _w;
|
||||
height = _h;
|
||||
}
|
||||
|
||||
texture = (material._updateTexture && material._updateTexture) || h.createEmptyTexture_l(width, height);
|
||||
|
||||
f.setSize(width, height);
|
||||
|
||||
f.bindOutputTexture(texture);
|
||||
|
||||
gl.clearColor(1.0, 1.0, 1.0, 0.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
var extent = material.segment.getExtentMerc();
|
||||
|
||||
doubleToTwoFloats2(extent.southWest.lon, tempArr);
|
||||
extentParamsHigh[0] = tempArr[0];
|
||||
extentParamsLow[0] = tempArr[1];
|
||||
|
||||
doubleToTwoFloats2(extent.southWest.lat, tempArr);
|
||||
extentParamsHigh[1] = tempArr[0];
|
||||
extentParamsLow[1] = tempArr[1];
|
||||
|
||||
extentParamsHigh[2] = 2.0 / extent.getWidth();
|
||||
extentParamsHigh[3] = 2.0 / extent.getHeight();
|
||||
|
||||
hPoly.activate();
|
||||
var sh = hPoly._program;
|
||||
var sha = sh.attributes,
|
||||
shu = sh.uniforms;
|
||||
|
||||
var geomHandler = material.layer._geometryHandler;
|
||||
|
||||
//=========================================
|
||||
//Polygon rendering
|
||||
//=========================================
|
||||
gl.uniform4fv(shu.extentParamsHigh, extentParamsHigh);
|
||||
gl.uniform4fv(shu.extentParamsLow, extentParamsLow);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._polyVerticesHighBufferMerc);
|
||||
gl.vertexAttribPointer(sha.coordinatesHigh, geomHandler._polyVerticesHighBufferMerc.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._polyVerticesLowBufferMerc);
|
||||
gl.vertexAttribPointer(sha.coordinatesLow, geomHandler._polyVerticesLowBufferMerc.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._polyColorsBuffer);
|
||||
gl.vertexAttribPointer(sha.colors, geomHandler._polyColorsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, geomHandler._polyIndexesBuffer);
|
||||
|
||||
gl.drawElements(gl.TRIANGLES, geomHandler._polyIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
|
||||
//Polygon picking PASS
|
||||
if (material.layer._pickingEnabled) {
|
||||
if (!material.pickingReady) {
|
||||
if (material._updatePickingMask) {
|
||||
pickingMask = material._updatePickingMask;
|
||||
} else {
|
||||
pickingMask = h.createEmptyTexture_n(width, height);
|
||||
}
|
||||
|
||||
f.bindOutputTexture(pickingMask);
|
||||
|
||||
gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._polyPickingColorsBuffer);
|
||||
gl.vertexAttribPointer(sha.colors, geomHandler._polyPickingColorsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.drawElements(gl.TRIANGLES, geomHandler._polyIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
} else {
|
||||
pickingMask = material.pickingMask;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================
|
||||
//Strokes and linestrings rendering
|
||||
//=========================================
|
||||
f.bindOutputTexture(texture);
|
||||
|
||||
hLine.activate();
|
||||
sh = hLine._program;
|
||||
sha = sh.attributes;
|
||||
shu = sh.uniforms;
|
||||
|
||||
gl.uniform2fv(shu.viewport, [width, height]);
|
||||
|
||||
gl.uniform4fv(shu.extentParamsHigh, extentParamsHigh);
|
||||
gl.uniform4fv(shu.extentParamsLow, extentParamsLow);
|
||||
|
||||
//vertex
|
||||
var mb = geomHandler._lineVerticesHighBufferMerc;
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, mb);
|
||||
|
||||
gl.vertexAttribPointer(sha.prevHigh, mb.itemSize, gl.FLOAT, false, 8, 0);
|
||||
gl.vertexAttribPointer(sha.currentHigh, mb.itemSize, gl.FLOAT, false, 8, 32);
|
||||
gl.vertexAttribPointer(sha.nextHigh, mb.itemSize, gl.FLOAT, false, 8, 64);
|
||||
|
||||
mb = geomHandler._lineVerticesLowBufferMerc;
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, mb);
|
||||
|
||||
gl.vertexAttribPointer(sha.prevLow, mb.itemSize, gl.FLOAT, false, 8, 0);
|
||||
gl.vertexAttribPointer(sha.currentLow, mb.itemSize, gl.FLOAT, false, 8, 32);
|
||||
gl.vertexAttribPointer(sha.nextLow, mb.itemSize, gl.FLOAT, false, 8, 64);
|
||||
|
||||
//order
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._lineOrdersBuffer);
|
||||
gl.vertexAttribPointer(sha.order, geomHandler._lineOrdersBuffer.itemSize, gl.FLOAT, false, 4, 0);
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, geomHandler._lineIndexesBuffer);
|
||||
|
||||
//PASS - stroke
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._lineStrokesBuffer);
|
||||
gl.vertexAttribPointer(sha.thickness, geomHandler._lineStrokesBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._lineStrokeColorsBuffer);
|
||||
gl.vertexAttribPointer(sha.color, geomHandler._lineStrokeColorsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
//Antialias pass
|
||||
gl.uniform1f(shu.thicknessOutline, 2);
|
||||
gl.uniform1f(shu.alpha, 0.54);
|
||||
gl.drawElements(gl.TRIANGLE_STRIP, geomHandler._lineIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
//
|
||||
//Aliased pass
|
||||
gl.uniform1f(shu.thicknessOutline, 1);
|
||||
gl.uniform1f(shu.alpha, 1.0);
|
||||
gl.drawElements(gl.TRIANGLE_STRIP, geomHandler._lineIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
|
||||
//PASS - inside line
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._lineThicknessBuffer);
|
||||
gl.vertexAttribPointer(sha.thickness, geomHandler._lineThicknessBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._lineColorsBuffer);
|
||||
gl.vertexAttribPointer(sha.color, geomHandler._lineColorsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
//Antialias pass
|
||||
gl.uniform1f(shu.thicknessOutline, 2);
|
||||
gl.uniform1f(shu.alpha, 0.54);
|
||||
gl.drawElements(gl.TRIANGLE_STRIP, geomHandler._lineIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
//
|
||||
//Aliased pass
|
||||
gl.uniform1f(shu.thicknessOutline, 1);
|
||||
gl.uniform1f(shu.alpha, 1.0);
|
||||
gl.drawElements(gl.TRIANGLE_STRIP, geomHandler._lineIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
|
||||
if (material.layer._pickingEnabled && !material.pickingReady) {
|
||||
f.bindOutputTexture(pickingMask);
|
||||
gl.uniform1f(shu.thicknessOutline, 8);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._linePickingColorsBuffer);
|
||||
gl.vertexAttribPointer(sha.color, geomHandler._linePickingColorsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
gl.drawElements(gl.TRIANGLE_STRIP, geomHandler._lineIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
material.applyTexture(texture, pickingMask);
|
||||
|
||||
} else {
|
||||
material.isLoading = false;
|
||||
}
|
||||
|
||||
deltaTime = window.performance.now() - startTime;
|
||||
// prevLayerId = material.layer._id;
|
||||
}));
|
||||
}
|
||||
|
||||
gl.disable(gl.BLEND);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.enable(gl.CULL_FACE);
|
||||
this._framebuffer = new Framebuffer(this._handler, {
|
||||
width: this._width,
|
||||
height: this._height,
|
||||
useDepth: false
|
||||
});
|
||||
this._framebuffer.init();
|
||||
};
|
||||
|
||||
f.deactivate();
|
||||
}
|
||||
};
|
||||
frame() {
|
||||
if (this._planet.layerLock.isFree() && this._queue.length) {
|
||||
var h = this._handler,
|
||||
gl = h.gl;
|
||||
|
||||
VectorTileCreator.prototype.add = function (material) {
|
||||
this._queue.push(material);
|
||||
};
|
||||
gl.disable(gl.CULL_FACE);
|
||||
gl.disable(gl.DEPTH_TEST);
|
||||
gl.enable(gl.BLEND);
|
||||
gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
|
||||
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
VectorTileCreator.prototype.remove = function (material) {
|
||||
//...
|
||||
};
|
||||
var hLine = h.programs.vectorTileLineRasterization,
|
||||
hPoly = h.programs.vectorTilePolygonRasterization;
|
||||
|
||||
export { VectorTileCreator };
|
||||
var _w = this._width,
|
||||
_h = this._height,
|
||||
width = _w,
|
||||
height = _h,
|
||||
_w2 = width << 1,
|
||||
_h2 = height << 1;
|
||||
|
||||
var pickingMask = null,
|
||||
texture = null;
|
||||
|
||||
// var prevLayerId = -1;
|
||||
|
||||
var extentParams = new Float32Array(4);
|
||||
|
||||
var extentParamsHigh = new Float32Array(4);
|
||||
var extentParamsLow = new Float32Array(4);
|
||||
|
||||
var f = this._framebuffer.activate();
|
||||
|
||||
var deltaTime = 0,
|
||||
startTime = window.performance.now();
|
||||
|
||||
while (this._planet.layerLock.isFree() && this._queue.length && deltaTime < 0.25) {
|
||||
var material = this._queue.shift();
|
||||
if (material.isLoading && material.segment.node.getState() === quadTree.RENDERING) {
|
||||
|
||||
if (material.segment.tileZoom <= 3) {
|
||||
width = _w2;
|
||||
height = _h2;
|
||||
} else {
|
||||
width = _w;
|
||||
height = _h;
|
||||
}
|
||||
|
||||
texture = (material._updateTexture && material._updateTexture) || h.createEmptyTexture_l(width, height);
|
||||
|
||||
f.setSize(width, height);
|
||||
|
||||
f.bindOutputTexture(texture);
|
||||
|
||||
gl.clearColor(1.0, 1.0, 1.0, 0.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
var extent = material.segment.getExtentMerc();
|
||||
|
||||
doubleToTwoFloats2(extent.southWest.lon, tempArr);
|
||||
extentParamsHigh[0] = tempArr[0];
|
||||
extentParamsLow[0] = tempArr[1];
|
||||
|
||||
doubleToTwoFloats2(extent.southWest.lat, tempArr);
|
||||
extentParamsHigh[1] = tempArr[0];
|
||||
extentParamsLow[1] = tempArr[1];
|
||||
|
||||
extentParamsHigh[2] = 2.0 / extent.getWidth();
|
||||
extentParamsHigh[3] = 2.0 / extent.getHeight();
|
||||
|
||||
hPoly.activate();
|
||||
var sh = hPoly._program;
|
||||
var sha = sh.attributes,
|
||||
shu = sh.uniforms;
|
||||
|
||||
var geomHandler = material.layer._geometryHandler;
|
||||
|
||||
//=========================================
|
||||
//Polygon rendering
|
||||
//=========================================
|
||||
gl.uniform4fv(shu.extentParamsHigh, extentParamsHigh);
|
||||
gl.uniform4fv(shu.extentParamsLow, extentParamsLow);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._polyVerticesHighBufferMerc);
|
||||
gl.vertexAttribPointer(sha.coordinatesHigh, geomHandler._polyVerticesHighBufferMerc.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._polyVerticesLowBufferMerc);
|
||||
gl.vertexAttribPointer(sha.coordinatesLow, geomHandler._polyVerticesLowBufferMerc.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._polyColorsBuffer);
|
||||
gl.vertexAttribPointer(sha.colors, geomHandler._polyColorsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, geomHandler._polyIndexesBuffer);
|
||||
|
||||
gl.drawElements(gl.TRIANGLES, geomHandler._polyIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
|
||||
//Polygon picking PASS
|
||||
if (material.layer._pickingEnabled) {
|
||||
if (!material.pickingReady) {
|
||||
if (material._updatePickingMask) {
|
||||
pickingMask = material._updatePickingMask;
|
||||
} else {
|
||||
pickingMask = h.createEmptyTexture_n(width, height);
|
||||
}
|
||||
|
||||
f.bindOutputTexture(pickingMask);
|
||||
|
||||
gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._polyPickingColorsBuffer);
|
||||
gl.vertexAttribPointer(sha.colors, geomHandler._polyPickingColorsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.drawElements(gl.TRIANGLES, geomHandler._polyIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
} else {
|
||||
pickingMask = material.pickingMask;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================
|
||||
//Strokes and linestrings rendering
|
||||
//=========================================
|
||||
f.bindOutputTexture(texture);
|
||||
|
||||
hLine.activate();
|
||||
sh = hLine._program;
|
||||
sha = sh.attributes;
|
||||
shu = sh.uniforms;
|
||||
|
||||
gl.uniform2fv(shu.viewport, [width, height]);
|
||||
|
||||
gl.uniform4fv(shu.extentParamsHigh, extentParamsHigh);
|
||||
gl.uniform4fv(shu.extentParamsLow, extentParamsLow);
|
||||
|
||||
//vertex
|
||||
var mb = geomHandler._lineVerticesHighBufferMerc;
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, mb);
|
||||
|
||||
gl.vertexAttribPointer(sha.prevHigh, mb.itemSize, gl.FLOAT, false, 8, 0);
|
||||
gl.vertexAttribPointer(sha.currentHigh, mb.itemSize, gl.FLOAT, false, 8, 32);
|
||||
gl.vertexAttribPointer(sha.nextHigh, mb.itemSize, gl.FLOAT, false, 8, 64);
|
||||
|
||||
mb = geomHandler._lineVerticesLowBufferMerc;
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, mb);
|
||||
|
||||
gl.vertexAttribPointer(sha.prevLow, mb.itemSize, gl.FLOAT, false, 8, 0);
|
||||
gl.vertexAttribPointer(sha.currentLow, mb.itemSize, gl.FLOAT, false, 8, 32);
|
||||
gl.vertexAttribPointer(sha.nextLow, mb.itemSize, gl.FLOAT, false, 8, 64);
|
||||
|
||||
//order
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._lineOrdersBuffer);
|
||||
gl.vertexAttribPointer(sha.order, geomHandler._lineOrdersBuffer.itemSize, gl.FLOAT, false, 4, 0);
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, geomHandler._lineIndexesBuffer);
|
||||
|
||||
//PASS - stroke
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._lineStrokesBuffer);
|
||||
gl.vertexAttribPointer(sha.thickness, geomHandler._lineStrokesBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._lineStrokeColorsBuffer);
|
||||
gl.vertexAttribPointer(sha.color, geomHandler._lineStrokeColorsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
//Antialias pass
|
||||
gl.uniform1f(shu.thicknessOutline, 2);
|
||||
gl.uniform1f(shu.alpha, 0.54);
|
||||
gl.drawElements(gl.TRIANGLE_STRIP, geomHandler._lineIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
//
|
||||
//Aliased pass
|
||||
gl.uniform1f(shu.thicknessOutline, 1);
|
||||
gl.uniform1f(shu.alpha, 1.0);
|
||||
gl.drawElements(gl.TRIANGLE_STRIP, geomHandler._lineIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
|
||||
//PASS - inside line
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._lineThicknessBuffer);
|
||||
gl.vertexAttribPointer(sha.thickness, geomHandler._lineThicknessBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._lineColorsBuffer);
|
||||
gl.vertexAttribPointer(sha.color, geomHandler._lineColorsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
//Antialias pass
|
||||
gl.uniform1f(shu.thicknessOutline, 2);
|
||||
gl.uniform1f(shu.alpha, 0.54);
|
||||
gl.drawElements(gl.TRIANGLE_STRIP, geomHandler._lineIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
//
|
||||
//Aliased pass
|
||||
gl.uniform1f(shu.thicknessOutline, 1);
|
||||
gl.uniform1f(shu.alpha, 1.0);
|
||||
gl.drawElements(gl.TRIANGLE_STRIP, geomHandler._lineIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
|
||||
if (material.layer._pickingEnabled && !material.pickingReady) {
|
||||
f.bindOutputTexture(pickingMask);
|
||||
gl.uniform1f(shu.thicknessOutline, 8);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, geomHandler._linePickingColorsBuffer);
|
||||
gl.vertexAttribPointer(sha.color, geomHandler._linePickingColorsBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
gl.drawElements(gl.TRIANGLE_STRIP, geomHandler._lineIndexesBuffer.numItems, gl.UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
material.applyTexture(texture, pickingMask);
|
||||
|
||||
} else {
|
||||
material.isLoading = false;
|
||||
}
|
||||
|
||||
deltaTime = window.performance.now() - startTime;
|
||||
// prevLayerId = material.layer._id;
|
||||
}
|
||||
|
||||
gl.disable(gl.BLEND);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.enable(gl.CULL_FACE);
|
||||
|
||||
f.deactivate();
|
||||
}
|
||||
};
|
||||
|
||||
add(material) {
|
||||
this._queue.push(material);
|
||||
};
|
||||
|
||||
remove(material) {
|
||||
//...
|
||||
};
|
||||
}
|
||||
|
||||
@ -20,319 +20,320 @@ import { ImageCanvas } from '../ImageCanvas.js';
|
||||
* @param {String} [options.depthComponent="DEPTH_COMPONENT16"] - Specifies depth buffer size.
|
||||
* @param {Boolean} [options.useDepth] - Using depth buffer during the rendering.
|
||||
*/
|
||||
const Framebuffer = function (handler, options = {}) {
|
||||
export class Framebuffer {
|
||||
|
||||
/**
|
||||
* WebGL handler.
|
||||
* @public
|
||||
* @type {og.webgl.Handler}
|
||||
*/
|
||||
this.handler = handler;
|
||||
constructor(handler, options = {}) {
|
||||
|
||||
/**
|
||||
* Framebuffer object.
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
this._fbo = null;
|
||||
/**
|
||||
* WebGL handler.
|
||||
* @public
|
||||
* @type {og.webgl.Handler}
|
||||
*/
|
||||
this.handler = handler;
|
||||
|
||||
this._isBare = options.isBare || false;
|
||||
/**
|
||||
* Framebuffer object.
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
this._fbo = null;
|
||||
|
||||
/**
|
||||
* Renderbuffer object.
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
this._depthRenderbuffer = null;
|
||||
this._isBare = options.isBare || false;
|
||||
|
||||
this._filter = options.filter || "NEAREST";
|
||||
/**
|
||||
* Renderbuffer object.
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
this._depthRenderbuffer = null;
|
||||
|
||||
this._internalFormatArr = options.internalFormat instanceof Array ? options.internalFormat : [options.internalFormat || "RGBA"];
|
||||
this._filter = options.filter || "NEAREST";
|
||||
|
||||
this._formatArr = options.format instanceof Array ? options.format : [options.format || "RGBA"];
|
||||
this._internalFormatArr = options.internalFormat instanceof Array ? options.internalFormat : [options.internalFormat || "RGBA"];
|
||||
|
||||
this._typeArr = options.type instanceof Array ? options.type : [options.type || "UNSIGNED_BYTE"];
|
||||
this._formatArr = options.format instanceof Array ? options.format : [options.format || "RGBA"];
|
||||
|
||||
this._attachmentArr = options.attachment instanceof Array ?
|
||||
options.attachment.map((a, i) => {
|
||||
let res = a.toUpperCase();
|
||||
if (res === "COLOR_ATTACHMENT") {
|
||||
return `${res}${i.toString()}`;
|
||||
}
|
||||
return res;
|
||||
}) : [options.attachment || "COLOR_ATTACHMENT0"];
|
||||
this._typeArr = options.type instanceof Array ? options.type : [options.type || "UNSIGNED_BYTE"];
|
||||
|
||||
/**
|
||||
* Framebuffer width.
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this._width = options.width || handler.canvas.width;
|
||||
this._attachmentArr = options.attachment instanceof Array ?
|
||||
options.attachment.map((a, i) => {
|
||||
let res = a.toUpperCase();
|
||||
if (res === "COLOR_ATTACHMENT") {
|
||||
return `${res}${i.toString()}`;
|
||||
}
|
||||
return res;
|
||||
}) : [options.attachment || "COLOR_ATTACHMENT0"];
|
||||
|
||||
/**
|
||||
* Framebuffer width.
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this._height = options.height || handler.canvas.height;
|
||||
/**
|
||||
* Framebuffer width.
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this._width = options.width || handler.canvas.width;
|
||||
|
||||
this._depthComponent = options.depthComponent != undefined ? options.depthComponent : "DEPTH_COMPONENT16";
|
||||
/**
|
||||
* Framebuffer width.
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this._height = options.height || handler.canvas.height;
|
||||
|
||||
this._useDepth = options.useDepth != undefined ? options.useDepth : true;
|
||||
this._depthComponent = options.depthComponent != undefined ? options.depthComponent : "DEPTH_COMPONENT16";
|
||||
|
||||
/**
|
||||
* Framebuffer activity.
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this._active = false;
|
||||
this._useDepth = options.useDepth != undefined ? options.useDepth : true;
|
||||
|
||||
this._size = options.size || 1;
|
||||
/**
|
||||
* Framebuffer activity.
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this._active = false;
|
||||
|
||||
/**
|
||||
* Framebuffer texture.
|
||||
* @public
|
||||
* @type {number}
|
||||
*/
|
||||
this.textures = options.textures || new Array(this._size);
|
||||
};
|
||||
this._size = options.size || 1;
|
||||
|
||||
Framebuffer.blit = function (sourceFramebuffer, destFramebuffer, glAttachment, glMask, glFilter) {
|
||||
/**
|
||||
* Framebuffer texture.
|
||||
* @public
|
||||
* @type {number}
|
||||
*/
|
||||
this.textures = options.textures || new Array(this._size);
|
||||
};
|
||||
|
||||
let gl = sourceFramebuffer.handler.gl;
|
||||
static blit(sourceFramebuffer, destFramebuffer, glAttachment, glMask, glFilter) {
|
||||
|
||||
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, sourceFramebuffer._fbo);
|
||||
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, framebuffer._fbo);
|
||||
gl.readBuffer(glAttachment);
|
||||
let gl = sourceFramebuffer.handler.gl;
|
||||
|
||||
gl.clearBufferfv(gl.COLOR, 0, [0.0, 0.0, 0.0, 1.0]);
|
||||
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, sourceFramebuffer._fbo);
|
||||
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, framebuffer._fbo);
|
||||
gl.readBuffer(glAttachment);
|
||||
|
||||
gl.blitFramebuffer(
|
||||
0, 0, sourceFramebuffer._width, sourceFramebuffer._height,
|
||||
0, 0, destFramebuffer._width, destFramebuffer._height,
|
||||
glMask, glFilter
|
||||
);
|
||||
gl.clearBufferfv(gl.COLOR, 0, [0.0, 0.0, 0.0, 1.0]);
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
|
||||
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
|
||||
};
|
||||
gl.blitFramebuffer(
|
||||
0, 0, sourceFramebuffer._width, sourceFramebuffer._height,
|
||||
0, 0, destFramebuffer._width, destFramebuffer._height,
|
||||
glMask, glFilter
|
||||
);
|
||||
|
||||
Framebuffer.prototype.destroy = function () {
|
||||
var gl = this.handler.gl;
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
|
||||
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
|
||||
};
|
||||
|
||||
for (var i = 0; i < this.textures.length; i++) {
|
||||
gl.deleteTexture(this.textures[i]);
|
||||
}
|
||||
this.textures = new Array(this._size);
|
||||
destroy() {
|
||||
var gl = this.handler.gl;
|
||||
|
||||
gl.deleteFramebuffer(this._fbo);
|
||||
gl.deleteRenderbuffer(this._depthRenderbuffer);
|
||||
|
||||
this._depthRenderbuffer = null;
|
||||
this._fbo = null;
|
||||
|
||||
this._active = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Framebuffer initialization.
|
||||
* @private
|
||||
*/
|
||||
Framebuffer.prototype.init = function () {
|
||||
var gl = this.handler.gl;
|
||||
|
||||
this._fbo = gl.createFramebuffer();
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbo);
|
||||
|
||||
if (!this._isBare) {
|
||||
let attachmentArr = [];
|
||||
for (var i = 0; i < this.textures.length; i++) {
|
||||
|
||||
let ti = this.textures[i] ||
|
||||
this.handler.createEmptyTexture2DExt(
|
||||
this._width,
|
||||
this._height,
|
||||
this._filter,
|
||||
this._internalFormatArr[i],
|
||||
this._formatArr[i],
|
||||
this._typeArr[i]
|
||||
);
|
||||
|
||||
let att_i = gl[this._attachmentArr[i]];
|
||||
|
||||
this.bindOutputTexture(ti, att_i);
|
||||
|
||||
this.textures[i] = ti;
|
||||
|
||||
if (this._attachmentArr[i] != "DEPTH_ATTACHMENT") {
|
||||
attachmentArr.push(att_i);
|
||||
}
|
||||
gl.deleteTexture(this.textures[i]);
|
||||
}
|
||||
gl.drawBuffers && gl.drawBuffers(attachmentArr);
|
||||
}
|
||||
this.textures = new Array(this._size);
|
||||
|
||||
if (this._useDepth) {
|
||||
this._depthRenderbuffer = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthRenderbuffer);
|
||||
gl.renderbufferStorage(gl.RENDERBUFFER, gl[this._depthComponent], this._width, this._height);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderbuffer);
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
||||
}
|
||||
gl.deleteFramebuffer(this._fbo);
|
||||
gl.deleteRenderbuffer(this._depthRenderbuffer);
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
this._depthRenderbuffer = null;
|
||||
this._fbo = null;
|
||||
|
||||
return this;
|
||||
};
|
||||
this._active = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Bind buffer texture.
|
||||
* @public
|
||||
* @param{Object} texture - Output texture.
|
||||
* @param {Number} [attachmentIndex=0] - color attachment index.
|
||||
*/
|
||||
Framebuffer.prototype.bindOutputTexture = function (texture, glAttachment) {
|
||||
var gl = this.handler.gl;
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, glAttachment || gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
};
|
||||
/**
|
||||
* Framebuffer initialization.
|
||||
* @private
|
||||
*/
|
||||
init() {
|
||||
var gl = this.handler.gl;
|
||||
|
||||
/**
|
||||
* Sets framebuffer viewport size.
|
||||
* @public
|
||||
* @param {number} width - Framebuffer width.
|
||||
* @param {number} height - Framebuffer height.
|
||||
*/
|
||||
Framebuffer.prototype.setSize = function (width, height, forceDestroy) {
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
this._fbo = gl.createFramebuffer();
|
||||
|
||||
if (this._active) {
|
||||
this.handler.gl.viewport(0, 0, this._width, this._height);
|
||||
}
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbo);
|
||||
|
||||
if (this._useDepth || forceDestroy) {
|
||||
this.destroy();
|
||||
this.init();
|
||||
}
|
||||
};
|
||||
if (!this._isBare) {
|
||||
let attachmentArr = [];
|
||||
for (var i = 0; i < this.textures.length; i++) {
|
||||
|
||||
/**
|
||||
* Returns framebuffer completed.
|
||||
* @public
|
||||
* @returns {boolean} -
|
||||
*/
|
||||
Framebuffer.prototype.isComplete = function () {
|
||||
var gl = this.handler.gl;
|
||||
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
let ti = this.textures[i] ||
|
||||
this.handler.createEmptyTexture2DExt(
|
||||
this._width,
|
||||
this._height,
|
||||
this._filter,
|
||||
this._internalFormatArr[i],
|
||||
this._formatArr[i],
|
||||
this._typeArr[i]
|
||||
);
|
||||
|
||||
/**
|
||||
* Gets pixel RBGA color from framebuffer by coordinates.
|
||||
* @public
|
||||
* @param {Uint8Array} res - Normalized x - coordinate.
|
||||
* @param {number} nx - Normalized x - coordinate.
|
||||
* @param {number} ny - Normalized y - coordinate.
|
||||
* @param {number} [w=1] - Normalized width.
|
||||
* @param {number} [h=1] - Normalized height.
|
||||
* @param {Number} [attachmentIndex=0] - color attachment index.
|
||||
*/
|
||||
Framebuffer.prototype.readPixels = function (res, nx, ny, index = 0, w = 1, h = 1) {
|
||||
var gl = this.handler.gl;
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbo);
|
||||
gl.readBuffer && gl.readBuffer(gl.COLOR_ATTACHMENT0 + index || 0);
|
||||
gl.readPixels(nx * this._width, ny * this._height, w, h, gl.RGBA, gl[this._typeArr[index]], res);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
};
|
||||
let att_i = gl[this._attachmentArr[i]];
|
||||
|
||||
/**
|
||||
* Reads all pixels(RGBA colors) from framebuffer.
|
||||
* @public
|
||||
* @param {Uint8Array} res - Result array.
|
||||
* @param {Number} [attachmentIndex=0] - color attachment index.
|
||||
*/
|
||||
Framebuffer.prototype.readAllPixels = function (res, attachmentIndex = 0) {
|
||||
var gl = this.handler.gl;
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbo);
|
||||
gl.readBuffer && gl.readBuffer(gl.COLOR_ATTACHMENT0 + attachmentIndex);
|
||||
gl.readPixels(0, 0, this._width, this._height, gl.RGBA, gl[this._typeArr[attachmentIndex]], res);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
};
|
||||
this.bindOutputTexture(ti, att_i);
|
||||
|
||||
/**
|
||||
* Activate framebuffer frame to draw.
|
||||
* @public
|
||||
* @returns {og.webgl.Framebuffer} Returns Current framebuffer.
|
||||
*/
|
||||
Framebuffer.prototype.activate = function () {
|
||||
var gl = this.handler.gl;
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbo);
|
||||
gl.viewport(0, 0, this._width, this._height);
|
||||
this._active = true;
|
||||
var c = this.handler.framebufferStack.current().data;
|
||||
c && (c._active = false);
|
||||
this.handler.framebufferStack.push(this);
|
||||
return this;
|
||||
};
|
||||
this.textures[i] = ti;
|
||||
|
||||
/**
|
||||
* Deactivate framebuffer frame.
|
||||
* @public
|
||||
*/
|
||||
Framebuffer.prototype.deactivate = function () {
|
||||
var h = this.handler,
|
||||
gl = h.gl;
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
this._active = false;
|
||||
if (this._attachmentArr[i] != "DEPTH_ATTACHMENT") {
|
||||
attachmentArr.push(att_i);
|
||||
}
|
||||
}
|
||||
gl.drawBuffers && gl.drawBuffers(attachmentArr);
|
||||
}
|
||||
|
||||
var f = this.handler.framebufferStack.popPrev();
|
||||
if (this._useDepth) {
|
||||
this._depthRenderbuffer = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthRenderbuffer);
|
||||
gl.renderbufferStorage(gl.RENDERBUFFER, gl[this._depthComponent], this._width, this._height);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderbuffer);
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
||||
}
|
||||
|
||||
if (f) {
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, f._fbo);
|
||||
gl.viewport(0, 0, f._width, f._height);
|
||||
} else {
|
||||
gl.viewport(0, 0, h.canvas.width, h.canvas.height);
|
||||
}
|
||||
};
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
|
||||
/**
|
||||
* Gets JavaScript image object that framebuffer has drawn.
|
||||
* @public
|
||||
* @returns {Object} -
|
||||
*/
|
||||
Framebuffer.prototype.getImage = function () {
|
||||
var data = new Uint8Array(4 * this._width * this._height);
|
||||
this.readAllPixels(data);
|
||||
var imageCanvas = new ImageCanvas(this._width, this._height);
|
||||
imageCanvas.setData(data);
|
||||
return imageCanvas.getImage();
|
||||
};
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Open dialog window with framebuffer image.
|
||||
* @public
|
||||
*/
|
||||
Framebuffer.prototype.openImage = function () {
|
||||
var img = this.getImage();
|
||||
var dataUrl = img.src;
|
||||
var windowContent = '<!DOCTYPE html>';
|
||||
windowContent += '<html>';
|
||||
windowContent += '<head><title>Print</title></head>';
|
||||
windowContent += '<body>';
|
||||
windowContent += '<img src="' + dataUrl + '">';
|
||||
windowContent += '</body>';
|
||||
windowContent += '</html>';
|
||||
var printWin = window.open('', '', 'width=' + img.width + 'px ,height=' + img.height + 'px');
|
||||
printWin.document.open();
|
||||
printWin.document.write(windowContent);
|
||||
printWin.document.close();
|
||||
printWin.focus();
|
||||
};
|
||||
/**
|
||||
* Bind buffer texture.
|
||||
* @public
|
||||
* @param{Object} texture - Output texture.
|
||||
* @param {Number} [attachmentIndex=0] - color attachment index.
|
||||
*/
|
||||
bindOutputTexture(texture, glAttachment) {
|
||||
var gl = this.handler.gl;
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, glAttachment || gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
};
|
||||
|
||||
export { Framebuffer };
|
||||
/**
|
||||
* Sets framebuffer viewport size.
|
||||
* @public
|
||||
* @param {number} width - Framebuffer width.
|
||||
* @param {number} height - Framebuffer height.
|
||||
*/
|
||||
setSize(width, height, forceDestroy) {
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
|
||||
if (this._active) {
|
||||
this.handler.gl.viewport(0, 0, this._width, this._height);
|
||||
}
|
||||
|
||||
if (this._useDepth || forceDestroy) {
|
||||
this.destroy();
|
||||
this.init();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns framebuffer completed.
|
||||
* @public
|
||||
* @returns {boolean} -
|
||||
*/
|
||||
isComplete() {
|
||||
var gl = this.handler.gl;
|
||||
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets pixel RBGA color from framebuffer by coordinates.
|
||||
* @public
|
||||
* @param {Uint8Array} res - Normalized x - coordinate.
|
||||
* @param {number} nx - Normalized x - coordinate.
|
||||
* @param {number} ny - Normalized y - coordinate.
|
||||
* @param {number} [w=1] - Normalized width.
|
||||
* @param {number} [h=1] - Normalized height.
|
||||
* @param {Number} [attachmentIndex=0] - color attachment index.
|
||||
*/
|
||||
readPixels(res, nx, ny, index = 0, w = 1, h = 1) {
|
||||
var gl = this.handler.gl;
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbo);
|
||||
gl.readBuffer && gl.readBuffer(gl.COLOR_ATTACHMENT0 + index || 0);
|
||||
gl.readPixels(nx * this._width, ny * this._height, w, h, gl.RGBA, gl[this._typeArr[index]], res);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reads all pixels(RGBA colors) from framebuffer.
|
||||
* @public
|
||||
* @param {Uint8Array} res - Result array.
|
||||
* @param {Number} [attachmentIndex=0] - color attachment index.
|
||||
*/
|
||||
readAllPixels(res, attachmentIndex = 0) {
|
||||
var gl = this.handler.gl;
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbo);
|
||||
gl.readBuffer && gl.readBuffer(gl.COLOR_ATTACHMENT0 + attachmentIndex);
|
||||
gl.readPixels(0, 0, this._width, this._height, gl.RGBA, gl[this._typeArr[attachmentIndex]], res);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
};
|
||||
|
||||
/**
|
||||
* Activate framebuffer frame to draw.
|
||||
* @public
|
||||
* @returns {og.webgl.Framebuffer} Returns Current framebuffer.
|
||||
*/
|
||||
activate() {
|
||||
var gl = this.handler.gl;
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbo);
|
||||
gl.viewport(0, 0, this._width, this._height);
|
||||
this._active = true;
|
||||
var c = this.handler.framebufferStack.current().data;
|
||||
c && (c._active = false);
|
||||
this.handler.framebufferStack.push(this);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Deactivate framebuffer frame.
|
||||
* @public
|
||||
*/
|
||||
deactivate() {
|
||||
var h = this.handler,
|
||||
gl = h.gl;
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
this._active = false;
|
||||
|
||||
var f = this.handler.framebufferStack.popPrev();
|
||||
|
||||
if (f) {
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, f._fbo);
|
||||
gl.viewport(0, 0, f._width, f._height);
|
||||
} else {
|
||||
gl.viewport(0, 0, h.canvas.width, h.canvas.height);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets JavaScript image object that framebuffer has drawn.
|
||||
* @public
|
||||
* @returns {Object} -
|
||||
*/
|
||||
getImage() {
|
||||
var data = new Uint8Array(4 * this._width * this._height);
|
||||
this.readAllPixels(data);
|
||||
var imageCanvas = new ImageCanvas(this._width, this._height);
|
||||
imageCanvas.setData(data);
|
||||
return imageCanvas.getImage();
|
||||
};
|
||||
|
||||
/**
|
||||
* Open dialog window with framebuffer image.
|
||||
* @public
|
||||
*/
|
||||
openImage() {
|
||||
var img = this.getImage();
|
||||
var dataUrl = img.src;
|
||||
var windowContent = '<!DOCTYPE html>';
|
||||
windowContent += '<html>';
|
||||
windowContent += '<head><title>Print</title></head>';
|
||||
windowContent += '<body>';
|
||||
windowContent += '<img src="' + dataUrl + '">';
|
||||
windowContent += '</body>';
|
||||
windowContent += '</html>';
|
||||
var printWin = window.open('', '', 'width=' + img.width + 'px ,height=' + img.height + 'px');
|
||||
printWin.document.open();
|
||||
printWin.document.write(windowContent);
|
||||
printWin.document.close();
|
||||
printWin.focus();
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -15,217 +15,218 @@
|
||||
* @param {String} [options.depthComponent="DEPTH_COMPONENT16"] - Specifies depth buffer size.
|
||||
* @param {Boolean} [options.useDepth] - Using depth buffer during the rendering.
|
||||
*/
|
||||
const Multisample = function (handler, options) {
|
||||
export class Multisample {
|
||||
|
||||
options = options || {};
|
||||
constructor(handler, options) {
|
||||
|
||||
options = options || {};
|
||||
|
||||
/**
|
||||
* WebGL handler.
|
||||
* @public
|
||||
* @type {og.webgl.Handler}
|
||||
*/
|
||||
this.handler = handler;
|
||||
|
||||
this._internalFormat = options.internalFormat ? options.internalFormat.toUpperCase() : "RGBA8";
|
||||
|
||||
/**
|
||||
* Framebuffer object.
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
this._fbo = null;
|
||||
|
||||
/**
|
||||
* Renderbuffer object.
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
this._depthRenderbuffer = null;
|
||||
|
||||
/**
|
||||
* Framebuffer width.
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this._width = options.width || handler.canvas.width;
|
||||
|
||||
/**
|
||||
* Framebuffer width.
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this._height = options.height || handler.canvas.height;
|
||||
|
||||
this._msaa = options.msaa != undefined ? options.msaa : 4;
|
||||
|
||||
this._useDepth = options.useDepth != undefined ? options.useDepth : true;
|
||||
|
||||
this._depthComponent = options.depthComponent != undefined ? options.depthComponent : "DEPTH_COMPONENT16";
|
||||
|
||||
/**
|
||||
* Framebuffer activity.
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this._active = false;
|
||||
|
||||
this._size = options.size || 1;
|
||||
|
||||
this._filter = options.filter || "NEAREST";
|
||||
|
||||
this._glFilter = null;
|
||||
|
||||
this.renderbuffers = new Array(this._size);
|
||||
};
|
||||
|
||||
destroy() {
|
||||
var gl = this.handler.gl;
|
||||
|
||||
for (var i = 0; i < this.renderbuffers.length; i++) {
|
||||
gl.deleteRenderbuffer(this.renderbuffers[i]);
|
||||
}
|
||||
this.renderbuffers = new Array(this._size);
|
||||
|
||||
gl.deleteFramebuffer(this._fbo);
|
||||
gl.deleteRenderbuffer(this._depthRenderbuffer);
|
||||
|
||||
this._depthRenderbuffer = null;
|
||||
this._fbo = null;
|
||||
|
||||
this._active = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* WebGL handler.
|
||||
* Framebuffer initialization.
|
||||
* @private
|
||||
*/
|
||||
init() {
|
||||
|
||||
var gl = this.handler.gl;
|
||||
|
||||
this._glFilter = gl[this._filter];
|
||||
|
||||
this._fbo = gl.createFramebuffer();
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbo);
|
||||
|
||||
let colorAttachments = [];
|
||||
for (var i = 0; i < this.renderbuffers.length; i++) {
|
||||
let rb = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
|
||||
gl.renderbufferStorageMultisample(gl.RENDERBUFFER, this._msaa, gl[this._internalFormat], this._width, this._height);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.RENDERBUFFER, rb);
|
||||
colorAttachments.push(gl.COLOR_ATTACHMENT0 + i);
|
||||
this.renderbuffers[i] = rb;
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
||||
}
|
||||
gl.drawBuffers(colorAttachments);
|
||||
|
||||
if (this._useDepth) {
|
||||
this._depthRenderbuffer = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthRenderbuffer);
|
||||
gl.renderbufferStorageMultisample(gl.RENDERBUFFER, this._msaa, gl[this._depthComponent], this._width, this._height);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderbuffer);
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
||||
}
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
blitTo(framebuffer, attachmentIndex = 0) {
|
||||
|
||||
let gl = this.handler.gl;
|
||||
|
||||
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, this._fbo);
|
||||
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, framebuffer._fbo);
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT0 + attachmentIndex);
|
||||
|
||||
gl.clearBufferfv(gl.COLOR, 0, [0.0, 0.0, 0.0, 1.0]);
|
||||
|
||||
gl.blitFramebuffer(
|
||||
0, 0, this._width, this._height,
|
||||
0, 0, framebuffer._width, framebuffer._height,
|
||||
gl.COLOR_BUFFER_BIT, this._glFilter
|
||||
);
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
|
||||
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets framebuffer viewport size.
|
||||
* @public
|
||||
* @type {og.webgl.Handler}
|
||||
* @param {number} width - Framebuffer width.
|
||||
* @param {number} height - Framebuffer height.
|
||||
*/
|
||||
this.handler = handler;
|
||||
setSize(width, height, forceDestroy) {
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
|
||||
this._internalFormat = options.internalFormat ? options.internalFormat.toUpperCase() : "RGBA8";
|
||||
if (this._active) {
|
||||
this.handler.gl.viewport(0, 0, this._width, this._height);
|
||||
}
|
||||
|
||||
if (this._useDepth || forceDestroy) {
|
||||
this.destroy();
|
||||
this.init();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Framebuffer object.
|
||||
* @private
|
||||
* @type {Object}
|
||||
* Returns framebuffer completed.
|
||||
* @public
|
||||
* @returns {boolean} -
|
||||
*/
|
||||
this._fbo = null;
|
||||
isComplete() {
|
||||
var gl = this.handler.gl;
|
||||
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Renderbuffer object.
|
||||
* @private
|
||||
* @type {Object}
|
||||
* Activate framebuffer frame to draw.
|
||||
* @public
|
||||
* @returns {og.webgl.Framebuffer} Returns Current framebuffer.
|
||||
*/
|
||||
this._depthRenderbuffer = null;
|
||||
activate() {
|
||||
var gl = this.handler.gl;
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbo);
|
||||
gl.viewport(0, 0, this._width, this._height);
|
||||
this._active = true;
|
||||
var c = this.handler.framebufferStack.current().data;
|
||||
c && (c._active = false);
|
||||
this.handler.framebufferStack.push(this);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Framebuffer width.
|
||||
* @private
|
||||
* @type {number}
|
||||
* Deactivate framebuffer frame.
|
||||
* @public
|
||||
*/
|
||||
this._width = options.width || handler.canvas.width;
|
||||
deactivate() {
|
||||
var h = this.handler,
|
||||
gl = h.gl;
|
||||
|
||||
/**
|
||||
* Framebuffer width.
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this._height = options.height || handler.canvas.height;
|
||||
//Q: check for this._useDepth ?
|
||||
|
||||
this._msaa = options.msaa != undefined ? options.msaa : 4;
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
this._active = false;
|
||||
|
||||
this._useDepth = options.useDepth != undefined ? options.useDepth : true;
|
||||
var f = this.handler.framebufferStack.popPrev();
|
||||
|
||||
this._depthComponent = options.depthComponent != undefined ? options.depthComponent : "DEPTH_COMPONENT16";
|
||||
|
||||
/**
|
||||
* Framebuffer activity.
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this._active = false;
|
||||
|
||||
this._size = options.size || 1;
|
||||
|
||||
this._filter = options.filter || "NEAREST";
|
||||
|
||||
this._glFilter = null;
|
||||
|
||||
this.renderbuffers = new Array(this._size);
|
||||
};
|
||||
|
||||
Multisample.prototype.destroy = function () {
|
||||
var gl = this.handler.gl;
|
||||
|
||||
for (var i = 0; i < this.renderbuffers.length; i++) {
|
||||
gl.deleteRenderbuffer(this.renderbuffers[i]);
|
||||
}
|
||||
this.renderbuffers = new Array(this._size);
|
||||
|
||||
gl.deleteFramebuffer(this._fbo);
|
||||
gl.deleteRenderbuffer(this._depthRenderbuffer);
|
||||
|
||||
this._depthRenderbuffer = null;
|
||||
this._fbo = null;
|
||||
|
||||
this._active = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Framebuffer initialization.
|
||||
* @private
|
||||
*/
|
||||
Multisample.prototype.init = function () {
|
||||
|
||||
var gl = this.handler.gl;
|
||||
|
||||
this._glFilter = gl[this._filter];
|
||||
|
||||
this._fbo = gl.createFramebuffer();
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbo);
|
||||
|
||||
let colorAttachments = [];
|
||||
for (var i = 0; i < this.renderbuffers.length; i++) {
|
||||
let rb = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
|
||||
gl.renderbufferStorageMultisample(gl.RENDERBUFFER, this._msaa, gl[this._internalFormat], this._width, this._height);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.RENDERBUFFER, rb);
|
||||
colorAttachments.push(gl.COLOR_ATTACHMENT0 + i);
|
||||
this.renderbuffers[i] = rb;
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
||||
}
|
||||
gl.drawBuffers(colorAttachments);
|
||||
|
||||
if (this._useDepth) {
|
||||
this._depthRenderbuffer = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthRenderbuffer);
|
||||
gl.renderbufferStorageMultisample(gl.RENDERBUFFER, this._msaa, gl[this._depthComponent], this._width, this._height);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderbuffer);
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
||||
}
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Multisample.prototype.blitTo = function (framebuffer, attachmentIndex = 0) {
|
||||
|
||||
let gl = this.handler.gl;
|
||||
|
||||
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, this._fbo);
|
||||
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, framebuffer._fbo);
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT0 + attachmentIndex);
|
||||
|
||||
gl.clearBufferfv(gl.COLOR, 0, [0.0, 0.0, 0.0, 1.0]);
|
||||
|
||||
gl.blitFramebuffer(
|
||||
0, 0, this._width, this._height,
|
||||
0, 0, framebuffer._width, framebuffer._height,
|
||||
gl.COLOR_BUFFER_BIT, this._glFilter
|
||||
);
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
|
||||
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets framebuffer viewport size.
|
||||
* @public
|
||||
* @param {number} width - Framebuffer width.
|
||||
* @param {number} height - Framebuffer height.
|
||||
*/
|
||||
Multisample.prototype.setSize = function (width, height, forceDestroy) {
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
|
||||
if (this._active) {
|
||||
this.handler.gl.viewport(0, 0, this._width, this._height);
|
||||
}
|
||||
|
||||
if (this._useDepth || forceDestroy) {
|
||||
this.destroy();
|
||||
this.init();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns framebuffer completed.
|
||||
* @public
|
||||
* @returns {boolean} -
|
||||
*/
|
||||
Multisample.prototype.isComplete = function () {
|
||||
var gl = this.handler.gl;
|
||||
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Activate framebuffer frame to draw.
|
||||
* @public
|
||||
* @returns {og.webgl.Framebuffer} Returns Current framebuffer.
|
||||
*/
|
||||
Multisample.prototype.activate = function () {
|
||||
var gl = this.handler.gl;
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbo);
|
||||
gl.viewport(0, 0, this._width, this._height);
|
||||
this._active = true;
|
||||
var c = this.handler.framebufferStack.current().data;
|
||||
c && (c._active = false);
|
||||
this.handler.framebufferStack.push(this);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Deactivate framebuffer frame.
|
||||
* @public
|
||||
*/
|
||||
Multisample.prototype.deactivate = function () {
|
||||
var h = this.handler,
|
||||
gl = h.gl;
|
||||
|
||||
//Q: check for this._useDepth ?
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
this._active = false;
|
||||
|
||||
var f = this.handler.framebufferStack.popPrev();
|
||||
|
||||
if (f) {
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, f._fbo);
|
||||
gl.viewport(0, 0, f._width, f._height);
|
||||
} else {
|
||||
gl.viewport(0, 0, h.canvas.width, h.canvas.height);
|
||||
}
|
||||
};
|
||||
|
||||
export { Multisample };
|
||||
if (f) {
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, f._fbo);
|
||||
gl.viewport(0, 0, f._width, f._height);
|
||||
} else {
|
||||
gl.viewport(0, 0, h.canvas.width, h.canvas.height);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -8,131 +8,132 @@
|
||||
* @param {og.webgl.Handler} handler - Handler.
|
||||
* @param {og.webgl.Program} program - Shader program.
|
||||
*/
|
||||
const ProgramController = function (handler, program) {
|
||||
export class ProgramController {
|
||||
|
||||
constructor(handler, program) {
|
||||
|
||||
/**
|
||||
* Shader program.
|
||||
* @private
|
||||
* @type {og.webgl.Program}
|
||||
*/
|
||||
this._program = program;
|
||||
|
||||
/**
|
||||
* Handler.
|
||||
* @private
|
||||
* @type {og.webgl.Handler}
|
||||
*/
|
||||
this._handler = handler;
|
||||
|
||||
/**
|
||||
* Program current frame activation flag.
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this._activated = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Shader program.
|
||||
* @private
|
||||
* @type {og.webgl.Program}
|
||||
* Lazy create program call.
|
||||
* @public
|
||||
*/
|
||||
this._program = program;
|
||||
initialize() {
|
||||
this._program.createProgram(this._handler.gl);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handler.
|
||||
* @private
|
||||
* @type {og.webgl.Handler}
|
||||
* Returns controller's shader program.
|
||||
* @public
|
||||
* @return {og.webgl.Program} -
|
||||
*/
|
||||
this._handler = handler;
|
||||
getProgram() {
|
||||
return this._program;
|
||||
};
|
||||
|
||||
/**
|
||||
* Program current frame activation flag.
|
||||
* @private
|
||||
* @type {boolean}
|
||||
* Activates current shader program.
|
||||
* @public
|
||||
* @returns {ProgramController} -
|
||||
*/
|
||||
this._activated = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Lazy create program call.
|
||||
* @public
|
||||
*/
|
||||
ProgramController.prototype.initialize = function () {
|
||||
this._program.createProgram(this._handler.gl);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns controller's shader program.
|
||||
* @public
|
||||
* @return {og.webgl.Program} -
|
||||
*/
|
||||
ProgramController.prototype.getProgram = function () {
|
||||
return this._program;
|
||||
};
|
||||
|
||||
/**
|
||||
* Activates current shader program.
|
||||
* @public
|
||||
* @returns {ProgramController} -
|
||||
*/
|
||||
ProgramController.prototype.activate = function () {
|
||||
if (!this._activated) {
|
||||
this._handler.activeProgram.deactivate();
|
||||
this._handler.activeProgram = this;
|
||||
var p = this._program;
|
||||
this._activated = true;
|
||||
p.enableAttribArrays();
|
||||
p.use();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove program from handler
|
||||
* @public
|
||||
*/
|
||||
ProgramController.prototype.remove = function () {
|
||||
var p = this._handler.programs;
|
||||
if (p[this._program.name]) {
|
||||
if (this._activated) {
|
||||
this.deactivate();
|
||||
activate() {
|
||||
if (!this._activated) {
|
||||
this._handler.activeProgram.deactivate();
|
||||
this._handler.activeProgram = this;
|
||||
var p = this._program;
|
||||
this._activated = true;
|
||||
p.enableAttribArrays();
|
||||
p.use();
|
||||
}
|
||||
this._program.delete();
|
||||
p[this._program.name] = null;
|
||||
delete p[this._program.name];
|
||||
}
|
||||
};
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Deactivate shader program. This is not necessary while activae function used.
|
||||
* @public
|
||||
*/
|
||||
ProgramController.prototype.deactivate = function () {
|
||||
this._program.disableAttribArrays();
|
||||
this._activated = false;
|
||||
};
|
||||
/**
|
||||
* Remove program from handler
|
||||
* @public
|
||||
*/
|
||||
remove() {
|
||||
var p = this._handler.programs;
|
||||
if (p[this._program.name]) {
|
||||
if (this._activated) {
|
||||
this.deactivate();
|
||||
}
|
||||
this._program.delete();
|
||||
p[this._program.name] = null;
|
||||
delete p[this._program.name];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns program activity.
|
||||
* @public
|
||||
* @return {boolean} -
|
||||
*/
|
||||
ProgramController.prototype.isActive = function () {
|
||||
return this._activated;
|
||||
};
|
||||
/**
|
||||
* Deactivate shader program. This is not necessary while activae function used.
|
||||
* @public
|
||||
*/
|
||||
deactivate() {
|
||||
this._program.disableAttribArrays();
|
||||
this._activated = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets program uniforms and attributes values and return controller instance.
|
||||
* @public
|
||||
* @param {Object} params - Object with variable name and value like { value: 12, someArray:[1,2,3], uSampler: texture,... }
|
||||
* @return {og.webgl.ProgramController} -
|
||||
*/
|
||||
ProgramController.prototype.set = function (params) {
|
||||
this.activate();
|
||||
this._program.set(params);
|
||||
return this;
|
||||
};
|
||||
/**
|
||||
* Returns program activity.
|
||||
* @public
|
||||
* @return {boolean} -
|
||||
*/
|
||||
isActive() {
|
||||
return this._activated;
|
||||
};
|
||||
|
||||
/**
|
||||
* Draw index buffer with this program.
|
||||
* @public
|
||||
* @param {number} mode - Gl draw mode
|
||||
* @param {WEBGLBuffer} buffer - Buffer to draw.
|
||||
* @return {og.webgl.ProgramController} Returns current shader controller instance.
|
||||
*/
|
||||
ProgramController.prototype.drawIndexBuffer = function (mode, buffer) {
|
||||
this._program.drawIndexBuffer(mode, buffer);
|
||||
return this;
|
||||
};
|
||||
/**
|
||||
* Sets program uniforms and attributes values and return controller instance.
|
||||
* @public
|
||||
* @param {Object} params - Object with variable name and value like { value: 12, someArray:[1,2,3], uSampler: texture,... }
|
||||
* @return {og.webgl.ProgramController} -
|
||||
*/
|
||||
set(params) {
|
||||
this.activate();
|
||||
this._program.set(params);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls Gl drawArray function.
|
||||
* @param {number} mode - Gl draw mode.
|
||||
* @param {number} numItems - draw items count.
|
||||
* @return {og.webgl.ProgramController} Returns current shader controller instance.
|
||||
*/
|
||||
ProgramController.prototype.drawArrays = function (mode, numItems) {
|
||||
this._program.drawArrays(mode, numItems);
|
||||
return this;
|
||||
};
|
||||
/**
|
||||
* Draw index buffer with this program.
|
||||
* @public
|
||||
* @param {number} mode - Gl draw mode
|
||||
* @param {WEBGLBuffer} buffer - Buffer to draw.
|
||||
* @return {og.webgl.ProgramController} Returns current shader controller instance.
|
||||
*/
|
||||
drawIndexBuffer(mode, buffer) {
|
||||
this._program.drawIndexBuffer(mode, buffer);
|
||||
return this;
|
||||
};
|
||||
|
||||
export { ProgramController };
|
||||
/**
|
||||
* Calls Gl drawArray function.
|
||||
* @param {number} mode - Gl draw mode.
|
||||
* @param {number} numItems - draw items count.
|
||||
* @return {og.webgl.ProgramController} Returns current shader controller instance.
|
||||
*/
|
||||
drawArrays(mode, numItems) {
|
||||
this._program.drawArrays(mode, numItems);
|
||||
return this;
|
||||
};
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user