From 952b18c08139d0ccef7d4fe5c05e29f34abcd7b0 Mon Sep 17 00:00:00 2001 From: Manfred Cheung Date: Thu, 24 Aug 2023 14:00:25 -0400 Subject: [PATCH] Fix Gravity edge type and add picking (#102) * fix gravity edge type * add picking to gravity edge type --- .../edges/bundle/ClusterBundle.data.vs.glsl | 2 +- src/graph/edges/gravity/Gravity.fs.glsl | 3 +- .../edges/gravity/Gravity.picking.fs.glsl | 10 +++++ src/graph/edges/gravity/Gravity.ts | 45 ++++++++++++++++--- src/graph/edges/gravity/Gravity.vs.glsl | 21 ++++++++- src/graph/edges/path/CurvedPath.data.vs.glsl | 2 +- src/graph/edges/path/StraightPath.vs.glsl | 2 +- 7 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 src/graph/edges/gravity/Gravity.picking.fs.glsl diff --git a/src/graph/edges/bundle/ClusterBundle.data.vs.glsl b/src/graph/edges/bundle/ClusterBundle.data.vs.glsl index 299612f..f6650d2 100755 --- a/src/graph/edges/bundle/ClusterBundle.data.vs.glsl +++ b/src/graph/edges/bundle/ClusterBundle.data.vs.glsl @@ -21,7 +21,7 @@ out vec2 vColorMix; flat out uvec4 vPickingColor; // manual import from ../../../renderer/shaders/valueForIndex.glsl -// to avoid uvec4 pragma error +// to avoid uvec4 glslify error vec4 valueForIndex(sampler2D tex, int index) { int texWidth = textureSize(tex, 0).x; int col = index % texWidth; diff --git a/src/graph/edges/gravity/Gravity.fs.glsl b/src/graph/edges/gravity/Gravity.fs.glsl index 318c3dc..7d5d4a0 100755 --- a/src/graph/edges/gravity/Gravity.fs.glsl +++ b/src/graph/edges/gravity/Gravity.fs.glsl @@ -6,6 +6,7 @@ precision highp float; uniform vec2 uViewportSize; uniform uint uRenderMode; +flat in float fLineWidth; in vec3 vColor; in vec2 vProjectedPosition; in float vProjectedW; @@ -13,5 +14,5 @@ in float vProjectedW; out vec4 fragColor; void main() { - fragColor = lineColor(vColor, vProjectedPosition, vProjectedW, uViewportSize, uRenderMode); + fragColor = lineColor(vColor, vProjectedPosition, vProjectedW, uViewportSize, uRenderMode, fLineWidth); } diff --git a/src/graph/edges/gravity/Gravity.picking.fs.glsl b/src/graph/edges/gravity/Gravity.picking.fs.glsl new file mode 100644 index 0000000..d21d74f --- /dev/null +++ b/src/graph/edges/gravity/Gravity.picking.fs.glsl @@ -0,0 +1,10 @@ +#version 300 es +precision highp float; + +flat in vec4 fPickingColor; + +out vec4 fragColor; + +void main() { + fragColor = fPickingColor; +} diff --git a/src/graph/edges/gravity/Gravity.ts b/src/graph/edges/gravity/Gravity.ts index 2e3f21d..1253f7d 100755 --- a/src/graph/edges/gravity/Gravity.ts +++ b/src/graph/edges/gravity/Gravity.ts @@ -1,12 +1,13 @@ import edgeVS from './Gravity.vs.glsl'; import edgeFS from './Gravity.fs.glsl'; +import pickingFS from './Gravity.picking.fs.glsl'; import dataVS from './Gravity.data.vs.glsl'; import {App, DrawCall, PicoGL, Program, VertexArray, VertexBuffer} from 'picogl'; import {BasicEdgeData, Edges, kBasicEdgeDataTypes} from '../Edges'; import {GraphPoints} from '../../../data/GraphPoints'; import {DataMappings, DataShader} from '../../../data/DataTools'; -import {PickingManager} from '../../../UX/picking/PickingManager'; +import {PickingColors, PickingEvent, PickingManager} from '../../../UX/picking/PickingManager'; import {GLStraightEdgeTypes, kGLStraightEdgeTypes} from '../straight/Straight'; import { GLDataTypes, @@ -15,6 +16,7 @@ import { RenderUniforms, setDrawCallUniforms, } from '../../../renderer/Renderable'; +import {MouseCallback} from '../../../UX/mouse/MouseHandler'; import {GraferContext} from '../../../renderer/GraferContext'; export const kGLGravityEdgeTypes = { @@ -29,6 +31,12 @@ export class Gravity extends Edges { protected program: Program; protected drawCall: DrawCall; + protected pickingProgram: Program; + protected pickingDrawCall: DrawCall; + protected pickingColors: PickingColors; + protected pickingVBO: VertexBuffer; + protected pickingHandler: MouseCallback; + protected verticesVBO: VertexBuffer; protected edgesVAO: VertexArray; @@ -68,15 +76,29 @@ export class Gravity extends Edges { } this.verticesVBO = context.createVertexBuffer(PicoGL.FLOAT, 2, new Float32Array(segmentVertices)); + + this.pickingHandler = this.handlePickingEvent.bind(this); + this.pickingColors = this.pickingManager.allocatePickingColors(data.length); + this.pickingVBO = context.createVertexBuffer(PicoGL.UNSIGNED_BYTE, 4, this.pickingColors.colors); + this.edgesVAO = context.createVertexArray().vertexAttributeBuffer(0, this.verticesVBO); this.configureTargetVAO(this.edgesVAO); + this.edgesVAO.instanceAttributeBuffer(5, this.pickingVBO); const shaders = this.getDrawShaders(); this.program = context.createProgram(shaders.vs, shaders.fs); this.drawCall = context.createDrawCall(this.program, this.edgesVAO).primitive(PicoGL.LINE_STRIP); + const pickingShaders = this.getPickingShaders(); + this.pickingProgram = context.createProgram(pickingShaders.vs, pickingShaders.fs); + this.pickingDrawCall = context.createDrawCall(this.pickingProgram, this.edgesVAO).primitive(PicoGL.TRIANGLE_STRIP); + this.compute(context, {}); + this.pickingManager.on(PickingManager.events.hoverOn, this.pickingHandler); + this.pickingManager.on(PickingManager.events.hoverOff, this.pickingHandler); + this.pickingManager.on(PickingManager.events.click, this.pickingHandler); + // printDataGL(context, this.targetVBO, data.length, kGLStraightEdgeTypes); } @@ -85,19 +107,21 @@ export class Gravity extends Edges { } public render(context:App, mode: RenderMode, uniforms: RenderUniforms): void { - setDrawCallUniforms(this.drawCall, uniforms); - setDrawCallUniforms(this.drawCall, this.localUniforms); - this.configureRenderContext(context, mode); switch (mode) { case RenderMode.PICKING: - // this.pickingDrawCall.draw(); + setDrawCallUniforms(this.pickingDrawCall, uniforms); + setDrawCallUniforms(this.pickingDrawCall, this.localUniforms); + this.pickingDrawCall.uniform('uPicking', true); + this.pickingDrawCall.draw(); break; default: + setDrawCallUniforms(this.drawCall, uniforms); + setDrawCallUniforms(this.drawCall, this.localUniforms); + this.drawCall.uniform('uPicking', false); this.drawCall.draw(); - break; } } @@ -111,7 +135,7 @@ export class Gravity extends Edges { protected getPickingShaders(): RenderableShaders { return { vs: edgeVS, - fs: null, // pickingFS, + fs: pickingFS, }; } @@ -129,4 +153,11 @@ export class Gravity extends Edges { varyings: [ 'fSource', 'fTarget', 'fSourceColor', 'fTargetColor' ], }; } + + protected handlePickingEvent(event: PickingEvent, colorID: number): void { + if (this.picking && this.pickingColors.map.has(colorID)) { + const id = this.idArray[this.pickingColors.map.get(colorID)]; + this.emit(event, id); + } + } } diff --git a/src/graph/edges/gravity/Gravity.vs.glsl b/src/graph/edges/gravity/Gravity.vs.glsl index e26e97b..dcfa0cb 100755 --- a/src/graph/edges/gravity/Gravity.vs.glsl +++ b/src/graph/edges/gravity/Gravity.vs.glsl @@ -5,22 +5,39 @@ layout(location=1) in uint iPointA; layout(location=2) in uint iPointB; layout(location=3) in uint iColorA; layout(location=4) in uint iColorB; +layout(location=5) in uvec4 iPickingColor; + +uniform bool uPicking; uniform mat4 uViewMatrix; uniform mat4 uSceneMatrix; uniform mat4 uProjectionMatrix; uniform vec2 uViewportSize; uniform float uPixelRatio; +uniform float uPickingWidth; +uniform float uLineWidth; uniform float uGravity; uniform sampler2D uColorPalette; +uniform sampler2D uGraphPoints; +flat out float fLineWidth; +flat out vec4 fPickingColor; out vec3 vColor; out vec2 vProjectedPosition; out float vProjectedW; -#pragma glslify: valueForIndex = require(../../../renderer/shaders/valueForIndex.glsl) +// manual import from ../../../renderer/shaders/valueForIndex.glsl +// to avoid uvec4 glslify error +vec4 valueForIndex(sampler2D tex, int index) { + int texWidth = textureSize(tex, 0).x; + int col = index % texWidth; + int row = index / texWidth; + return texelFetch(tex, ivec2(col, row), 0); +} void main() { + fPickingColor = uPicking ? vec4(iPickingColor) / 255.0 : vec4(0.0); + float multA = aVertex.x; float multB = 1.0 - aVertex.x; @@ -39,6 +56,8 @@ void main() { float toCenter = length(middle); vec3 towardsCenter = (middle * -1.0) / toCenter; + fLineWidth = (uPicking ? uLineWidth * uPickingWidth : uLineWidth) * uPixelRatio; + vec3 gravity = middle + towardsCenter * min(toCenter, distance * uGravity); vec3 position = gravity + pow(multB, 2.0) * (offsetB - gravity) + pow(multA, 2.0) * (offsetA - gravity); diff --git a/src/graph/edges/path/CurvedPath.data.vs.glsl b/src/graph/edges/path/CurvedPath.data.vs.glsl index 9a76576..e0d02e7 100755 --- a/src/graph/edges/path/CurvedPath.data.vs.glsl +++ b/src/graph/edges/path/CurvedPath.data.vs.glsl @@ -18,7 +18,7 @@ out vec2 vColorMix; flat out uvec4 vPickingColor; // manual import from ../../../renderer/shaders/valueForIndex.glsl -// to avoid uvec4 pragma error +// to avoid uvec4 glslify error vec4 valueForIndex(sampler2D tex, int index) { int texWidth = textureSize(tex, 0).x; int col = index % texWidth; diff --git a/src/graph/edges/path/StraightPath.vs.glsl b/src/graph/edges/path/StraightPath.vs.glsl index 9a5fc65..8eab6ef 100755 --- a/src/graph/edges/path/StraightPath.vs.glsl +++ b/src/graph/edges/path/StraightPath.vs.glsl @@ -28,7 +28,7 @@ out vec2 vProjectedPosition; out float vProjectedW; // manual import from ../../../renderer/shaders/valueForIndex.glsl -// to avoid uvec4 pragma error +// to avoid uvec4 glslify error vec4 valueForIndex(sampler2D tex, int index) { int texWidth = textureSize(tex, 0).x; int col = index % texWidth;