From 6084097749d52a299a73146ba5418caf9911c977 Mon Sep 17 00:00:00 2001 From: Manfred Cheung Date: Fri, 15 Sep 2023 14:54:35 -0400 Subject: [PATCH] feat: add option to change behaviour of point classes --- src/data/GraphPoints.ts | 42 ++++++++++++++++++++++++---- src/data/shaders/GraphPoints.fs.glsl | 12 +++++++- src/data/shaders/classMode.glsl | 2 ++ src/grafer/GraferController.ts | 13 ++++++++- src/graph/Graph.ts | 2 +- 5 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 src/data/shaders/classMode.glsl diff --git a/src/data/GraphPoints.ts b/src/data/GraphPoints.ts index 58fd203..e4a1aa4 100755 --- a/src/data/GraphPoints.ts +++ b/src/data/GraphPoints.ts @@ -1,11 +1,21 @@ import PicoGL, {App, Framebuffer, Texture} from 'picogl'; import pointsVS from './shaders/GraphPoints.vs.glsl'; import pointsFS from './shaders/GraphPoints.fs.glsl'; -import {GLDataTypes} from '../renderer/Renderable'; +import {GLDataTypes, setDrawCallUniforms} from '../renderer/Renderable'; import {DataMappings, concatenateData, packData} from './DataTools'; import {vec2, vec3} from 'gl-matrix'; import {DataTexture} from '../renderer/DataTexture'; +export enum ClassModes { + NONE, + ADD, +} + +export interface PointOptions { + positionClassMode?: ClassModes + radiusClassMode?: ClassModes +} + export interface PointData { id?: number | string; class?: number | string; @@ -58,6 +68,10 @@ export class GraphPoints extends DataTexture { private _pointView: DataView; private _pointTexture: Texture; + private _localUniforms = { + uPositionClassMode: ClassModes.ADD, + uRadiusClassMode: ClassModes.NONE, + }; private _dataArrayBuffer: Float32Array; private _length: number = 0; @@ -65,6 +79,20 @@ export class GraphPoints extends DataTexture { return this._length; } + public get positionClassMode(): ClassModes { + return this._localUniforms.uPositionClassMode; + } + public set positionClassMode(value: ClassModes) { + this._localUniforms.uPositionClassMode = value; + } + + public get radiusClassMode(): ClassModes { + return this._localUniforms.uRadiusClassMode; + } + public set radiusClassMode(value: ClassModes) { + this._localUniforms.uRadiusClassMode = value; + } + private map: Map; protected dirty: boolean = false; @@ -288,11 +316,13 @@ export class GraphPoints extends DataTexture { .depthMask(false); // create and initiate draw call - context.createDrawCall(program, pointsVAO) - .primitive(PicoGL.TRIANGLE_STRIP) - .texture('uPointTexture', this._pointTexture) - .texture('uClassTexture', this._classTexture) - .draw(); + const drawCall = context.createDrawCall(program, pointsVAO) + .primitive(PicoGL.TRIANGLE_STRIP); + setDrawCallUniforms(drawCall, Object.assign({}, this._localUniforms, { + uPointTexture: this._pointTexture, + uClassTexture: this._classTexture, + })); + drawCall.draw(); // read points texture into stored buffer for point coordinates readback this.readTextureAsync(this._frameBuffer.colorAttachments[0]).then(texArrayBuffer => { diff --git a/src/data/shaders/GraphPoints.fs.glsl b/src/data/shaders/GraphPoints.fs.glsl index 071f12c..3d65ad9 100644 --- a/src/data/shaders/GraphPoints.fs.glsl +++ b/src/data/shaders/GraphPoints.fs.glsl @@ -9,7 +9,11 @@ out vec4 fragColor; uniform sampler2D uPointTexture; uniform isampler2D uClassTexture; +uniform uint uPositionClassMode; +uniform uint uRadiusClassMode; + #pragma glslify: import(../../renderer/shaders/valueForIndex.glsl) +#pragma glslify: import(./classMode.glsl) void main() { vec2 texSize = vec2(textureSize(uPointTexture, 0).xy); @@ -19,7 +23,13 @@ void main() { int i = 0; int classIndex = texelFetch(uClassTexture, coords, 0).x; while(classIndex != -1 && i++ < 500) { - fragColor += valueForIndex(uPointTexture, classIndex); + vec4 point = valueForIndex(uPointTexture, classIndex); + if(uPositionClassMode == MODE_ADD) { + fragColor.xyz += point.xyz; + } + if(uRadiusClassMode == MODE_ADD) { + fragColor.w += point.w; + } classIndex = ivalueForIndex(uClassTexture, classIndex).x; } } \ No newline at end of file diff --git a/src/data/shaders/classMode.glsl b/src/data/shaders/classMode.glsl new file mode 100644 index 0000000..d54da11 --- /dev/null +++ b/src/data/shaders/classMode.glsl @@ -0,0 +1,2 @@ +#define MODE_NONE 0u +#define MODE_ADD 1u diff --git a/src/grafer/GraferController.ts b/src/grafer/GraferController.ts index c33b255..c692c66 100755 --- a/src/grafer/GraferController.ts +++ b/src/grafer/GraferController.ts @@ -1,5 +1,5 @@ import {Viewport, ViewportOptions} from '../renderer/Viewport'; -import {PointDataMappings} from '../data/GraphPoints'; +import {PointOptions, PointDataMappings} from '../data/GraphPoints'; import {nodes as GraphNodes, edges as GraphEdges, labels as GraphLabels, Graph} from '../graph/mod'; import {Layer} from '../graph/Layer'; import {DragTruck} from '../UX/mouse/drag/DragTruck'; @@ -31,6 +31,7 @@ export type GraferLabelsType = keyof typeof GraphLabels.types; export interface GraferDataInput { data: unknown[], mappings?: Partial, + options?: PointOptions, } export type GraferPointsData = GraferDataInput; @@ -413,6 +414,16 @@ export class GraferController extends EventEmitter { const mappings = Object.assign({}, pointsRadiusMapping, data.points.mappings); this._viewport.graph = new Graph(this._viewport.context, data.points.data, mappings); this._viewport.graph.picking = new PickingManager(this._viewport.context, this._viewport.mouseHandler); + + if ('options' in data.points) { + const options = data.points.options; + const keys = Object.keys(options); + for (const key of keys) { + if (key in this._viewport.graph) { + this._viewport.graph[key] = options[key]; + } + } + } } } diff --git a/src/graph/Graph.ts b/src/graph/Graph.ts index 4737a33..1296fa1 100755 --- a/src/graph/Graph.ts +++ b/src/graph/Graph.ts @@ -2,7 +2,7 @@ import {Renderable, RenderMode, RenderUniforms} from '../renderer/Renderable'; import {App} from 'picogl'; import {mat4, quat, vec3} from 'gl-matrix'; import {Layer} from './Layer'; -import {GraphPoints, PointData, PointDataMappings} from '../data/GraphPoints'; +import {GraphPoints, PointData, PointDataMappings, PointOptions} from '../data/GraphPoints'; import {PickingManager} from '../UX/picking/PickingManager'; import {EventEmitter} from '@dekkai/event-emitter/build/lib/EventEmitter';