Merge pull request #379 from tbo47/refactor-es6-class

refactor to use es6 classes
This commit is contained in:
Michael Gevlich 2021-09-28 16:45:36 +03:00 committed by GitHub
commit 94db508392
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 3934 additions and 3915 deletions

View File

@ -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 };

File diff suppressed because it is too large Load Diff

View File

@ -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 };

View File

@ -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 };

View File

@ -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();

View File

@ -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 };
}

View File

@ -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 = [];
};
}

View File

@ -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);
};
}

View File

@ -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) {
//...
};
}

View File

@ -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

View File

@ -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);
}
};
}

View File

@ -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;
};
}