Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Curvedpath fix #101

Merged
merged 4 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/graph/edges/path/CurvedPath.data.vs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ layout(location=1) in uint aTargetIndex;
layout(location=2) in uvec3 aControl;
layout(location=3) in uint aSourceColor;
layout(location=4) in uint aTargetColor;
layout(location=5) in uvec4 aPickingColor;

uniform sampler2D uGraphPoints;

Expand All @@ -14,8 +15,16 @@ out vec3 vControl;
flat out uint vSourceColor;
flat out uint vTargetColor;
out vec2 vColorMix;

#pragma glslify: valueForIndex = require(../../../renderer/shaders/valueForIndex.glsl)
flat out uvec4 vPickingColor;

// manual import from ../../../renderer/shaders/valueForIndex.glsl
// to avoid uvec4 pragma 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() {
vec4 source = valueForIndex(uGraphPoints, int(aSourceIndex));
Expand All @@ -41,4 +50,6 @@ void main() {
vTargetColor = aTargetColor;

vColorMix = vec2(float(aControl[1]) / float(aControl[2]), float(aControl[1] + 1u) / float(aControl[2]));

vPickingColor = aPickingColor;
}
36 changes: 29 additions & 7 deletions src/graph/edges/path/CurvedPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,18 @@ export interface CurvedPathEdgeData {
control: number | number[];
sourceColor?: GraferInputColor,
targetColor?: GraferInputColor,
pickingColor?: number | [number, number, number, number];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I presume vectors are used quite a bit, so in that case it may be useful to extract this into a type at least the array. i.e type vec4 = { r: number, g: number .... }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vectors are used quite a bit, this vec4/uvec4 is present in a few places in the code, i think if we want to consolidate the types it might be better to do it in a seperate PR so we dont have 4 additional unrelated files in this PR. what do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm fine with that, this was just a thought but yes if we have this throughout the code base we should have a clean up PR

}

const pickingColorNoOpMapping = (): null => null;
Nithos marked this conversation as resolved.
Show resolved Hide resolved
export const kCurvedPathEdgeMappings: DataMappings<CurvedPathEdgeData> = {
id: (entry: CurvedPathEdgeData, i) => 'id' in entry ? entry.id : i,
source: (entry: CurvedPathEdgeData) => entry.source,
target: (entry: CurvedPathEdgeData) => entry.target,
control: (entry: CurvedPathEdgeData) => entry.control,
sourceColor: (entry: CurvedPathEdgeData) => 'sourceColor' in entry ? entry.sourceColor : 0, // first registered color
targetColor: (entry: CurvedPathEdgeData) => 'targetColor' in entry ? entry.targetColor : 0, // first registered color
pickingColor: pickingColorNoOpMapping,
};

export const kCurvedPathEdgeDataTypes: GLDataTypes<CurvedPathEdgeData> = {
Expand All @@ -43,6 +46,7 @@ export const kCurvedPathEdgeDataTypes: GLDataTypes<CurvedPathEdgeData> = {
control: [PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT],
sourceColor: PicoGL.UNSIGNED_INT,
targetColor: PicoGL.UNSIGNED_INT,
pickingColor: [PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT],
Nithos marked this conversation as resolved.
Show resolved Hide resolved
};

export const kGLCurvedPathEdgeTypes = {
Expand All @@ -52,6 +56,7 @@ export const kGLCurvedPathEdgeTypes = {
sourceColor: PicoGL.UNSIGNED_INT,
targetColor: PicoGL.UNSIGNED_INT,
colorMix: [PicoGL.FLOAT, PicoGL.FLOAT],
pickingColor: [PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT],
} as const;
export type GLCurvedPathEdgeTypes = typeof kGLCurvedPathEdgeTypes;

Expand All @@ -62,7 +67,6 @@ export class CurvedPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeTypes>
protected pickingProgram: Program;
protected pickingDrawCall: DrawCall;
protected pickingColors: PickingColors;
protected pickingVBO: VertexBuffer;
protected pickingHandler: MouseCallback;

protected verticesVBO: VertexBuffer;
Expand Down Expand Up @@ -97,15 +101,11 @@ export class CurvedPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeTypes>
);
}

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.verticesVBO = context.createVertexBuffer(PicoGL.FLOAT, 2, new Float32Array(segmentVertices));
this.edgesVAO = context.createVertexArray().vertexAttributeBuffer(0, this.verticesVBO);
this.configureTargetVAO(this.edgesVAO);
this.edgesVAO.instanceAttributeBuffer(7, this.pickingVBO);

const shaders = this.getDrawShaders();
this.program = context.createProgram(shaders.vs, shaders.fs);
Expand All @@ -120,6 +120,9 @@ export class CurvedPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeTypes>
});

// printDataGL(context, this.targetVBO, data.length, kGLCurvedPathEdgeTypes);
this.pickingManager.on(PickingManager.events.hoverOn, this.pickingHandler);
this.pickingManager.on(PickingManager.events.hoverOff, this.pickingHandler);
this.pickingManager.on(PickingManager.events.click, this.pickingHandler);

this.localUniforms.uSegments = segments;
}
Expand All @@ -128,6 +131,25 @@ export class CurvedPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeTypes>
// TODO: Implement destroy method
}

protected ingestData(context: App, data: unknown[], mappings: Partial<DataMappings<CurvedPathEdgeData>>): void {
this.pickingColors = this.pickingManager.allocatePickingColors(data.length);
super.ingestData(context, data, mappings);
}

protected packDataCB(): any {
Nithos marked this conversation as resolved.
Show resolved Hide resolved
return (index, entry): void => {
this.idArray.push(entry.id);

const indexStart = 4 * index;
entry.pickingColor = [
this.pickingColors.colors[indexStart],
this.pickingColors.colors[indexStart + 1],
this.pickingColors.colors[indexStart + 2],
this.pickingColors.colors[indexStart + 3],
];
};
}

public render(context:App, mode: RenderMode, uniforms: RenderUniforms): void {
setDrawCallUniforms(this.drawCall, uniforms);
setDrawCallUniforms(this.drawCall, this.localUniforms);
Expand Down Expand Up @@ -173,7 +195,7 @@ export class CurvedPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeTypes>
protected getDataShader(): DataShader {
return {
vs: dataVS,
varyings: [ 'vSource', 'vTarget', 'vControl', 'vSourceColor', 'vTargetColor', 'vColorMix' ],
varyings: [ 'vSource', 'vTarget', 'vControl', 'vSourceColor', 'vTargetColor', 'vColorMix', 'vPickingColor' ],
};
}

Expand Down
4 changes: 4 additions & 0 deletions src/graph/edges/path/StraightPath.data.vs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ layout(location=1) in uint aTargetIndex;
layout(location=2) in uvec2 aControl;
layout(location=3) in uint aSourceColor;
layout(location=4) in uint aTargetColor;
layout(location=5) in uvec4 aPickingColor;

uniform sampler2D uGraphPoints;

Expand All @@ -13,6 +14,7 @@ flat out uint fTarget;
flat out uint fSourceColor;
flat out uint fTargetColor;
flat out vec2 fColorMix;
flat out uvec4 fPickingColor;

void main() {
fSource = aSourceIndex;
Expand All @@ -22,4 +24,6 @@ void main() {
fTargetColor = aTargetColor;

fColorMix = vec2(float(aControl[0]) / float(aControl[1]), float(aControl[0] + 1u) / float(aControl[1]));

fPickingColor = aPickingColor;
}
10 changes: 10 additions & 0 deletions src/graph/edges/path/StraightPath.picking.fs.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#version 300 es
precision highp float;

flat in vec4 fPickingColor;

out vec4 fragColor;

void main() {
fragColor = fPickingColor;
}
55 changes: 51 additions & 4 deletions src/graph/edges/path/StraightPath.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import edgeVS from './StraightPath.vs.glsl';
import edgeFS from './StraightPath.fs.glsl';
import pickingFS from './StraightPath.picking.fs.glsl';
import dataVS from './StraightPath.data.vs.glsl';

import {CurvedPathEdgeData, GLCurvedPathEdgeTypes, kCurvedPathEdgeMappings} from './CurvedPath';
Expand All @@ -15,14 +16,16 @@ import {DataMappings, DataShader, kDataMappingFlatten} from '../../../data/DataT
import {BasicEdgeData, Edges} from '../Edges';
import {GraferContext} from '../../../renderer/GraferContext';
import {GraphPoints} from '../../../data/GraphPoints';
import {PickingManager} from '../../../UX/picking/PickingManager';
import {PickingColors, PickingEvent, PickingManager} from '../../../UX/picking/PickingManager';
import { MouseCallback } from 'src/UX/mouse/MouseHandler';

export const kStraightPathEdgeDataTypes: GLDataTypes<CurvedPathEdgeData> = {
source: PicoGL.UNSIGNED_INT,
target: PicoGL.UNSIGNED_INT,
control: [PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT],
sourceColor: PicoGL.UNSIGNED_INT,
targetColor: PicoGL.UNSIGNED_INT,
pickingColor: [PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT],
};

export const kGLStraightPathEdgeTypes = {
Expand All @@ -31,13 +34,19 @@ export const kGLStraightPathEdgeTypes = {
sourceColor: PicoGL.UNSIGNED_INT,
targetColor: PicoGL.UNSIGNED_INT,
colorMix: [PicoGL.FLOAT, PicoGL.FLOAT],
pickingColor: [PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT],
} as const;
export type GLStraightPathEdgeTypes = typeof kGLStraightPathEdgeTypes;

export class StraightPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeTypes> {
protected program: Program;
protected drawCall: DrawCall;

protected pickingProgram: Program;
protected pickingDrawCall: DrawCall;
protected pickingColors: PickingColors;
protected pickingHandler: MouseCallback;

protected verticesVBO: VertexBuffer;
protected edgesVAO: VertexArray;

Expand All @@ -57,24 +66,52 @@ export class StraightPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeType
1, 1,
]));

this.pickingHandler = this.handlePickingEvent.bind(this);

this.edgesVAO = context.createVertexArray().vertexAttributeBuffer(0, this.verticesVBO);
this.configureTargetVAO(this.edgesVAO);

const shaders = this.getDrawShaders();
this.program = context.createProgram(shaders.vs, shaders.fs);
this.drawCall = context.createDrawCall(this.program, this.edgesVAO).primitive(PicoGL.TRIANGLE_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, {
uGraphPoints: this.dataTexture,
});

// printDataGL(context, this.targetVBO, data.length, kGLStraightPathEdgeTypes);
this.pickingManager.on(PickingManager.events.hoverOn, this.pickingHandler);
this.pickingManager.on(PickingManager.events.hoverOff, this.pickingHandler);
this.pickingManager.on(PickingManager.events.click, this.pickingHandler);
}

public destroy(): void {
// TODO: Implement destroy method
}

protected ingestData(context: App, data: unknown[], mappings: Partial<DataMappings<CurvedPathEdgeData>>): void {
Nithos marked this conversation as resolved.
Show resolved Hide resolved
this.pickingColors = this.pickingManager.allocatePickingColors(data.length);
super.ingestData(context, data, mappings);
}

protected packDataCB(): any {
return (index, entry): void => {
this.idArray.push(entry.id);

const indexStart = 4 * index;
entry.pickingColor = [
this.pickingColors.colors[indexStart],
this.pickingColors.colors[indexStart + 1],
this.pickingColors.colors[indexStart + 2],
this.pickingColors.colors[indexStart + 3],
];
};
}

public render(context:App, mode: RenderMode, uniforms: RenderUniforms): void {
this.configureRenderContext(context, mode);

Expand All @@ -83,7 +120,10 @@ export class StraightPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeType

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:
Expand All @@ -102,7 +142,7 @@ export class StraightPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeType
protected getPickingShaders(): RenderableShaders {
return {
vs: edgeVS,
fs: null, // pickingFS,
fs: pickingFS,
};
}

Expand All @@ -117,7 +157,7 @@ export class StraightPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeType
protected getDataShader(): DataShader {
return {
vs: dataVS,
varyings: [ 'fSource', 'fTarget', 'fSourceColor', 'fTargetColor', 'fColorMix' ],
varyings: [ 'fSource', 'fTarget', 'fSourceColor', 'fTargetColor', 'fColorMix', 'fPickingColor' ],
};
}

Expand Down Expand Up @@ -156,4 +196,11 @@ export class StraightPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeType

return edgesMappings;
}

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);
}
}
}
18 changes: 16 additions & 2 deletions src/graph/edges/path/StraightPath.vs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,39 @@ layout(location=2) in uint iPointB;
layout(location=3) in uint iColorA;
layout(location=4) in uint iColorB;
layout(location=5) in vec2 iColorMix;
layout(location=6) 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 sampler2D uGraphPoints;
uniform sampler2D uColorPalette;

uniform float uLineWidth;

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 pragma 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.y;
float multB = 1.0 - aVertex.y;

Expand All @@ -42,7 +56,7 @@ void main() {
vec2 direction = normalize(bScreen - aScreen);
vec2 perp = vec2(-direction.y, direction.x);

fLineWidth = uLineWidth * uPixelRatio;
fLineWidth = (uPicking ? uLineWidth * uPickingWidth : uLineWidth) * uPixelRatio;
float offsetWidth = fLineWidth + 0.5;
vec4 position = aProjected * multA + bProjected * multB;
vec4 offset = vec4(((aVertex.x * perp * offsetWidth) / uViewportSize) * position.w, 0.0, 0.0);
Expand Down