sigma
Version:
A JavaScript library dedicated to graph drawing.
186 lines (185 loc) • 8.73 kB
JavaScript
;
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Sigma.js WebGL Renderer Edge Program
* =====================================
*
* Program rendering edges as thick lines using four points translated
* orthogonally from the source & target's centers by half thickness.
*
* Rendering two triangles by using only four points is made possible through
* the use of indices.
*
* This method should be faster than the 6 points / 2 triangles approach and
* should handle thickness better than with gl.LINES.
*
* This version of the shader balances geometry computation evenly between
* the CPU & GPU (normals are computed on the CPU side).
* @module
*/
var utils_1 = require("../../../utils");
var edge_vert_glsl_1 = __importDefault(require("../shaders/edge.vert.glsl.js"));
var edge_frag_glsl_1 = __importDefault(require("../shaders/edge.frag.glsl.js"));
var edge_1 = require("./common/edge");
var POINTS = 4, ATTRIBUTES = 6, STRIDE = POINTS * ATTRIBUTES;
var EdgeProgram = /** @class */ (function (_super) {
__extends(EdgeProgram, _super);
function EdgeProgram(gl) {
var _this = _super.call(this, gl, edge_vert_glsl_1.default, edge_frag_glsl_1.default, POINTS, ATTRIBUTES) || this;
// Initializing indices buffer
var indicesBuffer = gl.createBuffer();
if (indicesBuffer === null)
throw new Error("EdgeProgram: error while getting resolutionLocation");
_this.indicesBuffer = indicesBuffer;
// Locations
_this.positionLocation = gl.getAttribLocation(_this.program, "a_position");
_this.colorLocation = gl.getAttribLocation(_this.program, "a_color");
_this.normalLocation = gl.getAttribLocation(_this.program, "a_normal");
_this.thicknessLocation = gl.getAttribLocation(_this.program, "a_thickness");
// Uniform locations
var scaleLocation = gl.getUniformLocation(_this.program, "u_scale");
if (scaleLocation === null)
throw new Error("EdgeProgram: error while getting scaleLocation");
_this.scaleLocation = scaleLocation;
var matrixLocation = gl.getUniformLocation(_this.program, "u_matrix");
if (matrixLocation === null)
throw new Error("EdgeProgram: error while getting matrixLocation");
_this.matrixLocation = matrixLocation;
var cameraRatioLocation = gl.getUniformLocation(_this.program, "u_cameraRatio");
if (cameraRatioLocation === null)
throw new Error("EdgeProgram: error while getting cameraRatioLocation");
_this.cameraRatioLocation = cameraRatioLocation;
var viewportRatioLocation = gl.getUniformLocation(_this.program, "u_viewportRatio");
if (viewportRatioLocation === null)
throw new Error("EdgeProgram: error while getting viewportRatioLocation");
_this.viewportRatioLocation = viewportRatioLocation;
var thicknessRatioLocation = gl.getUniformLocation(_this.program, "u_thicknessRatio");
if (thicknessRatioLocation === null)
throw new Error("EdgeProgram: error while getting thicknessRatioLocation");
_this.thicknessRatioLocation = thicknessRatioLocation;
// Enabling the OES_element_index_uint extension
// NOTE: on older GPUs, this means that really large graphs won't
// have all their edges rendered. But it seems that the
// `OES_element_index_uint` is quite everywhere so we'll handle
// the potential issue if it really arises.
// NOTE: when using webgl2, the extension is enabled by default
_this.canUse32BitsIndices = utils_1.canUse32BitsIndices(gl);
_this.IndicesArray = _this.canUse32BitsIndices ? Uint32Array : Uint16Array;
_this.indicesArray = new _this.IndicesArray();
_this.indicesType = _this.canUse32BitsIndices ? gl.UNSIGNED_INT : gl.UNSIGNED_SHORT;
_this.bind();
return _this;
}
EdgeProgram.prototype.bind = function () {
var gl = this.gl;
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
// Bindings
gl.enableVertexAttribArray(this.positionLocation);
gl.enableVertexAttribArray(this.normalLocation);
gl.enableVertexAttribArray(this.thicknessLocation);
gl.enableVertexAttribArray(this.colorLocation);
gl.vertexAttribPointer(this.positionLocation, 2, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(this.normalLocation, 2, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(this.thicknessLocation, 1, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 16);
gl.vertexAttribPointer(this.colorLocation, 4, gl.UNSIGNED_BYTE, true, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 20);
};
EdgeProgram.prototype.computeIndices = function () {
var l = this.array.length / ATTRIBUTES;
var size = l + l / 2;
var indices = new this.IndicesArray(size);
for (var i = 0, c = 0; i < l; i += 4) {
indices[c++] = i;
indices[c++] = i + 1;
indices[c++] = i + 2;
indices[c++] = i + 2;
indices[c++] = i + 1;
indices[c++] = i + 3;
}
this.indicesArray = indices;
};
EdgeProgram.prototype.bufferData = function () {
_super.prototype.bufferData.call(this);
// Indices data
var gl = this.gl;
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indicesArray, gl.STATIC_DRAW);
};
EdgeProgram.prototype.process = function (sourceData, targetData, data, hidden, offset) {
if (hidden) {
for (var i_1 = offset * STRIDE, l = i_1 + STRIDE; i_1 < l; i_1++)
this.array[i_1] = 0;
return;
}
var thickness = data.size || 1, x1 = sourceData.x, y1 = sourceData.y, x2 = targetData.x, y2 = targetData.y, color = utils_1.floatColor(data.color);
// Computing normals
var dx = x2 - x1, dy = y2 - y1;
var len = dx * dx + dy * dy, n1 = 0, n2 = 0;
if (len) {
len = 1 / Math.sqrt(len);
n1 = -dy * len;
n2 = dx * len;
}
var i = POINTS * ATTRIBUTES * offset;
var array = this.array;
// First point
array[i++] = x1;
array[i++] = y1;
array[i++] = n1;
array[i++] = n2;
array[i++] = thickness;
array[i++] = color;
// First point flipped
array[i++] = x1;
array[i++] = y1;
array[i++] = -n1;
array[i++] = -n2;
array[i++] = thickness;
array[i++] = color;
// Second point
array[i++] = x2;
array[i++] = y2;
array[i++] = n1;
array[i++] = n2;
array[i++] = thickness;
array[i++] = color;
// Second point flipped
array[i++] = x2;
array[i++] = y2;
array[i++] = -n1;
array[i++] = -n2;
array[i++] = thickness;
array[i] = color;
};
EdgeProgram.prototype.render = function (params) {
var gl = this.gl;
var program = this.program;
gl.useProgram(program);
// Binding uniforms
gl.uniform1f(this.scaleLocation, params.scalingRatio);
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix);
gl.uniform1f(this.cameraRatioLocation, params.ratio);
gl.uniform1f(this.viewportRatioLocation, 1 / Math.min(params.width, params.height));
gl.uniform1f(this.thicknessRatioLocation, 1 / Math.pow(params.ratio, params.edgesPowRatio));
// Drawing:
gl.drawElements(gl.TRIANGLES, this.indicesArray.length, this.indicesType, 0);
};
return EdgeProgram;
}(edge_1.AbstractEdgeProgram));
exports.default = EdgeProgram;