From db0f50d01147dbbf6d85d190b0a28565e546c99d Mon Sep 17 00:00:00 2001 From: Emanuele Bezzi Date: Wed, 1 Dec 2021 16:49:13 -0500 Subject: [PATCH] Add frontend --- .../components/graph/drawSpatialImageRegl.js | 38 ++++++++++ client/src/components/graph/graph.js | 72 ++++++++++++------- 2 files changed, 86 insertions(+), 24 deletions(-) create mode 100644 client/src/components/graph/drawSpatialImageRegl.js diff --git a/client/src/components/graph/drawSpatialImageRegl.js b/client/src/components/graph/drawSpatialImageRegl.js new file mode 100644 index 00000000..c072dc17 --- /dev/null +++ b/client/src/components/graph/drawSpatialImageRegl.js @@ -0,0 +1,38 @@ +export default function drawSpatialImageRegl(regl) { + return regl({ + frag: ` + precision mediump float; + uniform sampler2D texture; + varying vec2 uv; + void main () { + gl_FragColor = texture2D(texture, uv); + }`, + + vert: ` + precision mediump float; + attribute vec2 position; + varying vec2 uv; + const float zMiddle = 0.; + uniform mat3 projView; + + vec2 norm(vec2 position) { + return ((position - 0.5) * 2.0) * vec2(1., -1.); + } + void main() { + uv = position; + vec3 xy = projView * vec3(norm(position), 1.); + gl_Position = vec4(xy.xy, 0, 1.); + }`, + + attributes: { + position: [-1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1], + }, + + uniforms: { + projView: regl.prop("projView"), + texture: regl.prop("spatialImageAsTexture"), + }, + + count: 6, + }); +} diff --git a/client/src/components/graph/graph.js b/client/src/components/graph/graph.js index 5b16003d..8b936129 100644 --- a/client/src/components/graph/graph.js +++ b/client/src/components/graph/graph.js @@ -14,6 +14,7 @@ import { createColorTable, createColorQuery, } from "../../util/stateManager/colorHelpers"; +import _drawSpatialImage from "./drawSpatialImageRegl"; import * as globals from "../../globals"; import GraphOverlayLayer from "./overlays/graphOverlayLayer"; @@ -87,6 +88,7 @@ class Graph extends React.Component { const camera = _camera(canvas); const regl = _regl(canvas); const drawPoints = _drawPoints(regl); + const drawSpatialImage = _drawSpatialImage(regl); // preallocate webgl buffers const pointBuffer = regl.buffer(); @@ -100,6 +102,7 @@ class Graph extends React.Component { pointBuffer, colorBuffer, flagBuffer, + drawSpatialImage, }; } @@ -232,6 +235,7 @@ class Graph extends React.Component { pointBuffer: null, colorBuffer: null, flagBuffer: null, + drawSpatialImage: null, // component rendering derived state - these must stay synchronized // with the reducer state they were generated from. @@ -317,7 +321,10 @@ class Graph extends React.Component { if (e.type !== "wheel") e.preventDefault(); if (camera.handleEvent(e, projectionTF)) { this.renderCanvas(); - this.setState((state) => ({ ...state, updateOverlay: !state.updateOverlay })); + this.setState((state) => ({ + ...state, + updateOverlay: !state.updateOverlay, + })); } }; @@ -509,6 +516,13 @@ class Graph extends React.Component { return { toolSVG: newToolSVG, tool, container }; }; + loadTextureFromUrl = (src) => new Promise((resolve, reject) => { + const img = new Image(); + img.onload = () => resolve(img); + img.onerror = reject; + img.src = src; + }); + fetchAsyncProps = async (props) => { const { annoMatrix, @@ -551,6 +565,10 @@ class Graph extends React.Component { pointDilationLabel ); + this.spatialImage = await this.loadTextureFromUrl( + "/api/v0.2/spatial/image" + ); + const { width, height } = viewport; return { positions, @@ -721,6 +739,7 @@ class Graph extends React.Component { flagBuffer, camera, projectionTF, + drawSpatialImage, } = this.state; this.renderPoints( regl, @@ -729,7 +748,8 @@ class Graph extends React.Component { pointBuffer, flagBuffer, camera, - projectionTF + projectionTF, + drawSpatialImage ); }); @@ -797,7 +817,8 @@ class Graph extends React.Component { pointBuffer, flagBuffer, camera, - projectionTF + projectionTF, + drawSpatialImage ) { const { annoMatrix } = this.props; if (!this.reglCanvas || !annoMatrix) return; @@ -809,7 +830,7 @@ class Graph extends React.Component { regl.poll(); regl.clear({ depth: 1, - color: [1, 1, 1, 1], + color: [0, 0, 0, 0], }); drawPoints({ distance: camera.distance(), @@ -821,6 +842,12 @@ class Graph extends React.Component { nPoints: schema.dataframe.nObs, minViewportDimension: Math.min(width, height), }); + drawSpatialImage({ + projView, + spatialImageAsTexture: regl.texture({ + data: this.spatialImage, + }), + }); regl._gl.flush(); } @@ -951,32 +978,29 @@ const ErrorLoading = ({ displayName, error, width, height }) => { ); }; -const StillLoading = ({ displayName, width, height }) => +const StillLoading = ({ displayName, width, height }) => ( /* Render a busy/loading indicator */ - ( +
-
-
+
- ) -; - +
+); export default Graph;