From eb3b2deca766b9ad8c856d8183c2a8dc9dea7831 Mon Sep 17 00:00:00 2001 From: Alexis Jacomy Date: Wed, 10 Jul 2024 10:51:02 +0200 Subject: [PATCH] [all] Implements depth in all edge programs This commit is related to #1427. Details: - Copies code from node programs to edge programs to handle depth - Adds code to clear the depth buffer before rendering - Fixes various node programs depth issues (where the depth wasn't normalized) --- packages/edge-curve/src/factory.ts | 28 ++++++++++------- packages/edge-curve/src/shader-frag.ts | 4 ++- packages/edge-curve/src/shader-vert.ts | 9 ++++++ packages/node-border/src/factory.ts | 6 ++-- packages/node-border/src/shader-vert.ts | 6 ++-- packages/node-image/src/factory.ts | 6 ++-- packages/node-image/src/shader-vert.ts | 6 ++-- packages/node-piechart/src/factory.ts | 6 ++-- packages/node-piechart/src/shader-vert.ts | 6 ++-- packages/sigma/src/rendering/edge.ts | 7 +++-- .../programs/edge-arrow-head/index.ts | 27 +++++++++------- .../programs/edge-arrow-head/vert.glsl.ts | 8 +++++ .../rendering/programs/edge-clamped/index.ts | 31 +++++++++++-------- .../programs/edge-clamped/vert.glsl.ts | 9 ++++++ .../src/rendering/programs/edge-line/index.ts | 15 ++++++--- .../rendering/programs/edge-line/vert.glsl.ts | 9 ++++++ .../programs/edge-rectangle/frag.glsl.ts | 4 +++ .../programs/edge-rectangle/index.ts | 29 ++++++++++------- .../programs/edge-rectangle/vert.glsl.ts | 9 ++++++ .../rendering/programs/edge-triangle/index.ts | 19 +++++++++--- .../programs/edge-triangle/vert.glsl.ts | 9 ++++++ .../rendering/programs/node-circle/index.ts | 6 ++-- .../programs/node-circle/vert.glsl.ts | 11 ++++--- .../rendering/programs/node-point/index.ts | 6 ++-- .../programs/node-point/vert.glsl.ts | 11 ++++--- packages/sigma/src/sigma.ts | 12 ++++--- 26 files changed, 201 insertions(+), 98 deletions(-) diff --git a/packages/edge-curve/src/factory.ts b/packages/edge-curve/src/factory.ts index 6ccd62919..78932ab1e 100644 --- a/packages/edge-curve/src/factory.ts +++ b/packages/edge-curve/src/factory.ts @@ -20,17 +20,8 @@ export default function createEdgeCurveProgram< ...(inputOptions || {}), }; const { arrowHead, curvatureAttribute, drawLabel } = options as CreateEdgeCurveProgramOptions; - const UNIFORMS = [ - "u_matrix", - "u_sizeRatio", - "u_dimensions", - "u_pixelRatio", - "u_feather", - "u_minEdgeThickness", - ...(arrowHead ? ["u_lengthToThicknessRatio", "u_widenessToThicknessRatio"] : []), - ] as const; - return class EdgeCurveProgram extends EdgeProgram<(typeof UNIFORMS)[number], N, E, G> { + return class EdgeCurveProgram extends EdgeProgram { drawLabel = drawLabel || createDrawCurvedEdgeLabel(options); getDefinition() { @@ -39,7 +30,16 @@ export default function createEdgeCurveProgram< VERTEX_SHADER_SOURCE: getVertexShader(options), FRAGMENT_SHADER_SOURCE: getFragmentShader(options), METHOD: WebGLRenderingContext.TRIANGLES, - UNIFORMS, + UNIFORMS: [ + "u_matrix", + "u_sizeRatio", + "u_dimensions", + "u_pixelRatio", + "u_feather", + "u_minEdgeThickness", + ...(arrowHead ? ["u_lengthToThicknessRatio", "u_widenessToThicknessRatio"] : []), + ...(this.hasDepth ? ["a_maxDepth"] : []), + ], ATTRIBUTES: [ { name: "a_source", size: 2, type: FLOAT }, { name: "a_target", size: 2, type: FLOAT }, @@ -48,6 +48,7 @@ export default function createEdgeCurveProgram< { name: "a_curvature", size: 1, type: FLOAT }, { name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true }, { name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true }, + ...(this.hasDepth ? [{ name: "a_depth", size: 1, type: FLOAT }] : []), ], CONSTANT_ATTRIBUTES: [ { name: "a_current", size: 1, type: FLOAT }, // TODO: could optimize to bool @@ -91,6 +92,9 @@ export default function createEdgeCurveProgram< array[startIndex++] = curvature; array[startIndex++] = color; array[startIndex++] = edgeIndex; + if (this.hasDepth) { + array[startIndex++] = data.depth; + } } setUniforms(params: RenderParams, { gl, uniformLocations }: ProgramInfo): void { @@ -103,6 +107,8 @@ export default function createEdgeCurveProgram< gl.uniform2f(u_dimensions, params.width * params.pixelRatio, params.height * params.pixelRatio); gl.uniform1f(u_minEdgeThickness, params.minEdgeThickness); + if (this.hasDepth) gl.uniform1f(uniformLocations.a_maxDepth, params.maxEdgesDepth); + if (arrowHead) { const { u_lengthToThicknessRatio, u_widenessToThicknessRatio } = uniformLocations; diff --git a/packages/edge-curve/src/shader-frag.ts b/packages/edge-curve/src/shader-frag.ts index 3c8250520..3d3acc31e 100644 --- a/packages/edge-curve/src/shader-frag.ts +++ b/packages/edge-curve/src/shader-frag.ts @@ -73,7 +73,9 @@ ${ gl_FragColor = mix(v_color, transparent, t); #endif } else { - gl_FragColor = transparent; + #ifdef HAS_DEPTH + discard; + #endif } } `; diff --git a/packages/edge-curve/src/shader-vert.ts b/packages/edge-curve/src/shader-vert.ts index c396018b2..87c1e3f16 100644 --- a/packages/edge-curve/src/shader-vert.ts +++ b/packages/edge-curve/src/shader-vert.ts @@ -36,6 +36,11 @@ uniform float u_widenessToThicknessRatio; : "" } +#ifdef HAS_DEPTH +attribute float a_depth; +uniform float a_maxDepth; +#endif + const float bias = 255.0 / 254.0; const float epsilon = 0.7; @@ -90,6 +95,10 @@ void main() { position = viewportToClipspace(viewportOffsetPosition, u_dimensions); gl_Position = vec4(position, 0, 1); + + #ifdef HAS_DEPTH + gl_Position.z = a_depth / a_maxDepth; + #endif ${ arrowHead diff --git a/packages/node-border/src/factory.ts b/packages/node-border/src/factory.ts index 60a198b72..ff795eca9 100644 --- a/packages/node-border/src/factory.ts +++ b/packages/node-border/src/factory.ts @@ -40,12 +40,12 @@ export default function getNodeBorderProgram< "u_correctionRatio", "u_matrix", ...borders.flatMap(({ color }, i) => ("value" in color ? [`u_borderColor_${i + 1}`] : [])), - ...(this.hasDepth ? ["u_maxZIndex"] : []), + ...(this.hasDepth ? ["a_maxDepth"] : []), ], ATTRIBUTES: [ { name: "a_position", size: 2, type: FLOAT }, { name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true }, - ...(this.hasDepth ? [{ name: "a_zIndex", size: 1, type: FLOAT }] : []), + ...(this.hasDepth ? [{ name: "a_depth", size: 1, type: FLOAT }] : []), { name: "a_size", size: 1, type: FLOAT }, ...borders.flatMap(({ color }, i) => "attribute" in color @@ -95,7 +95,7 @@ export default function getNodeBorderProgram< } }); - if (this.hasDepth) gl.uniform1f(uniformLocations.u_maxZIndex, params.maxNodesDepth); + if (this.hasDepth) gl.uniform1f(uniformLocations.a_maxDepth, params.maxNodesDepth); } }; } diff --git a/packages/node-border/src/shader-vert.ts b/packages/node-border/src/shader-vert.ts index 88f68e4d2..852c9d519 100644 --- a/packages/node-border/src/shader-vert.ts +++ b/packages/node-border/src/shader-vert.ts @@ -31,8 +31,8 @@ ${borders #endif #ifdef HAS_DEPTH -attribute float a_zIndex; -uniform float u_maxZIndex; +attribute float a_depth; +uniform float a_maxDepth; #endif const float bias = 255.0 / 254.0; @@ -52,7 +52,7 @@ void main() { v_diffVector = diffVector; #ifdef HAS_DEPTH - gl_Position.z = a_zIndex / u_maxZIndex; + gl_Position.z = a_depth / a_maxDepth; #endif #ifdef PICKING_MODE diff --git a/packages/node-image/src/factory.ts b/packages/node-image/src/factory.ts index ebde2ef72..3be9fbe69 100644 --- a/packages/node-image/src/factory.ts +++ b/packages/node-image/src/factory.ts @@ -112,14 +112,14 @@ export default function getNodeImageProgram< "u_colorizeImages", "u_keepWithinCircle", "u_atlas", - ...(this.hasDepth ? ["u_maxZIndex"] : []), + ...(this.hasDepth ? ["a_maxDepth"] : []), ], 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 }, - ...(this.hasDepth ? [{ name: "a_zIndex", size: 1, type: FLOAT }] : []), + ...(this.hasDepth ? [{ name: "a_depth", size: 1, type: FLOAT }] : []), { name: "a_texture", size: 4, type: FLOAT }, { name: "a_textureIndex", size: 1, type: FLOAT }, ], @@ -278,7 +278,7 @@ export default function getNodeImageProgram< gl.uniform1i(u_colorizeImages, drawingMode === "color" ? 1 : 0); gl.uniform1i(u_keepWithinCircle, keepWithinCircle ? 1 : 0); - if (this.hasDepth) gl.uniform1f(uniformLocations.u_maxZIndex, params.maxNodesDepth); + if (this.hasDepth) gl.uniform1f(uniformLocations.a_maxDepth, params.maxNodesDepth); } }; } diff --git a/packages/node-image/src/shader-vert.ts b/packages/node-image/src/shader-vert.ts index e929dbf14..312fad8a8 100644 --- a/packages/node-image/src/shader-vert.ts +++ b/packages/node-image/src/shader-vert.ts @@ -19,8 +19,8 @@ varying vec4 v_texture; varying float v_textureIndex; #ifdef HAS_DEPTH -attribute float a_zIndex; -uniform float u_maxZIndex; +attribute float a_depth; +uniform float a_maxDepth; #endif const float bias = 255.0 / 254.0; @@ -40,7 +40,7 @@ void main() { v_radius = size / 2.0 / marginRatio; #ifdef HAS_DEPTH - gl_Position.z = a_zIndex / u_maxZIndex; + gl_Position.z = a_depth / a_maxDepth; #endif #ifdef PICKING_MODE diff --git a/packages/node-piechart/src/factory.ts b/packages/node-piechart/src/factory.ts index 7113b453e..05a513023 100644 --- a/packages/node-piechart/src/factory.ts +++ b/packages/node-piechart/src/factory.ts @@ -41,14 +41,14 @@ export default function getNodePiechartProgram< "u_cameraAngle", "u_matrix", "u_defaultColor", - ...(this.hasDepth ? ["u_maxZIndex"] : []), + ...(this.hasDepth ? ["a_maxDepth"] : []), ...("value" in offset ? ["u_offset"] : []), ...slices.flatMap(({ color }, i) => ("value" in color ? [`u_sliceColor_${i + 1}`] : [])), ], ATTRIBUTES: [ { name: "a_position", size: 2, type: FLOAT }, { name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true }, - ...(this.hasDepth ? [{ name: "a_zIndex", size: 1, type: FLOAT }] : []), + ...(this.hasDepth ? [{ name: "a_depth", size: 1, type: FLOAT }] : []), { name: "a_size", size: 1, type: FLOAT }, ...("attribute" in offset ? [{ name: "a_offset", size: 1, type: FLOAT }] : []), ...slices.flatMap(({ color }, i) => @@ -97,7 +97,7 @@ export default function getNodePiechartProgram< gl.uniform1f(u_cameraAngle, params.cameraAngle); gl.uniformMatrix3fv(u_matrix, false, params.matrix); - if (this.hasDepth) gl.uniform1f(uniformLocations.u_maxZIndex, params.maxNodesDepth); + if (this.hasDepth) gl.uniform1f(uniformLocations.a_maxDepth, params.maxNodesDepth); if ("value" in offset) gl.uniform1f(uniformLocations.u_offset, offset.value); const [r, g, b, a] = colorToArray(options.defaultColor || DEFAULT_COLOR); diff --git a/packages/node-piechart/src/shader-vert.ts b/packages/node-piechart/src/shader-vert.ts index e17d6cfa9..392244ac5 100644 --- a/packages/node-piechart/src/shader-vert.ts +++ b/packages/node-piechart/src/shader-vert.ts @@ -34,8 +34,8 @@ ${slices #endif #ifdef HAS_DEPTH -attribute float a_zIndex; -uniform float u_maxZIndex; +attribute float a_depth; +uniform float a_maxDepth; #endif const vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0); @@ -55,7 +55,7 @@ void main() { ${"attribute" in offset ? "v_offset = a_offset;\n" : ""} #ifdef HAS_DEPTH - gl_Position.z = a_zIndex / u_maxZIndex; + gl_Position.z = a_depth / a_maxDepth; #endif #ifdef PICKING_MODE diff --git a/packages/sigma/src/rendering/edge.ts b/packages/sigma/src/rendering/edge.ts index 9f2dbd4d8..840e1e84a 100644 --- a/packages/sigma/src/rendering/edge.ts +++ b/packages/sigma/src/rendering/edge.ts @@ -63,7 +63,7 @@ export abstract class EdgeProgram< } abstract processVisibleItem( - edgeIndex: number, + edgeId: number, startIndex: number, sourceData: NodeDisplayData, targetData: NodeDisplayData, @@ -147,7 +147,10 @@ export function createEdgeCompoundProgram< targetData: NodeDisplayData, data: EdgeDisplayData, ): void { - this.programs.forEach((program) => program.process(edgeIndex, offset, sourceData, targetData, data)); + const l = this.programs.length; + this.programs.forEach((program, i) => + program.process(edgeIndex, offset, sourceData, targetData, { ...data, depth: data.depth + 1 - i / l }), + ); } render(params: RenderParams): void { diff --git a/packages/sigma/src/rendering/programs/edge-arrow-head/index.ts b/packages/sigma/src/rendering/programs/edge-arrow-head/index.ts index 81315c075..4492c2230 100644 --- a/packages/sigma/src/rendering/programs/edge-arrow-head/index.ts +++ b/packages/sigma/src/rendering/programs/edge-arrow-head/index.ts @@ -9,15 +9,6 @@ import VERTEX_SHADER_SOURCE from "./vert.glsl"; const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext; -const UNIFORMS = [ - "u_matrix", - "u_sizeRatio", - "u_correctionRatio", - "u_minEdgeThickness", - "u_lengthToThicknessRatio", - "u_widenessToThicknessRatio", -] as const; - export type CreateEdgeArrowHeadProgramOptions = { lengthToThicknessRatio: number; widenessToThicknessRatio: number; @@ -42,20 +33,29 @@ export function createEdgeArrowHeadProgram< N extends Attributes = Attributes, E extends Attributes = Attributes, G extends Attributes = Attributes, - > extends EdgeProgram<(typeof UNIFORMS)[number], N, E, G> { + > extends EdgeProgram { getDefinition() { return { VERTICES: 3, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE, METHOD: WebGLRenderingContext.TRIANGLES, - UNIFORMS, + UNIFORMS: [ + "u_matrix", + "u_sizeRatio", + "u_correctionRatio", + "u_minEdgeThickness", + "u_lengthToThicknessRatio", + "u_widenessToThicknessRatio", + ...(this.hasDepth ? ["a_maxDepth"] : []), + ], ATTRIBUTES: [ { name: "a_position", size: 2, type: FLOAT }, { name: "a_normal", size: 2, type: FLOAT }, { name: "a_radius", size: 1, type: FLOAT }, { name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true }, { name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true }, + ...(this.hasDepth ? [{ name: "a_depth", size: 1, type: FLOAT }] : []), ], CONSTANT_ATTRIBUTES: [{ name: "a_barycentric", size: 3, type: FLOAT }], CONSTANT_DATA: [ @@ -105,6 +105,9 @@ export function createEdgeArrowHeadProgram< array[startIndex++] = radius; array[startIndex++] = color; array[startIndex++] = edgeIndex; + if (this.hasDepth) { + array[startIndex++] = data.depth; + } } setUniforms(params: RenderParams, { gl, uniformLocations }: ProgramInfo): void { @@ -123,6 +126,8 @@ export function createEdgeArrowHeadProgram< gl.uniform1f(u_minEdgeThickness, params.minEdgeThickness); gl.uniform1f(u_lengthToThicknessRatio, options.lengthToThicknessRatio); gl.uniform1f(u_widenessToThicknessRatio, options.widenessToThicknessRatio); + + if (this.hasDepth) gl.uniform1f(uniformLocations.a_maxDepth, params.maxEdgesDepth); } }; } diff --git a/packages/sigma/src/rendering/programs/edge-arrow-head/vert.glsl.ts b/packages/sigma/src/rendering/programs/edge-arrow-head/vert.glsl.ts index daf99816e..17da66aed 100644 --- a/packages/sigma/src/rendering/programs/edge-arrow-head/vert.glsl.ts +++ b/packages/sigma/src/rendering/programs/edge-arrow-head/vert.glsl.ts @@ -5,6 +5,10 @@ attribute vec2 a_normal; attribute float a_radius; attribute vec3 a_barycentric; +#ifdef HAS_DEPTH +attribute float a_depth; +#endif + #ifdef PICKING_MODE attribute vec4 a_id; #else @@ -55,6 +59,10 @@ void main() { gl_Position = vec4(position, 0, 1); + #ifdef HAS_DEPTH + gl_Position.z = a_depth; + #endif + #ifdef PICKING_MODE // For picking mode, we use the ID as the color: v_color = a_id; diff --git a/packages/sigma/src/rendering/programs/edge-clamped/index.ts b/packages/sigma/src/rendering/programs/edge-clamped/index.ts index f4b1b1f09..39b0f4469 100644 --- a/packages/sigma/src/rendering/programs/edge-clamped/index.ts +++ b/packages/sigma/src/rendering/programs/edge-clamped/index.ts @@ -10,17 +10,6 @@ import VERTEX_SHADER_SOURCE from "./vert.glsl"; const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext; -const UNIFORMS = [ - "u_matrix", - "u_zoomRatio", - "u_sizeRatio", - "u_correctionRatio", - "u_pixelRatio", - "u_feather", - "u_minEdgeThickness", - "u_lengthToThicknessRatio", -] as const; - export type CreateEdgeClampedProgramOptions = Pick; export const DEFAULT_EDGE_CLAMPED_PROGRAM_OPTIONS: CreateEdgeClampedProgramOptions = { @@ -41,14 +30,24 @@ export function createEdgeClampedProgram< N extends Attributes = Attributes, E extends Attributes = Attributes, G extends Attributes = Attributes, - > extends EdgeProgram<(typeof UNIFORMS)[number], N, E, G> { + > extends EdgeProgram { getDefinition() { return { VERTICES: 6, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE, METHOD: WebGLRenderingContext.TRIANGLES, - UNIFORMS, + UNIFORMS: [ + "u_matrix", + "u_zoomRatio", + "u_sizeRatio", + "u_correctionRatio", + "u_pixelRatio", + "u_feather", + "u_minEdgeThickness", + "u_lengthToThicknessRatio", + ...(this.hasDepth ? ["a_maxDepth"] : []), + ], ATTRIBUTES: [ { name: "a_positionStart", size: 2, type: FLOAT }, { name: "a_positionEnd", size: 2, type: FLOAT }, @@ -56,6 +55,7 @@ export function createEdgeClampedProgram< { name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true }, { name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true }, { name: "a_radius", size: 1, type: FLOAT }, + ...(this.hasDepth ? [{ name: "a_depth", size: 1, type: FLOAT }] : []), ], CONSTANT_ATTRIBUTES: [ // If 0, then position will be a_positionStart @@ -117,6 +117,9 @@ export function createEdgeClampedProgram< array[startIndex++] = color; array[startIndex++] = edgeIndex; array[startIndex++] = radius; + if (this.hasDepth) { + array[startIndex++] = data.depth; + } } setUniforms(params: RenderParams, { gl, uniformLocations }: ProgramInfo): void { @@ -139,6 +142,8 @@ export function createEdgeClampedProgram< gl.uniform1f(u_feather, params.antiAliasingFeather); gl.uniform1f(u_minEdgeThickness, params.minEdgeThickness); gl.uniform1f(u_lengthToThicknessRatio, options.lengthToThicknessRatio); + + if (this.hasDepth) gl.uniform1f(uniformLocations.a_maxDepth, params.maxEdgesDepth); } }; } diff --git a/packages/sigma/src/rendering/programs/edge-clamped/vert.glsl.ts b/packages/sigma/src/rendering/programs/edge-clamped/vert.glsl.ts index b19fe19ad..395a70f2b 100644 --- a/packages/sigma/src/rendering/programs/edge-clamped/vert.glsl.ts +++ b/packages/sigma/src/rendering/programs/edge-clamped/vert.glsl.ts @@ -24,6 +24,11 @@ varying vec2 v_normal; varying float v_thickness; varying float v_feather; +#ifdef HAS_DEPTH +attribute float a_depth; +uniform float a_maxDepth; +#endif + const float bias = 255.0 / 254.0; void main() { @@ -57,6 +62,10 @@ void main() { v_feather = u_feather * u_correctionRatio / u_zoomRatio / u_pixelRatio * 2.0; + #ifdef HAS_DEPTH + gl_Position.z = a_depth / a_maxDepth; + #endif + #ifdef PICKING_MODE // For picking mode, we use the ID as the color: v_color = a_id; diff --git a/packages/sigma/src/rendering/programs/edge-line/index.ts b/packages/sigma/src/rendering/programs/edge-line/index.ts index 4705ab5f5..fe43224b8 100644 --- a/packages/sigma/src/rendering/programs/edge-line/index.ts +++ b/packages/sigma/src/rendering/programs/edge-line/index.ts @@ -17,24 +17,23 @@ import VERTEX_SHADER_SOURCE from "./vert.glsl"; const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext; -const UNIFORMS = ["u_matrix"] as const; - export default class EdgeLineProgram< N extends Attributes = Attributes, E extends Attributes = Attributes, G extends Attributes = Attributes, -> extends EdgeProgram<(typeof UNIFORMS)[number], N, E, G> { +> extends EdgeProgram { getDefinition() { return { VERTICES: 2, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE, METHOD: WebGLRenderingContext.LINES, - UNIFORMS, + UNIFORMS: ["u_matrix", ...(this.hasDepth ? ["a_maxDepth"] : [])], ATTRIBUTES: [ { name: "a_position", size: 2, type: FLOAT }, { name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true }, { name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true }, + ...(this.hasDepth ? [{ name: "a_depth", size: 1, type: FLOAT }] : []), ], }; } @@ -59,17 +58,25 @@ export default class EdgeLineProgram< array[startIndex++] = y1; array[startIndex++] = color; array[startIndex++] = edgeIndex; + if (this.hasDepth) { + array[startIndex++] = data.depth; + } // Second point array[startIndex++] = x2; array[startIndex++] = y2; array[startIndex++] = color; array[startIndex++] = edgeIndex; + if (this.hasDepth) { + array[startIndex++] = data.depth; + } } setUniforms(params: RenderParams, { gl, uniformLocations }: ProgramInfo): void { const { u_matrix } = uniformLocations; gl.uniformMatrix3fv(u_matrix, false, params.matrix); + + if (this.hasDepth) gl.uniform1f(uniformLocations.a_maxDepth, params.maxEdgesDepth); } } diff --git a/packages/sigma/src/rendering/programs/edge-line/vert.glsl.ts b/packages/sigma/src/rendering/programs/edge-line/vert.glsl.ts index 94fac1341..c0b4bfbad 100644 --- a/packages/sigma/src/rendering/programs/edge-line/vert.glsl.ts +++ b/packages/sigma/src/rendering/programs/edge-line/vert.glsl.ts @@ -8,6 +8,11 @@ uniform mat3 u_matrix; varying vec4 v_color; +#ifdef HAS_DEPTH +attribute float a_depth; +uniform float a_maxDepth; +#endif + const float bias = 255.0 / 254.0; void main() { @@ -18,6 +23,10 @@ void main() { 1 ); + #ifdef HAS_DEPTH + gl_Position.z = a_depth / a_maxDepth; + #endif + #ifdef PICKING_MODE // For picking mode, we use the ID as the color: v_color = a_id; diff --git a/packages/sigma/src/rendering/programs/edge-rectangle/frag.glsl.ts b/packages/sigma/src/rendering/programs/edge-rectangle/frag.glsl.ts index feb8d7bfb..56b68bef7 100644 --- a/packages/sigma/src/rendering/programs/edge-rectangle/frag.glsl.ts +++ b/packages/sigma/src/rendering/programs/edge-rectangle/frag.glsl.ts @@ -22,6 +22,10 @@ void main(void) { dist ); + #ifdef HAS_DEPTH + if (t >= 1.0) { discard; } + #endif + gl_FragColor = mix(v_color, transparent, t); #endif } diff --git a/packages/sigma/src/rendering/programs/edge-rectangle/index.ts b/packages/sigma/src/rendering/programs/edge-rectangle/index.ts index d8792fdf3..616c26b38 100644 --- a/packages/sigma/src/rendering/programs/edge-rectangle/index.ts +++ b/packages/sigma/src/rendering/programs/edge-rectangle/index.ts @@ -26,34 +26,34 @@ import VERTEX_SHADER_SOURCE from "./vert.glsl"; const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext; -const UNIFORMS = [ - "u_matrix", - "u_zoomRatio", - "u_sizeRatio", - "u_correctionRatio", - "u_pixelRatio", - "u_feather", - "u_minEdgeThickness", -] as const; - export default class EdgeRectangleProgram< N extends Attributes = Attributes, E extends Attributes = Attributes, G extends Attributes = Attributes, -> extends EdgeProgram<(typeof UNIFORMS)[number], N, E, G> { +> extends EdgeProgram { getDefinition() { return { VERTICES: 6, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE, METHOD: WebGLRenderingContext.TRIANGLES, - UNIFORMS, + UNIFORMS: [ + "u_matrix", + "u_zoomRatio", + "u_sizeRatio", + "u_correctionRatio", + "u_pixelRatio", + "u_feather", + "u_minEdgeThickness", + ...(this.hasDepth ? ["a_maxDepth"] : []), + ], ATTRIBUTES: [ { name: "a_positionStart", size: 2, type: FLOAT }, { name: "a_positionEnd", size: 2, type: FLOAT }, { name: "a_normal", size: 2, type: FLOAT }, { name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true }, { name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true }, + ...(this.hasDepth ? [{ name: "a_depth", size: 1, type: FLOAT }] : []), ], CONSTANT_ATTRIBUTES: [ // If 0, then position will be a_positionStart @@ -111,6 +111,9 @@ export default class EdgeRectangleProgram< array[startIndex++] = n2; array[startIndex++] = color; array[startIndex++] = edgeIndex; + if (this.hasDepth) { + array[startIndex++] = data.depth; + } } setUniforms(params: RenderParams, { gl, uniformLocations }: ProgramInfo): void { @@ -124,5 +127,7 @@ export default class EdgeRectangleProgram< gl.uniform1f(u_pixelRatio, params.pixelRatio); gl.uniform1f(u_feather, params.antiAliasingFeather); gl.uniform1f(u_minEdgeThickness, params.minEdgeThickness); + + if (this.hasDepth) gl.uniform1f(uniformLocations.a_maxDepth, params.maxEdgesDepth); } } diff --git a/packages/sigma/src/rendering/programs/edge-rectangle/vert.glsl.ts b/packages/sigma/src/rendering/programs/edge-rectangle/vert.glsl.ts index 64af81f80..82edd3d09 100644 --- a/packages/sigma/src/rendering/programs/edge-rectangle/vert.glsl.ts +++ b/packages/sigma/src/rendering/programs/edge-rectangle/vert.glsl.ts @@ -21,6 +21,11 @@ varying vec2 v_normal; varying float v_thickness; varying float v_feather; +#ifdef HAS_DEPTH +attribute float a_depth; +uniform float a_maxDepth; +#endif + const float bias = 255.0 / 254.0; void main() { @@ -54,6 +59,10 @@ void main() { v_feather = u_feather * u_correctionRatio / u_zoomRatio / u_pixelRatio * 2.0; + #ifdef HAS_DEPTH + gl_Position.z = a_depth / a_maxDepth; + #endif + #ifdef PICKING_MODE // For picking mode, we use the ID as the color: v_color = a_id; diff --git a/packages/sigma/src/rendering/programs/edge-triangle/index.ts b/packages/sigma/src/rendering/programs/edge-triangle/index.ts index 660fdb828..e0c8eeb35 100644 --- a/packages/sigma/src/rendering/programs/edge-triangle/index.ts +++ b/packages/sigma/src/rendering/programs/edge-triangle/index.ts @@ -16,26 +16,31 @@ import VERTEX_SHADER_SOURCE from "./vert.glsl"; const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext; -const UNIFORMS = ["u_matrix", "u_sizeRatio", "u_correctionRatio", "u_minEdgeThickness"] as const; - export default class EdgeTriangleProgram< N extends Attributes = Attributes, E extends Attributes = Attributes, G extends Attributes = Attributes, -> extends EdgeProgram<(typeof UNIFORMS)[number], N, E, G> { +> extends EdgeProgram { getDefinition() { return { VERTICES: 3, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE, METHOD: WebGLRenderingContext.TRIANGLES, - UNIFORMS, + UNIFORMS: [ + "u_matrix", + "u_sizeRatio", + "u_correctionRatio", + "u_minEdgeThickness", + ...(this.hasDepth ? ["a_maxDepth"] : []), + ], ATTRIBUTES: [ { name: "a_positionStart", size: 2, type: FLOAT }, { name: "a_positionEnd", size: 2, type: FLOAT }, { name: "a_normal", size: 2, type: FLOAT }, { name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true }, { name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true }, + ...(this.hasDepth ? [{ name: "a_depth", size: 1, type: FLOAT }] : []), ], CONSTANT_ATTRIBUTES: [ // If 0, then position will be a_positionStart @@ -82,7 +87,6 @@ export default class EdgeTriangleProgram< const array = this.array; - // First point array[startIndex++] = x1; array[startIndex++] = y1; array[startIndex++] = x2; @@ -91,6 +95,9 @@ export default class EdgeTriangleProgram< array[startIndex++] = n2; array[startIndex++] = color; array[startIndex++] = edgeIndex; + if (this.hasDepth) { + array[startIndex++] = data.depth; + } } setUniforms(params: RenderParams, { gl, uniformLocations }: ProgramInfo): void { @@ -100,5 +107,7 @@ export default class EdgeTriangleProgram< gl.uniform1f(u_sizeRatio, params.sizeRatio); gl.uniform1f(u_correctionRatio, params.correctionRatio); gl.uniform1f(u_minEdgeThickness, params.minEdgeThickness); + + if (this.hasDepth) gl.uniform1f(uniformLocations.a_maxDepth, params.maxEdgesDepth); } } diff --git a/packages/sigma/src/rendering/programs/edge-triangle/vert.glsl.ts b/packages/sigma/src/rendering/programs/edge-triangle/vert.glsl.ts index 16acca6c7..530de6c09 100644 --- a/packages/sigma/src/rendering/programs/edge-triangle/vert.glsl.ts +++ b/packages/sigma/src/rendering/programs/edge-triangle/vert.glsl.ts @@ -14,6 +14,11 @@ uniform float u_correctionRatio; varying vec4 v_color; +#ifdef HAS_DEPTH +attribute float a_depth; +uniform float a_maxDepth; +#endif + const float minThickness = 1.7; const float bias = 255.0 / 254.0; @@ -32,6 +37,10 @@ void main() { gl_Position = vec4((u_matrix * vec3(position + unitNormal * webGLThickness, 1)).xy, 0, 1); + #ifdef HAS_DEPTH + gl_Position.z = a_depth / a_maxDepth; + #endif + #ifdef PICKING_MODE // For picking mode, we use the ID as the color: v_color = a_id; diff --git a/packages/sigma/src/rendering/programs/node-circle/index.ts b/packages/sigma/src/rendering/programs/node-circle/index.ts index 38a179333..76e9a7ec1 100644 --- a/packages/sigma/src/rendering/programs/node-circle/index.ts +++ b/packages/sigma/src/rendering/programs/node-circle/index.ts @@ -34,13 +34,13 @@ export default class NodeCircleProgram< VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE, METHOD: WebGLRenderingContext.TRIANGLES, - UNIFORMS: ["u_sizeRatio", "u_correctionRatio", "u_matrix", ...(this.hasDepth ? ["u_maxZIndex"] : [])], + UNIFORMS: ["u_sizeRatio", "u_correctionRatio", "u_matrix", ...(this.hasDepth ? ["a_maxDepth"] : [])], 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 }, - ...(this.hasDepth ? [{ name: "a_zIndex", size: 1, type: FLOAT }] : []), + ...(this.hasDepth ? [{ name: "a_depth", size: 1, type: FLOAT }] : []), ], CONSTANT_ATTRIBUTES: [{ name: "a_angle", size: 1, type: FLOAT }], CONSTANT_DATA: [[NodeCircleProgram.ANGLE_1], [NodeCircleProgram.ANGLE_2], [NodeCircleProgram.ANGLE_3]], @@ -68,6 +68,6 @@ export default class NodeCircleProgram< gl.uniform1f(u_sizeRatio, params.sizeRatio); gl.uniformMatrix3fv(u_matrix, false, params.matrix); - if (this.hasDepth) gl.uniform1f(uniformLocations.u_maxZIndex, params.maxNodesDepth); + if (this.hasDepth) gl.uniform1f(uniformLocations.a_maxDepth, params.maxNodesDepth); } } diff --git a/packages/sigma/src/rendering/programs/node-circle/vert.glsl.ts b/packages/sigma/src/rendering/programs/node-circle/vert.glsl.ts index 4fd8df503..45c9495ee 100644 --- a/packages/sigma/src/rendering/programs/node-circle/vert.glsl.ts +++ b/packages/sigma/src/rendering/programs/node-circle/vert.glsl.ts @@ -6,10 +6,6 @@ attribute vec2 a_position; attribute float a_size; attribute float a_angle; -#ifdef HAS_DEPTH -attribute float a_zIndex; -#endif - uniform mat3 u_matrix; uniform float u_sizeRatio; uniform float u_correctionRatio; @@ -19,6 +15,11 @@ varying vec2 v_diffVector; varying float v_radius; varying float v_border; +#ifdef HAS_DEPTH +attribute float a_depth; +uniform float a_maxDepth; +#endif + const float bias = 255.0 / 254.0; void main() { @@ -35,7 +36,7 @@ void main() { v_radius = size / 2.0; #ifdef HAS_DEPTH - gl_Position.z = a_zIndex; + gl_Position.z = a_depth / a_maxDepth; #endif #ifdef PICKING_MODE diff --git a/packages/sigma/src/rendering/programs/node-point/index.ts b/packages/sigma/src/rendering/programs/node-point/index.ts index 2a8ee231c..2b9d2a965 100644 --- a/packages/sigma/src/rendering/programs/node-point/index.ts +++ b/packages/sigma/src/rendering/programs/node-point/index.ts @@ -29,13 +29,13 @@ export default class NodePointProgram< VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE, METHOD: WebGLRenderingContext.POINTS, - UNIFORMS: ["u_sizeRatio", "u_pixelRatio", "u_matrix", ...(this.hasDepth ? ["u_maxZIndex"] : [])], + UNIFORMS: ["u_sizeRatio", "u_pixelRatio", "u_matrix", ...(this.hasDepth ? ["a_maxDepth"] : [])], 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 }, - ...(this.hasDepth ? [{ name: "a_zIndex", size: 1, type: FLOAT }] : []), + ...(this.hasDepth ? [{ name: "a_depth", size: 1, type: FLOAT }] : []), ], }; } @@ -63,6 +63,6 @@ export default class NodePointProgram< gl.uniform1f(u_sizeRatio, sizeRatio); gl.uniformMatrix3fv(u_matrix, false, matrix); - if (this.hasDepth) gl.uniform1f(uniformLocations.u_maxZIndex, maxNodesDepth); + if (this.hasDepth) gl.uniform1f(uniformLocations.a_maxDepth, maxNodesDepth); } } diff --git a/packages/sigma/src/rendering/programs/node-point/vert.glsl.ts b/packages/sigma/src/rendering/programs/node-point/vert.glsl.ts index 8df274b3d..374825be4 100644 --- a/packages/sigma/src/rendering/programs/node-point/vert.glsl.ts +++ b/packages/sigma/src/rendering/programs/node-point/vert.glsl.ts @@ -5,10 +5,6 @@ attribute vec4 a_color; attribute vec2 a_position; attribute float a_size; -#ifdef HAS_DEPTH -attribute float a_zIndex; -#endif - uniform float u_sizeRatio; uniform float u_pixelRatio; uniform mat3 u_matrix; @@ -16,6 +12,11 @@ uniform mat3 u_matrix; varying vec4 v_color; varying float v_border; +#ifdef HAS_DEPTH +attribute float a_depth; +uniform float a_maxDepth; +#endif + const float bias = 255.0 / 254.0; void main() { @@ -33,7 +34,7 @@ void main() { v_border = (0.5 / a_size) * u_sizeRatio; #ifdef HAS_DEPTH - gl_Position.z = a_zIndex; + gl_Position.z = a_depth / a_maxDepth; #endif #ifdef PICKING_MODE diff --git a/packages/sigma/src/sigma.ts b/packages/sigma/src/sigma.ts index ba6a5feb1..d0873b09d 100644 --- a/packages/sigma/src/sigma.ts +++ b/packages/sigma/src/sigma.ts @@ -1455,8 +1455,8 @@ export default class Sigma< downSizingRatio: this.pickingDownSizingRatio, minEdgeThickness: this.settings.minEdgeThickness, antiAliasingFeather: this.settings.antiAliasingFeather, - maxEdgesDepth: this.graph.size + 1, - maxNodesDepth: this.graph.order + 1, + maxEdgesDepth: this.graph.size, + maxNodesDepth: this.graph.order, }; } @@ -1871,10 +1871,12 @@ export default class Sigma< this.emit("beforeClear"); this.webGLContexts.nodes.bindFramebuffer(WebGLRenderingContext.FRAMEBUFFER, null); - this.webGLContexts.nodes.clear(WebGLRenderingContext.COLOR_BUFFER_BIT); + this.webGLContexts.nodes.clear(WebGLRenderingContext.COLOR_BUFFER_BIT | WebGLRenderingContext.DEPTH_BUFFER_BIT); this.webGLContexts.edges.bindFramebuffer(WebGLRenderingContext.FRAMEBUFFER, null); - this.webGLContexts.edges.clear(WebGLRenderingContext.COLOR_BUFFER_BIT); - this.webGLContexts.hoverNodes.clear(WebGLRenderingContext.COLOR_BUFFER_BIT); + this.webGLContexts.edges.clear(WebGLRenderingContext.COLOR_BUFFER_BIT | WebGLRenderingContext.DEPTH_BUFFER_BIT); + this.webGLContexts.hoverNodes.clear( + WebGLRenderingContext.COLOR_BUFFER_BIT | WebGLRenderingContext.DEPTH_BUFFER_BIT, + ); this.canvasContexts.labels.clearRect(0, 0, this.width, this.height); this.canvasContexts.hovers.clearRect(0, 0, this.width, this.height); this.canvasContexts.edgeLabels.clearRect(0, 0, this.width, this.height);