Commit b0d101e1 authored by Alexandre Delanoë's avatar Alexandre Delanoë

Merge remote-tracking branch 'origin/705-dev-upgrade-sigma-js' into dev

parents c782ea3f d8f1ac3a
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
"debouncing": "^22.7.25", "debouncing": "^22.7.25",
"echarts": "~5.1.2", "echarts": "~5.1.2",
"echarts-for-react": "~3.0.1", "echarts-for-react": "~3.0.1",
"graphology": "~0.25.1", "graphology": "~0.25.4",
"graphology-communities-louvain": "~2.0.1", "graphology-communities-louvain": "~2.0.1",
"graphology-layout-forceatlas2": "~0.9.2", "graphology-layout-forceatlas2": "~0.9.2",
"graphology-layout-noverlap": "~0.4.2", "graphology-layout-noverlap": "~0.4.2",
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
"react-dom": "~18.2.0", "react-dom": "~18.2.0",
"react-tooltip": "~4.2.8", "react-tooltip": "~4.2.8",
"secp256k1": "~4.0.2", "secp256k1": "~4.0.2",
"sigma": "~2.4.0", "sigma": "~3.0.0",
"twgl.js": "~5.0.4", "twgl.js": "~5.0.4",
"use-debounce": "^10.0.0", "use-debounce": "^10.0.0",
"uuid": "8.3.2" "uuid": "8.3.2"
...@@ -3992,10 +3992,6 @@ ...@@ -3992,10 +3992,6 @@
"license": "MIT", "license": "MIT",
"optional": true "optional": true
}, },
"node_modules/@yomguithereal/helpers": {
"version": "1.1.1",
"license": "MIT"
},
"node_modules/@zeit/schemas": { "node_modules/@zeit/schemas": {
"version": "2.36.0", "version": "2.36.0",
"resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.36.0.tgz", "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.36.0.tgz",
...@@ -12006,12 +12002,12 @@ ...@@ -12006,12 +12002,12 @@
} }
}, },
"node_modules/sigma": { "node_modules/sigma": {
"version": "2.4.0", "version": "3.0.0",
"license": "MIT", "resolved": "https://registry.npmjs.org/sigma/-/sigma-3.0.0.tgz",
"integrity": "sha512-O3w+sfyarnurPuxcBtkQ6wp5E9d0OctwMiXhQ8YUCiUX5G8Yz5XM6Vo6lsAGtMm/XvQR77+0JOzAIEeo4LpdjA==",
"dependencies": { "dependencies": {
"@yomguithereal/helpers": "^1.1.1",
"events": "^3.3.0", "events": "^3.3.0",
"graphology-utils": "^2.5.0" "graphology-utils": "^2.5.2"
} }
}, },
"node_modules/signal-exit": { "node_modules/signal-exit": {
......
(builtins.getFlake ("git+file://" + toString ./.)).devShells.${builtins.currentSystem}.default
\ No newline at end of file
...@@ -242,7 +242,7 @@ drawGraphCpt = here.component "drawGraph" cpt ...@@ -242,7 +242,7 @@ drawGraphCpt = here.component "drawGraph" cpt
-- When we change state, we make it empty though. -- When we change state, we make it empty though.
--pure $ RH.div { ref: elRef, style: {height: "95%"} } [] --pure $ RH.div { ref: elRef, style: {height: "95%"} } []
-- based on https://github.com/jacomyal/sigma.js/blob/v2.4.0/src/settings.ts -- based on https://github.com/jacomyal/sigma.js/blob/v3.0.0/src/settings.ts
-- TODO: check some of the types -- TODO: check some of the types
type SigmaSettings = type SigmaSettings =
( -- Performance ( -- Performance
...@@ -250,9 +250,7 @@ type SigmaSettings = ...@@ -250,9 +250,7 @@ type SigmaSettings =
--, hideLablesOnMove :: Boolean --, hideLablesOnMove :: Boolean
renderLabels :: Boolean renderLabels :: Boolean
--, renderEdgeLabels :: Boolean --, renderEdgeLabels :: Boolean
--, enableEdgeClickEvents :: Boolean , enableEdgeEvents :: Boolean
--, enableEdgeWheelEvents :: Boolean
, enableEdgeHoverEvents :: Boolean
-- Component rendering -- Component rendering
, defaultNodeColor :: String , defaultNodeColor :: String
--, defaultNodeType :: String --, defaultNodeType :: String
...@@ -279,9 +277,9 @@ type SigmaSettings = ...@@ -279,9 +277,9 @@ type SigmaSettings =
--, minCameraRatio :: Number --, minCameraRatio :: Number
--, maxCameraRatio :: Number --, maxCameraRatio :: Number
-- Renderers -- Renderers
--, labelRenderer :: DrawLabel --, defaultDrawNodeLabel :: DrawLabel
--, hoverRenderer :: DrawHover --, defaultDrawNodeHover :: DrawHover
--, edgeLabelRenderer :: DrawEdgeLabel --, defaultDrawEdgeLabel :: DrawEdgeLabel
-- Lifecycle -- Lifecycle
--, allowInvalidContainer :: Boolean --, allowInvalidContainer :: Boolean
...@@ -300,9 +298,7 @@ sigmaSettings _theme = ...@@ -300,9 +298,7 @@ sigmaSettings _theme =
--, hideLablesOnMove : false --, hideLablesOnMove : false
renderLabels: false -- initially false, because of forceatlas renderLabels: false -- initially false, because of forceatlas
--, renderEdgeLabels : true --, renderEdgeLabels : true
--, enableEdgeClickEvents : false , enableEdgeEvents: false
--, enableEdgeWheelEvents : false
, enableEdgeHoverEvents: false
-- Component rendering -- Component rendering
, defaultNodeColor: "#FFF" , defaultNodeColor: "#FFF"
--, defaultNodeType : "circle" --, defaultNodeType : "circle"
...@@ -329,9 +325,9 @@ sigmaSettings _theme = ...@@ -329,9 +325,9 @@ sigmaSettings _theme =
--, minCameraRatio : Nothing --, minCameraRatio : Nothing
--, maxCameraRatio : Nothing --, maxCameraRatio : Nothing
-- Renderers -- Renderers
--, labelRenderer : drawLabel --, defaultDrawNodeLabel : drawLabel
--, hoverRenderer : drawHover --, defaultDrawNodeHover : drawHover
--, edgeLabelRenderer : drawEdgeLabel --, defaultDrawEdgeLabel : drawEdgeLabel
-- Lifecycle -- Lifecycle
--, allowInvalidContainer : false --, allowInvalidContainer : false
......
...@@ -4,7 +4,7 @@ import Graph from 'graphology'; ...@@ -4,7 +4,7 @@ import Graph from 'graphology';
import Sigma from 'sigma'; import Sigma from 'sigma';
//import { takeScreenshot } from '../../src/external-deps/sigmajs-screenshot.js'; //import { takeScreenshot } from '../../src/external-deps/sigmajs-screenshot.js';
import takeScreenshot from '../../src/external-deps/sigmajs-screenshot-with-canvas.js'; import takeScreenshot from '../../src/external-deps/sigmajs-screenshot-with-canvas.js';
import CircleNodeProgram from 'sigma/rendering/webgl/programs/node.fast'; import { NodeCircleProgram } from 'sigma/rendering';
import ContourCircleNodeProgram from '../../src/external-deps/sigmajs-circle-with-contour.js'; import ContourCircleNodeProgram from '../../src/external-deps/sigmajs-circle-with-contour.js';
import TriangleNodeProgram from '../../src/external-deps/sigmajs-triangle.js'; import TriangleNodeProgram from '../../src/external-deps/sigmajs-triangle.js';
import ContourTriangleNodeProgram from '../../src/external-deps/sigmajs-triangle-with-contour.js'; import ContourTriangleNodeProgram from '../../src/external-deps/sigmajs-triangle-with-contour.js';
...@@ -198,7 +198,7 @@ function _sigma(left, right, el, opts) { ...@@ -198,7 +198,7 @@ function _sigma(left, right, el, opts) {
const settings = { const settings = {
labelRenderer: drawLabel, labelRenderer: drawLabel,
nodeProgramClasses: { nodeProgramClasses: {
circle: CircleNodeProgram.default, // TODO why default? It seems that import should be fixed circle: NodeCircleProgram,
ccircle: ContourCircleNodeProgram, ccircle: ContourCircleNodeProgram,
triangle: TriangleNodeProgram, triangle: TriangleNodeProgram,
ctriangle: ContourTriangleNodeProgram, ctriangle: ContourTriangleNodeProgram,
...@@ -209,7 +209,7 @@ function _sigma(left, right, el, opts) { ...@@ -209,7 +209,7 @@ function _sigma(left, right, el, opts) {
}, },
...opts.settings ...opts.settings
}; };
let s = new sigma(graph, el, settings); let s = new Sigma(graph, el, settings);
console.log('[_sigma] initializing sigma with el', el, 'opts', opts.settings, 'sigma', s); console.log('[_sigma] initializing sigma with el', el, 'opts', opts.settings, 'sigma', s);
console.log('[_sigma] labelRenderedSizeThreshold', opts.settings.labelRenderedSizeThreshold); console.log('[_sigma] labelRenderedSizeThreshold', opts.settings.labelRenderedSizeThreshold);
sigmaMouseSelector(s); sigmaMouseSelector(s);
......
// language=GLSL
const SHADER_SOURCE = /*glsl*/ `
precision mediump float;
varying vec4 v_color;
varying float v_border;
const float radius = 0.5;
const vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0);
void main(void) {
vec2 m = gl_PointCoord - vec2(0.5, 0.5);
float dist = radius - length(m);
// No antialiasing for picking mode:
#ifdef PICKING_MODE
if (dist > v_border)
gl_FragColor = v_color;
else
gl_FragColor = transparent;
#else
float t = 0.0;
if (dist > v_border)
t = 1.0;
else if (dist > 0.0)
t = dist / v_border;
gl_FragColor = mix(transparent, v_color, t);
#endif
}
`;
export default SHADER_SOURCE;
\ No newline at end of file
// language=GLSL
const SHADER_SOURCE = /*glsl*/ `
attribute vec4 a_id;
attribute vec4 a_color;
attribute vec2 a_position;
attribute float a_size;
uniform float u_sizeRatio;
uniform float u_pixelRatio;
uniform mat3 u_matrix;
varying vec4 v_color;
varying float v_border;
const float bias = 255.0 / 254.0;
void main() {
gl_Position = vec4(
(u_matrix * vec3(a_position, 1)).xy,
0,
1
);
// Multiply the point size twice:
// - x SCALING_RATIO to correct the canvas scaling
// - x 2 to correct the formulae
gl_PointSize = a_size / u_sizeRatio * u_pixelRatio * 2.0;
v_border = (0.5 / a_size) * u_sizeRatio;
#ifdef PICKING_MODE
// For picking mode, we use the ID as the color:
v_color = a_id;
#else
// For normal mode, we use the color:
v_color = a_color;
#endif
v_color.a *= bias;
}
`;
export default SHADER_SOURCE;
\ No newline at end of file
// Based on sigma.js/src/rendering/webgl/programs/node.fast.ts // Based on https://github.com/jacomyal/sigma.js/blob/main/packages/sigma/src/rendering/programs/node-point/index.ts
import { NodeDisplayData } from "sigma/types";
import { floatColor } from "sigma/utils"; import { floatColor } from "sigma/utils";
import vertexShaderSource from "sigma/rendering/webgl/shaders/node.fast.vert.glsl"; import { NodeProgram } from 'sigma/rendering';
import fragmentShaderSource from "sigma/rendering/webgl/shaders/node.fast.frag.glsl";
import { AbstractNodeProgram } from "sigma/rendering/webgl/programs/common/node";
import { RenderParams } from "sigma/rendering/webgl/programs/common/program";
import CircleNodeProgram from 'sigma/rendering/webgl/programs/node.fast';
const POINTS = 2; import VERTEX_SHADER_SOURCE from "./circle-vert.glsl";
const ATTRIBUTES = 4; import FRAGMENT_SHADER_SOURCE from "./circle-frag.glsl";
const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext;
const UNIFORMS = ["u_sizeRatio", "u_pixelRatio", "u_matrix"]
/* /*
export default class NodeContourFastProgram extends AbstractNodeProgram { export default class NodePointProgram<
//constructor(gl : WebGLRenderingContext) { N extends Attributes = Attributes,
constructor(gl) { E extends Attributes = Attributes,
super(gl, vertexShaderSource, fragmentShaderSource, POINTS, ATTRIBUTES); G extends Attributes = Attributes,
this.bind(); > extends NodeProgram<(typeof UNIFORMS)[number], N, E, G> {
}
*/ */
export default class NodeContourFastProgram extends CircleNodeProgram { export default class NodeContourFastProgram extends NodeProgram {
constructor(gl) { getDefinition() {
super(gl, vertexShaderSource, fragmentShaderSource, POINTS, ATTRIBUTES); return {
// NOTE super method above will set POINTS = 1 from CircleNodeProgram VERTICES: 2,
// We need to overwrite this VERTEX_SHADER_SOURCE,
// https://gitlab.iscpif.fr/gargantext/purescript-gargantext/issues/471 FRAGMENT_SHADER_SOURCE,
this.points = POINTS; METHOD: WebGLRenderingContext.POINTS,
this.bind(); UNIFORMS,
ATTRIBUTES: [
{ name: "a_position", size: 2, type: FLOAT },
{ name: "a_size", size: 1, type: FLOAT },
{ name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true },
{ name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true },
],
};
} }
//process(data: NodeDisplayData, hidden: boolean, offset: number): void { // processVisibleItem(nodeIndex: number, startIndex: number, data: NodeDisplayData) {
process(data, hidden, offset) { processVisibleItem(nodeIndex, startIndex, data) {
const array = this.array; const array = this.array;
let i = offset * POINTS * ATTRIBUTES;
if (hidden) {
// contour
array[i++] = 0;
array[i++] = 0;
array[i++] = 0;
array[i++] = 0;
// circle
array[i++] = 0;
array[i++] = 0;
array[i++] = 0;
array[i++] = 0;
return;
}
const color = floatColor(data.color); const color = floatColor(data.color);
//const black = floatColor('black'); //const black = floatColor('black');
const gray = floatColor('#aaa') const gray = floatColor('#aaa')
// contour // contour
array[i++] = data.x; array[startIndex++] = data.x;
array[i++] = data.y; array[startIndex++] = data.y;
array[i++] = data.size + 1; array[startIndex++] = data.size + 1;
//array[i++] = black; //array[i++] = black;
array[i++] = gray; array[startIndex++] = gray;
array[startIndex++] = nodeIndex;
// circle // circle
array[i++] = data.x; array[startIndex++] = data.x;
array[i++] = data.y; array[startIndex++] = data.y;
array[i++] = data.size; array[startIndex++] = data.size;
array[i] = color; array[startIndex++] = color;
array[startIndex++] = nodeIndex;
} }
//render(params: RenderParams): void { //setUniforms({ sizeRatio, pixelRatio, matrix }: RenderParams, { gl, uniformLocations }: ProgramInfo): void {
render(params) { setUniforms({ sizeRatio, pixelRatio, matrix }, { gl, uniformLocations }) {
if (this.hasNothingToRender()) return; const { u_sizeRatio, u_pixelRatio, u_matrix } = uniformLocations;
const gl = this.gl;
const program = this.program;
gl.useProgram(program);
gl.uniform1f(this.ratioLocation, 1 / Math.sqrt(params.ratio));
gl.uniform1f(this.scaleLocation, params.scalingRatio);
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix);
gl.drawArrays(gl.POINTS, 0, this.array.length / ATTRIBUTES); gl.uniform1f(u_pixelRatio, pixelRatio);
gl.uniform1f(u_sizeRatio, sizeRatio);
gl.uniformMatrix3fv(u_matrix, false, matrix);
} }
} }
...@@ -8,33 +8,72 @@ ...@@ -8,33 +8,72 @@
* @module * @module
*/ */
import { NodeDisplayData } from "sigma/types";
import { floatColor } from "sigma/utils"; import { floatColor } from "sigma/utils";
import TriangleProgram from "./sigmajs-triangle-abstract"; import { NodeProgram } from "sigma/rendering";
const POINTS = 12; import VERTEX_SHADER_SOURCE from "./triangle-vert.glsl";
const ATTRIBUTES = 5; import FRAGMENT_SHADER_SOURCE from "./triangle-frag.glsl";
const ANGLE_1_1 = (0 * Math.PI) / 4; const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext;
const ANGLE_1_2 = (2 * Math.PI) / 4;
const ANGLE_1_3 = (4 * Math.PI) / 4;
const ANGLE_2_1 = (4 * Math.PI) / 4;
const ANGLE_2_2 = (6 * Math.PI) / 4;
const ANGLE_2_3 = (8 * Math.PI) / 4;
export default class NodeProgram extends TriangleProgram { const UNIFORMS = ["u_sizeRatio", "u_correctionRatio", "u_matrix"];
constructor(gl) {
super(gl, POINTS, ATTRIBUTES); export default class NodeDiamondContourProgram extends NodeProgram {
static ANGLE_1_1 = (0 * Math.PI) / 4;
static ANGLE_1_2 = (2 * Math.PI) / 4;
static ANGLE_1_3 = (4 * Math.PI) / 4;
static ANGLE_2_1 = (4 * Math.PI) / 4;
static ANGLE_2_2 = (6 * Math.PI) / 4;
static ANGLE_2_3 = (8 * Math.PI) / 4;
getDefinition() {
return {
VERTICES: 12,
VERTEX_SHADER_SOURCE,
FRAGMENT_SHADER_SOURCE,
METHOD: WebGLRenderingContext.TRIANGLES,
UNIFORMS,
ATTRIBUTES: [
{ name: "a_position", size: 2, type: FLOAT },
{ name: "a_size", size: 1, type: FLOAT },
{ name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true },
{ name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true },
],
CONSTANT_ATTRIBUTES: [{ name: "a_angle", size: 1, type: FLOAT }],
CONSTANT_DATA: [[NodeDiamondContourProgram.ANGLE_1_1], [NodeDiamondContourProgram.ANGLE_1_2], [NodeDiamondContourProgram.ANGLE_1_3]
,[NodeDiamondContourProgram.ANGLE_2_1], [NodeDiamondContourProgram.ANGLE_2_2], [NodeDiamondContourProgram.ANGLE_2_3]
,[NodeDiamondContourProgram.ANGLE_1_1], [NodeDiamondContourProgram.ANGLE_1_2], [NodeDiamondContourProgram.ANGLE_1_3]
,[NodeDiamondContourProgram.ANGLE_2_1], [NodeDiamondContourProgram.ANGLE_2_2], [NodeDiamondContourProgram.ANGLE_2_3]],
};
} }
triangleDefinitions(data) { processVisibleItem(nodeIndex, startIndex, data) {
const gray = '#aaa'; const array = this.array;
const color = floatColor(data.color);
const gray = floatColor('#aaa')
const size = data.size / 1.7; // experimental... const size = data.size / 1.7; // experimental...
const contourSize = size + 0.8; // experimental... const contour_size = size + 0.8;
// contour
array[startIndex++] = data.x;
array[startIndex++] = data.y;
array[startIndex++] = contour_size;
array[startIndex++] = gray;
array[startIndex++] = nodeIndex;
// circle
array[startIndex++] = data.x;
array[startIndex++] = data.y;
array[startIndex++] = size;
array[startIndex++] = color;
array[startIndex++] = nodeIndex;
}
setUniforms(params, { gl, uniformLocations }) {
const { u_sizeRatio, u_correctionRatio, u_matrix } = uniformLocations;
return [ { x: data.x, y: data.y, size: contourSize, color: gray, angles: [ANGLE_1_1, ANGLE_1_2, ANGLE_1_3] }, gl.uniform1f(u_correctionRatio, params.correctionRatio);
{ x: data.x, y: data.y, size: contourSize, color: gray, angles: [ANGLE_2_1, ANGLE_2_2, ANGLE_2_3] }, gl.uniform1f(u_sizeRatio, params.sizeRatio);
{ x: data.x, y: data.y, size: size, color: data.color, angles: [ANGLE_1_1, ANGLE_1_2, ANGLE_1_3] }, gl.uniformMatrix3fv(u_matrix, false, params.matrix);
{ x: data.x, y: data.y, size: size, color: data.color, angles: [ANGLE_2_1, ANGLE_2_2, ANGLE_2_3] } ];
} }
} }
\ No newline at end of file
...@@ -8,29 +8,60 @@ ...@@ -8,29 +8,60 @@
* @module * @module
*/ */
import { NodeDisplayData } from "sigma/types";
import { floatColor } from "sigma/utils"; import { floatColor } from "sigma/utils";
import TriangleProgram from "./sigmajs-triangle-abstract"; import { NodeProgram } from "sigma/rendering";
const POINTS = 6; import VERTEX_SHADER_SOURCE from "./triangle-vert.glsl";
const ATTRIBUTES = 5; import FRAGMENT_SHADER_SOURCE from "./triangle-frag.glsl";
const ANGLE_1_1 = (0 * Math.PI) / 4; const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext;
const ANGLE_1_2 = (2 * Math.PI) / 4;
const ANGLE_1_3 = (4 * Math.PI) / 4;
const ANGLE_2_1 = (4 * Math.PI) / 4;
const ANGLE_2_2 = (6 * Math.PI) / 4;
const ANGLE_2_3 = (8 * Math.PI) / 4;
export default class NodeProgram extends TriangleProgram { const UNIFORMS = ["u_sizeRatio", "u_correctionRatio", "u_matrix"];
constructor(gl) {
super(gl, POINTS, ATTRIBUTES); export default class NodeDiamondProgram extends NodeProgram {
static ANGLE_1_1 = (0 * Math.PI) / 4;
static ANGLE_1_2 = (2 * Math.PI) / 4;
static ANGLE_1_3 = (4 * Math.PI) / 4;
static ANGLE_2_1 = (4 * Math.PI) / 4;
static ANGLE_2_2 = (6 * Math.PI) / 4;
static ANGLE_2_3 = (8 * Math.PI) / 4;
getDefinition() {
return {
VERTICES: 6,
VERTEX_SHADER_SOURCE,
FRAGMENT_SHADER_SOURCE,
METHOD: WebGLRenderingContext.TRIANGLES,
UNIFORMS,
ATTRIBUTES: [
{ name: "a_position", size: 2, type: FLOAT },
{ name: "a_size", size: 1, type: FLOAT },
{ name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true },
{ name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true },
],
CONSTANT_ATTRIBUTES: [{ name: "a_angle", size: 1, type: FLOAT }],
CONSTANT_DATA: [[NodeDiamondProgram.ANGLE_1_1], [NodeDiamondProgram.ANGLE_1_2], [NodeDiamondProgram.ANGLE_1_3]
,[NodeDiamondProgram.ANGLE_2_1], [NodeDiamondProgram.ANGLE_2_2], [NodeDiamondProgram.ANGLE_2_3]],
};
} }
triangleDefinitions(data) { processVisibleItem(nodeIndex, startIndex, data) {
const array = this.array;
const color = floatColor(data.color);
const size = data.size / 1.7; // experimental... const size = data.size / 1.7; // experimental...
return [ { x: data.x, y: data.y, size: size, color: data.color, angles: [ANGLE_1_1, ANGLE_1_2, ANGLE_1_3] }, array[startIndex++] = data.x;
{ x: data.x, y: data.y, size: size, color: data.color, angles: [ANGLE_2_1, ANGLE_2_2, ANGLE_2_3] } ]; array[startIndex++] = data.y;
array[startIndex++] = size;
array[startIndex++] = color;
array[startIndex++] = nodeIndex;
}
setUniforms(params, { gl, uniformLocations }) {
const { u_sizeRatio, u_correctionRatio, u_matrix } = uniformLocations;
gl.uniform1f(u_correctionRatio, params.correctionRatio);
gl.uniform1f(u_sizeRatio, params.sizeRatio);
gl.uniformMatrix3fv(u_matrix, false, params.matrix);
} }
} }
...@@ -8,33 +8,72 @@ ...@@ -8,33 +8,72 @@
* @module * @module
*/ */
import { NodeDisplayData } from "sigma/types";
import { floatColor } from "sigma/utils"; import { floatColor } from "sigma/utils";
import TriangleProgram from "./sigmajs-triangle-abstract"; import { NodeProgram } from "sigma/rendering";
const POINTS = 12; import VERTEX_SHADER_SOURCE from "./triangle-vert.glsl";
const ATTRIBUTES = 5; import FRAGMENT_SHADER_SOURCE from "./triangle-frag.glsl";
const ANGLE_1_1 = - (1 * Math.PI) / 4; const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext;
const ANGLE_1_2 = (1 * Math.PI) / 4;
const ANGLE_1_3 = (3 * Math.PI) / 4;
const ANGLE_2_1 = (3 * Math.PI) / 4;
const ANGLE_2_2 = (5 * Math.PI) / 4;
const ANGLE_2_3 = (7 * Math.PI) / 4;
export default class NodeProgram extends TriangleProgram { const UNIFORMS = ["u_sizeRatio", "u_correctionRatio", "u_matrix"];
constructor(gl) {
super(gl, POINTS, ATTRIBUTES); export default class NodeSquareContourProgram extends NodeProgram {
static ANGLE_1_1 = - (1 * Math.PI) / 4;
static ANGLE_1_2 = (1 * Math.PI) / 4;
static ANGLE_1_3 = (3 * Math.PI) / 4;
static ANGLE_2_1 = (3 * Math.PI) / 4;
static ANGLE_2_2 = (5 * Math.PI) / 4;
static ANGLE_2_3 = (7 * Math.PI) / 4;
getDefinition() {
return {
VERTICES: 12,
VERTEX_SHADER_SOURCE,
FRAGMENT_SHADER_SOURCE,
METHOD: WebGLRenderingContext.TRIANGLES,
UNIFORMS,
ATTRIBUTES: [
{ name: "a_position", size: 2, type: FLOAT },
{ name: "a_size", size: 1, type: FLOAT },
{ name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true },
{ name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true },
],
CONSTANT_ATTRIBUTES: [{ name: "a_angle", size: 1, type: FLOAT }],
CONSTANT_DATA: [[NodeSquareContourProgram.ANGLE_1_1], [NodeSquareContourProgram.ANGLE_1_2], [NodeSquareContourProgram.ANGLE_1_3]
,[NodeSquareContourProgram.ANGLE_2_1], [NodeSquareContourProgram.ANGLE_2_2], [NodeSquareContourProgram.ANGLE_2_3]
,[NodeSquareContourProgram.ANGLE_1_1], [NodeSquareContourProgram.ANGLE_1_2], [NodeSquareContourProgram.ANGLE_1_3]
,[NodeSquareContourProgram.ANGLE_2_1], [NodeSquareContourProgram.ANGLE_2_2], [NodeSquareContourProgram.ANGLE_2_3]],
};
} }
triangleDefinitions(data) { processVisibleItem(nodeIndex, startIndex, data) {
const gray = '#aaa'; const array = this.array;
const color = floatColor(data.color);
const gray = floatColor('#aaa')
const size = data.size / 1.7; // experimental... const size = data.size / 1.7; // experimental...
const contourSize = size + 0.8; // experimental... const contour_size = size + 0.8;
// contour
array[startIndex++] = data.x;
array[startIndex++] = data.y;
array[startIndex++] = contour_size;
array[startIndex++] = gray;
array[startIndex++] = nodeIndex;
// circle
array[startIndex++] = data.x;
array[startIndex++] = data.y;
array[startIndex++] = size;
array[startIndex++] = color;
array[startIndex++] = nodeIndex;
}
setUniforms(params, { gl, uniformLocations }) {
const { u_sizeRatio, u_correctionRatio, u_matrix } = uniformLocations;
return [ { x: data.x, y: data.y, size: contourSize, color: gray, angles: [ANGLE_1_1, ANGLE_1_2, ANGLE_1_3] }, gl.uniform1f(u_correctionRatio, params.correctionRatio);
{ x: data.x, y: data.y, size: contourSize, color: gray, angles: [ANGLE_2_1, ANGLE_2_2, ANGLE_2_3] }, gl.uniform1f(u_sizeRatio, params.sizeRatio);
{ x: data.x, y: data.y, size: size, color: data.color, angles: [ANGLE_1_1, ANGLE_1_2, ANGLE_1_3] }, gl.uniformMatrix3fv(u_matrix, false, params.matrix);
{ x: data.x, y: data.y, size: size, color: data.color, angles: [ANGLE_2_1, ANGLE_2_2, ANGLE_2_3] } ];
} }
} }
\ No newline at end of file
...@@ -8,29 +8,61 @@ ...@@ -8,29 +8,61 @@
* @module * @module
*/ */
import { NodeDisplayData } from "sigma/types";
import { floatColor } from "sigma/utils"; import { floatColor } from "sigma/utils";
import TriangleProgram from "./sigmajs-triangle-abstract"; import { NodeProgram } from "sigma/rendering";
const POINTS = 6; import VERTEX_SHADER_SOURCE from "./triangle-vert.glsl";
const ATTRIBUTES = 5; import FRAGMENT_SHADER_SOURCE from "./triangle-frag.glsl";
const ANGLE_1_1 = - (1 * Math.PI) / 4; const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext;
const ANGLE_1_2 = (1 * Math.PI) / 4;
const ANGLE_1_3 = (3 * Math.PI) / 4;
const ANGLE_2_1 = (3 * Math.PI) / 4;
const ANGLE_2_2 = (5 * Math.PI) / 4;
const ANGLE_2_3 = (7 * Math.PI) / 4;
export default class NodeProgram extends TriangleProgram { const UNIFORMS = ["u_sizeRatio", "u_correctionRatio", "u_matrix"];
constructor(gl) {
super(gl, POINTS, ATTRIBUTES); export default class NodeSquareProgram extends NodeProgram {
static ANGLE_1_1 = - (1 * Math.PI) / 4;
static ANGLE_1_2 = (1 * Math.PI) / 4;
static ANGLE_1_3 = (3 * Math.PI) / 4;
static ANGLE_2_1 = (3 * Math.PI) / 4;
static ANGLE_2_2 = (5 * Math.PI) / 4;
static ANGLE_2_3 = (7 * Math.PI) / 4;
getDefinition() {
return {
VERTICES: 6,
VERTEX_SHADER_SOURCE,
FRAGMENT_SHADER_SOURCE,
METHOD: WebGLRenderingContext.TRIANGLES,
UNIFORMS,
ATTRIBUTES: [
{ name: "a_position", size: 2, type: FLOAT },
{ name: "a_size", size: 1, type: FLOAT },
{ name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true },
{ name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true },
],
CONSTANT_ATTRIBUTES: [{ name: "a_angle", size: 1, type: FLOAT }],
CONSTANT_DATA: [[NodeSquareProgram.ANGLE_1_1], [NodeSquareProgram.ANGLE_1_2], [NodeSquareProgram.ANGLE_1_3]
,[NodeSquareProgram.ANGLE_2_1], [NodeSquareProgram.ANGLE_2_2], [NodeSquareProgram.ANGLE_2_3]],
};
} }
triangleDefinitions(data) { processVisibleItem(nodeIndex, startIndex, data) {
const array = this.array;
const color = floatColor(data.color);
const size = data.size / 1.7; // experimental... const size = data.size / 1.7; // experimental...
return [ { x: data.x, y: data.y, size: size, color: data.color, angles: [ANGLE_1_1, ANGLE_1_2, ANGLE_1_3] }, array[startIndex++] = data.x;
{ x: data.x, y: data.y, size: size, color: data.color, angles: [ANGLE_2_1, ANGLE_2_2, ANGLE_2_3] }]; array[startIndex++] = data.y;
array[startIndex++] = size;
array[startIndex++] = color;
array[startIndex++] = nodeIndex;
}
setUniforms(params, { gl, uniformLocations }) {
const { u_sizeRatio, u_correctionRatio, u_matrix } = uniformLocations;
gl.uniform1f(u_correctionRatio, params.correctionRatio);
gl.uniform1f(u_sizeRatio, params.sizeRatio);
gl.uniformMatrix3fv(u_matrix, false, params.matrix);
} }
} }
/**
* Sigma.js WebGL Renderer Node Program
* =====================================
*
* Simple program rendering nodes as triangles.
* It does not extend AbstractNodeProgram, which works very differently, and
* really targets the gl.POINTS drawing methods.
* @module
*/
import { NodeDisplayData } from "sigma/types";
import { floatColor } from "sigma/utils";
import { AbstractProgram, RenderParams } from "sigma/rendering/webgl/programs/common/program";
const vertexShaderSource = `
attribute vec2 a_position;
attribute float a_size;
attribute float a_angle;
attribute vec4 a_color;
uniform mat3 u_matrix;
uniform float u_sqrtZoomRatio;
uniform float u_correctionRatio;
varying vec4 v_color;
varying vec2 v_diffVector;
varying float v_radius;
varying float v_border;
const float bias = 255.0 / 254.0;
const float marginRatio = 1.05;
void main() {
float size = a_size * u_correctionRatio * u_sqrtZoomRatio * 4.0;
vec2 diffVector = size * vec2(cos(a_angle), sin(a_angle));
vec2 position = a_position + diffVector * marginRatio;
gl_Position = vec4(
(u_matrix * vec3(position, 1)).xy,
0,
1
);
v_border = u_correctionRatio * u_sqrtZoomRatio * u_sqrtZoomRatio;
v_diffVector = diffVector;
//v_radius = size / 2.0 / marginRatio;
v_radius = 1.0;
v_color = a_color;
v_color.a *= bias;
}
`;
const fragmentShaderSource = `
precision mediump float;
varying vec4 v_color;
varying vec2 v_diffVector;
varying float v_radius;
varying float v_border;
const vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0);
void main(void) {
float dist = length(v_diffVector) - v_radius;
// Originally, a triangle is drawn. This code paints it in such a
// way that a circle is rendered.
//float t = 0.0;
//if (dist > v_border) {
// t = 1.0;
//} else if (dist > 0.0) {
// t = dist / v_border;
//}
//gl_FragColor = mix(v_color, transparent, t);
gl_FragColor = v_color;
}
`;
const POINTS = 3;
const ATTRIBUTES = 5;
const ANGLE_1 = - (0.5 * Math.PI) / 3;
const ANGLE_2 = (1.5 * Math.PI) / 3;
const ANGLE_3 = (3.5 * Math.PI) / 3;
export default class NodeProgram extends AbstractProgram {
constructor(gl, points, attributes) {
let pts = points || POINTS;
let attribs = attributes || ATTRIBUTES;
super(gl, vertexShaderSource, fragmentShaderSource, pts, attribs);
// Locations
this.positionLocation = gl.getAttribLocation(this.program, "a_position");
this.sizeLocation = gl.getAttribLocation(this.program, "a_size");
this.colorLocation = gl.getAttribLocation(this.program, "a_color");
this.angleLocation = gl.getAttribLocation(this.program, "a_angle");
// Uniform Location
const matrixLocation = gl.getUniformLocation(this.program, "u_matrix");
if (matrixLocation === null) throw new Error("AbstractNodeProgram: error while getting matrixLocation");
this.matrixLocation = matrixLocation;
const sqrtZoomRatioLocation = gl.getUniformLocation(this.program, "u_sqrtZoomRatio");
if (sqrtZoomRatioLocation === null) throw new Error("NodeProgram: error while getting sqrtZoomRatioLocation");
this.sqrtZoomRatioLocation = sqrtZoomRatioLocation;
const correctionRatioLocation = gl.getUniformLocation(this.program, "u_correctionRatio");
if (correctionRatioLocation === null) throw new Error("NodeProgram: error while getting correctionRatioLocation");
this.correctionRatioLocation = correctionRatioLocation;
this.bind();
}
bind() {
const gl = this.gl;
gl.enableVertexAttribArray(this.positionLocation);
gl.enableVertexAttribArray(this.sizeLocation);
gl.enableVertexAttribArray(this.colorLocation);
gl.enableVertexAttribArray(this.angleLocation);
gl.vertexAttribPointer(
this.positionLocation,
2,
gl.FLOAT,
false,
this.attributes * Float32Array.BYTES_PER_ELEMENT,
0,
);
gl.vertexAttribPointer(
this.sizeLocation,
1,
gl.FLOAT,
false,
this.attributes * Float32Array.BYTES_PER_ELEMENT,
8
);
gl.vertexAttribPointer(
this.colorLocation,
4,
gl.UNSIGNED_BYTE,
true,
this.attributes * Float32Array.BYTES_PER_ELEMENT,
12,
);
gl.vertexAttribPointer(
this.angleLocation,
1,
gl.FLOAT,
false,
this.attributes * Float32Array.BYTES_PER_ELEMENT,
16,
);
}
process(data, hidden, offset) {
const array = this.array;
let i = offset * this.points * this.attributes;
if (hidden) {
for (let l = i + this.points * this.attributes; i < l; i++) array[i] = 0;
return;
}
let definitions = this.triangleDefinitions(data);
for(let l = 0; l < definitions.length; l++) {
this.renderTriangle(i + l * 3*this.attributes, definitions[l]);
}
}
// overwrite this function
triangleDefinitions(data) {
const size = data.size / 1.7; // experimental...
return [ { x: data.x, y: data.y, size: data.size, color: data.color, angles: [ANGLE_1, ANGLE_2, ANGLE_3] } ];
}
renderTriangle(i, { x, y, size, color, angles }) {
const array = this.array;
const fColor = floatColor(color);
array[i++] = x;
array[i++] = y;
array[i++] = size;
array[i++] = fColor;
array[i++] = angles[0];
array[i++] = x;
array[i++] = y;
array[i++] = size;
array[i++] = fColor;
array[i++] = angles[1];
array[i++] = x;
array[i++] = y;
array[i++] = size;
array[i++] = fColor;
array[i] = angles[2];
}
render(params) {
if (this.hasNothingToRender()) return;
const gl = this.gl;
const program = this.program;
gl.useProgram(program);
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix);
gl.uniform1f(this.sqrtZoomRatioLocation, Math.sqrt(params.ratio));
gl.uniform1f(this.correctionRatioLocation, params.correctionRatio);
gl.drawArrays(gl.TRIANGLES, 0, this.array.length / this.attributes);
}
}
...@@ -8,28 +8,67 @@ ...@@ -8,28 +8,67 @@
* @module * @module
*/ */
import { NodeDisplayData } from "sigma/types";
import { floatColor } from "sigma/utils"; import { floatColor } from "sigma/utils";
import TriangleProgram from "./sigmajs-triangle-abstract"; import { NodeProgram } from "sigma/rendering";
const POINTS = 6; import VERTEX_SHADER_SOURCE from "./triangle-vert.glsl";
const ATTRIBUTES = 5; import FRAGMENT_SHADER_SOURCE from "./triangle-frag.glsl";
const ANGLE_1 = - (0.5 * Math.PI) / 3; const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext;
const ANGLE_2 = (1.5 * Math.PI) / 3;
const ANGLE_3 = (3.5 * Math.PI) / 3;
export default class NodeProgram extends TriangleProgram { const UNIFORMS = ["u_sizeRatio", "u_correctionRatio", "u_matrix"];
constructor(gl) {
super(gl, POINTS, ATTRIBUTES); export default class NodeTriangleContourProgram extends NodeProgram {
static ANGLE_1 = - (0.5 * Math.PI) / 3;
static ANGLE_2 = (1.5 * Math.PI) / 3;
static ANGLE_3 = (3.5 * Math.PI) / 3;
getDefinition() {
return {
VERTICES: 6,
VERTEX_SHADER_SOURCE,
FRAGMENT_SHADER_SOURCE,
METHOD: WebGLRenderingContext.TRIANGLES,
UNIFORMS,
ATTRIBUTES: [
{ name: "a_position", size: 2, type: FLOAT },
{ name: "a_size", size: 1, type: FLOAT },
{ name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true },
{ name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true },
],
CONSTANT_ATTRIBUTES: [{ name: "a_angle", size: 1, type: FLOAT }],
CONSTANT_DATA: [[NodeTriangleContourProgram.ANGLE_1], [NodeTriangleContourProgram.ANGLE_2], [NodeTriangleContourProgram.ANGLE_3]
,[NodeTriangleContourProgram.ANGLE_1], [NodeTriangleContourProgram.ANGLE_2], [NodeTriangleContourProgram.ANGLE_3]],
};
} }
triangleDefinitions(data) { processVisibleItem(nodeIndex, startIndex, data) {
const array = this.array;
const color = floatColor(data.color);
const gray = floatColor('#aaa') const gray = floatColor('#aaa')
const size = data.size / 2.3; // experimental... const size = data.size / 1.7; // experimental...
const contourSize = size + 0.8; // experimental... const contour_size = size + 0.8;
// contour
array[startIndex++] = data.x;
array[startIndex++] = data.y;
array[startIndex++] = contour_size;
array[startIndex++] = gray;
array[startIndex++] = nodeIndex;
// circle
array[startIndex++] = data.x;
array[startIndex++] = data.y;
array[startIndex++] = size;
array[startIndex++] = color;
array[startIndex++] = nodeIndex;
}
setUniforms(params, { gl, uniformLocations }) {
const { u_sizeRatio, u_correctionRatio, u_matrix } = uniformLocations;
return [ { x: data.x, y: data.y, size: contourSize, color: '#aaa', angles: [ANGLE_1, ANGLE_2, ANGLE_3] }, gl.uniform1f(u_correctionRatio, params.correctionRatio);
{ x: data.x, y: data.y, size: size, color: data.color, angles: [ANGLE_1, ANGLE_2, ANGLE_3] }]; gl.uniform1f(u_sizeRatio, params.sizeRatio);
gl.uniformMatrix3fv(u_matrix, false, params.matrix);
} }
} }
\ No newline at end of file
...@@ -8,193 +8,56 @@ ...@@ -8,193 +8,56 @@
* @module * @module
*/ */
import { NodeDisplayData } from "sigma/types";
import { floatColor } from "sigma/utils"; import { floatColor } from "sigma/utils";
import { AbstractProgram, RenderParams } from "sigma/rendering/webgl/programs/common/program"; import { NodeProgram } from "sigma/rendering";
const vertexShaderSource = ` import VERTEX_SHADER_SOURCE from "./triangle-vert.glsl";
attribute vec2 a_position; import FRAGMENT_SHADER_SOURCE from "./triangle-frag.glsl";
attribute float a_size;
attribute float a_angle; const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext;
attribute vec4 a_color;
const UNIFORMS = ["u_sizeRatio", "u_correctionRatio", "u_matrix"];
uniform mat3 u_matrix;
uniform float u_sqrtZoomRatio; export default class NodeTriangleProgram extends NodeProgram {
uniform float u_correctionRatio; static ANGLE_1 = - (0.5 * Math.PI) / 3;
static ANGLE_2 = (1.5 * Math.PI) / 3;
varying vec4 v_color; static ANGLE_3 = (3.5 * Math.PI) / 3;
varying vec2 v_diffVector;
varying float v_radius; getDefinition() {
varying float v_border; return {
VERTICES: 3,
const float bias = 255.0 / 254.0; VERTEX_SHADER_SOURCE,
const float marginRatio = 1.05; FRAGMENT_SHADER_SOURCE,
METHOD: WebGLRenderingContext.TRIANGLES,
void main() { UNIFORMS,
float size = a_size * u_correctionRatio * u_sqrtZoomRatio * 4.0; ATTRIBUTES: [
vec2 diffVector = size * vec2(cos(a_angle), sin(a_angle)); { name: "a_position", size: 2, type: FLOAT },
vec2 position = a_position + diffVector * marginRatio; { name: "a_size", size: 1, type: FLOAT },
gl_Position = vec4( { name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true },
(u_matrix * vec3(position, 1)).xy, { name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true },
0, ],
1 CONSTANT_ATTRIBUTES: [{ name: "a_angle", size: 1, type: FLOAT }],
); CONSTANT_DATA: [[NodeTriangleProgram.ANGLE_1], [NodeTriangleProgram.ANGLE_2], [NodeTriangleProgram.ANGLE_3]],
};
v_border = u_correctionRatio * u_sqrtZoomRatio * u_sqrtZoomRatio;
v_diffVector = diffVector;
//v_radius = size / 2.0 / marginRatio;
v_radius = 1.0;
v_color = a_color;
v_color.a *= bias;
}
`;
const fragmentShaderSource = `
precision mediump float;
varying vec4 v_color;
varying vec2 v_diffVector;
varying float v_radius;
varying float v_border;
const vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0);
void main(void) {
float dist = length(v_diffVector) - v_radius;
// Originally, a triangle is drawn. This code paints it in such a
// way that a circle is rendered.
//float t = 0.0;
//if (dist > v_border) {
// t = 1.0;
//} else if (dist > 0.0) {
// t = dist / v_border;
//}
//gl_FragColor = mix(v_color, transparent, t);
gl_FragColor = v_color;
}
`;
const POINTS = 3;
const ATTRIBUTES = 5;
const ANGLE_1 = - (0.5 * Math.PI) / 3;
const ANGLE_2 = (1.5 * Math.PI) / 3;
const ANGLE_3 = (3.5 * Math.PI) / 3;
export default class NodeProgram extends AbstractProgram {
constructor(gl) {
super(gl, vertexShaderSource, fragmentShaderSource, POINTS, ATTRIBUTES);
// Locations
this.positionLocation = gl.getAttribLocation(this.program, "a_position");
this.sizeLocation = gl.getAttribLocation(this.program, "a_size");
this.colorLocation = gl.getAttribLocation(this.program, "a_color");
this.angleLocation = gl.getAttribLocation(this.program, "a_angle");
// Uniform Location
const matrixLocation = gl.getUniformLocation(this.program, "u_matrix");
if (matrixLocation === null) throw new Error("AbstractNodeProgram: error while getting matrixLocation");
this.matrixLocation = matrixLocation;
const sqrtZoomRatioLocation = gl.getUniformLocation(this.program, "u_sqrtZoomRatio");
if (sqrtZoomRatioLocation === null) throw new Error("NodeProgram: error while getting sqrtZoomRatioLocation");
this.sqrtZoomRatioLocation = sqrtZoomRatioLocation;
const correctionRatioLocation = gl.getUniformLocation(this.program, "u_correctionRatio");
if (correctionRatioLocation === null) throw new Error("NodeProgram: error while getting correctionRatioLocation");
this.correctionRatioLocation = correctionRatioLocation;
this.bind();
} }
bind() { processVisibleItem(nodeIndex, startIndex, data) {
const gl = this.gl;
gl.enableVertexAttribArray(this.positionLocation);
gl.enableVertexAttribArray(this.sizeLocation);
gl.enableVertexAttribArray(this.colorLocation);
gl.enableVertexAttribArray(this.angleLocation);
gl.vertexAttribPointer(
this.positionLocation,
2,
gl.FLOAT,
false,
this.attributes * Float32Array.BYTES_PER_ELEMENT,
0,
);
gl.vertexAttribPointer(
this.sizeLocation,
1,
gl.FLOAT,
false,
this.attributes * Float32Array.BYTES_PER_ELEMENT,
8
);
gl.vertexAttribPointer(
this.colorLocation,
4,
gl.UNSIGNED_BYTE,
true,
this.attributes * Float32Array.BYTES_PER_ELEMENT,
12,
);
gl.vertexAttribPointer(
this.angleLocation,
1,
gl.FLOAT,
false,
this.attributes * Float32Array.BYTES_PER_ELEMENT,
16,
);
}
process(data, hidden, offset) {
const array = this.array; const array = this.array;
let i = offset * POINTS * ATTRIBUTES;
if (hidden) {
for (let l = i + POINTS * ATTRIBUTES; i < l; i++) array[i] = 0;
return;
}
const color = floatColor(data.color); const color = floatColor(data.color);
const size = data.size / 1.7; // experimental... const size = data.size / 1.7; // experimental...
array[i++] = data.x; array[startIndex++] = data.x;
array[i++] = data.y; array[startIndex++] = data.y;
array[i++] = size; array[startIndex++] = size;
array[i++] = color; array[startIndex++] = color;
array[i++] = ANGLE_1; array[startIndex++] = nodeIndex;
array[i++] = data.x;
array[i++] = data.y;
array[i++] = size;
array[i++] = color;
array[i++] = ANGLE_2;
array[i++] = data.x;
array[i++] = data.y;
array[i++] = size;
array[i++] = color;
array[i] = ANGLE_3;
} }
render(params) { setUniforms(params, { gl, uniformLocations }) {
if (this.hasNothingToRender()) return; const { u_sizeRatio, u_correctionRatio, u_matrix } = uniformLocations;
const gl = this.gl;
const program = this.program;
gl.useProgram(program);
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix);
gl.uniform1f(this.sqrtZoomRatioLocation, Math.sqrt(params.ratio));
gl.uniform1f(this.correctionRatioLocation, params.correctionRatio);
gl.drawArrays(gl.TRIANGLES, 0, this.array.length / ATTRIBUTES); gl.uniform1f(u_correctionRatio, params.correctionRatio);
gl.uniform1f(u_sizeRatio, params.sizeRatio);
gl.uniformMatrix3fv(u_matrix, false, params.matrix);
} }
} }
// language=GLSL
const SHADER_SOURCE = /*glsl*/ `
precision highp float;
varying vec4 v_color;
varying vec2 v_diffVector;
varying float v_radius;
uniform float u_correctionRatio;
const vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0);
void main(void) {
float border = u_correctionRatio * 2.0;
float dist = length(v_diffVector) - v_radius + border;
// Originally, a triangle is drawn. This code paints it in such a
// way that a circle is rendered.
//float t = 0.0;
//if (dist > v_border) {
// t = 1.0;
//} else if (dist > 0.0) {
// t = dist / v_border;
//}
//gl_FragColor = mix(v_color, transparent, t);
gl_FragColor = v_color;
}
`;
export default SHADER_SOURCE;
\ No newline at end of file
// language=GLSL
const SHADER_SOURCE = /*glsl*/ `
attribute vec4 a_id;
attribute vec4 a_color;
attribute vec2 a_position;
attribute float a_size;
attribute float a_angle;
uniform mat3 u_matrix;
uniform float u_sizeRatio;
uniform float u_correctionRatio;
varying vec4 v_color;
varying vec2 v_diffVector;
varying float v_radius;
varying float v_border;
const float bias = 255.0 / 254.0;
void main() {
float size = a_size * u_correctionRatio / u_sizeRatio * 4.0;
vec2 diffVector = size * vec2(cos(a_angle), sin(a_angle));
vec2 position = a_position + diffVector;
gl_Position = vec4(
(u_matrix * vec3(position, 1)).xy,
0,
1
);
v_diffVector = diffVector;
v_radius = size / 2.0;
#ifdef PICKING_MODE
// For picking mode, we use the ID as the color:
v_color = a_id;
#else
// For normal mode, we use the color:
v_color = a_color;
#endif
v_color.a *= bias;
}
`;
export default SHADER_SOURCE;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment