@vitessce/gl 3.6.17 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { f as distEs6Exports } from "./index-BDUyhk4k.js";
2
- import { p, o, A, s, r, q, i, j, l, C, m, D, G, e, H, c, M, k, n, d, P, S, h, T, u, b, t, w, v } from "./index-BDUyhk4k.js";
1
+ import { f as distEs6Exports } from "./index-PjbBCu4D.js";
2
+ import { p, o, A, s, r, q, i, j, l, C, m, D, G, e, H, c, M, k, n, d, P, S, h, T, u, b, t, w, v } from "./index-PjbBCu4D.js";
3
3
  const SELECTION_TYPE = distEs6Exports.SELECTION_TYPE;
4
4
  export {
5
5
  p as AXIS_FONT_FAMILY,
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-BDUyhk4k.js";
1
+ import { B as BaseDecoder } from "./index-PjbBCu4D.js";
2
2
  const dctZigZag = new Int32Array([
3
3
  0,
4
4
  1,
@@ -1,5 +1,5 @@
1
1
  import { i as inflate_1 } from "./pako.esm-SxljTded.js";
2
- import { g as getDefaultExportFromCjs, B as BaseDecoder, L as LercParameters, a as LercAddCompression } from "./index-BDUyhk4k.js";
2
+ import { g as getDefaultExportFromCjs, B as BaseDecoder, L as LercParameters, a as LercAddCompression } from "./index-PjbBCu4D.js";
3
3
  var LercDecode = { exports: {} };
4
4
  var hasRequiredLercDecode;
5
5
  function requireLercDecode() {
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-BDUyhk4k.js";
1
+ import { B as BaseDecoder } from "./index-PjbBCu4D.js";
2
2
  const MIN_BITS = 9;
3
3
  const CLEAR_CODE = 256;
4
4
  const EOI_CODE = 257;
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-BDUyhk4k.js";
1
+ import { B as BaseDecoder } from "./index-PjbBCu4D.js";
2
2
  class PackbitsDecoder extends BaseDecoder {
3
3
  decodeBlock(buffer) {
4
4
  const dataView = new DataView(buffer);
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-BDUyhk4k.js";
1
+ import { B as BaseDecoder } from "./index-PjbBCu4D.js";
2
2
  class RawDecoder extends BaseDecoder {
3
3
  decodeBlock(buffer) {
4
4
  return buffer;
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-BDUyhk4k.js";
1
+ import { B as BaseDecoder } from "./index-PjbBCu4D.js";
2
2
  class WebImageDecoder extends BaseDecoder {
3
3
  constructor() {
4
4
  super();
@@ -19,9 +19,6 @@ declare class BitmaskLayer extends BitmaskLayer_base {
19
19
  fs: string;
20
20
  vs: string;
21
21
  modules: any[];
22
- defines: {
23
- COLORMAP_FUNC: any;
24
- };
25
22
  };
26
23
  /**
27
24
  * Override the parent loadChannelTextures to enable
@@ -1 +1 @@
1
- {"version":3,"file":"BitmaskLayerBeta.d.ts","sourceRoot":"","sources":["../src/BitmaskLayerBeta.js"],"names":[],"mappings":";;;;;;;;;;;AAgEA;;;GAGG;AACH;;IAEE;;;;;;;MAYC;IAED;;;;MAIE;IACF,4CA0BC;IAED;;;;aA6CC;IAED,sBAuHC;IAED;;OAEG;IACH,uDAqBC;IAED,8HAuEC;CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sCApXM,gBAAgB"}
1
+ {"version":3,"file":"BitmaskLayerBeta.d.ts","sourceRoot":"","sources":["../src/BitmaskLayerBeta.js"],"names":[],"mappings":";;;;;;;;;;;AAgEA;;;GAGG;AACH;;IAEE;;;;MAMC;IAED;;;;MAIE;IACF,4CA0BC;IAED;;;;aA6CC;IAED,sBA2HC;IAED;;OAEG;IACH,uDAqBC;IAED,8HAuEC;CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sCAlXM,gBAAgB"}
@@ -54,16 +54,10 @@ const defaultProps = {
54
54
  export default class BitmaskLayer extends XRLayer {
55
55
  // eslint-disable-next-line class-methods-use-this
56
56
  getShaders() {
57
- const { colormap } = this.props;
58
57
  return {
59
58
  fs,
60
59
  vs,
61
60
  modules: [project32, picking],
62
- defines: {
63
- [COLORMAP_SHADER_PLACEHOLDER]: GLSL_COLORMAPS.includes(colormap)
64
- ? colormap
65
- : GLSL_COLORMAP_DEFAULT,
66
- },
67
61
  };
68
62
  }
69
63
  /**
@@ -124,10 +118,7 @@ export default class BitmaskLayer extends XRLayer {
124
118
  }
125
119
  draw(opts) {
126
120
  const { uniforms } = opts;
127
- const { channelStrokeWidths, channelsFilled, channelOpacities, channelColors, channelsVisible,
128
- // TODO: use `channelFeatureValueColormaps` in shader,
129
- // figure out how to call multiple GLSL colormap functions
130
- channelFeatureValueColormaps, channelFeatureValueColormapRanges, channelIsStaticColorMode, channelIsSetColorMode, hoveredCell, colorScaleLo, colorScaleHi, isExpressionMode, zoom, minZoom, maxZoom, zoomOffset, // TODO: figure out if this needs to be used or not
121
+ const { channelStrokeWidths, channelsFilled, channelOpacities, channelColors, channelsVisible, channelFeatureValueColormaps, channelFeatureValueColormapRanges, channelIsStaticColorMode, channelIsSetColorMode, hoveredCell, colorScaleLo, colorScaleHi, isExpressionMode, zoom, minZoom, maxZoom, zoomOffset, // TODO: figure out if this needs to be used or not
131
122
  } = this.props;
132
123
  const { textures, model,
133
124
  // Expression and set index (and colors) textures with offsets
@@ -160,6 +151,9 @@ export default class BitmaskLayer extends XRLayer {
160
151
  channelStrokeWidths: padWithDefault(channelStrokeWidths, 1.0,
161
152
  // There are six texture entries on the shaders
162
153
  MAX_CHANNELS - channelStrokeWidths.length),
154
+ channelColormapFuncIndices: padWithDefault(channelFeatureValueColormaps.map(d => GLSL_COLORMAPS.indexOf(d)), 0,
155
+ // There are six texture entries on the shaders
156
+ MAX_CHANNELS - channelFeatureValueColormaps.length),
163
157
  channelColormapRangeStarts: padWithDefault(channelFeatureValueColormapRanges.map(r => r?.[0] || 0.0), 0.0,
164
158
  // There are six texture entries on the shaders
165
159
  MAX_CHANNELS - channelFeatureValueColormapRanges.length),
@@ -1,3 +1,3 @@
1
1
  export const vs: "\n#define SHADER_NAME bitmask-layer-vertex-shader\n\nattribute vec2 texCoords;\nattribute vec3 positions;\nattribute vec3 positions64Low;\nattribute vec3 instancePickingColors;\n\nvarying vec2 vTexCoord;\n\nvoid main(void) {\n geometry.worldPosition = positions;\n geometry.uv = texCoords;\n geometry.pickingColor = instancePickingColors;\n gl_Position = project_position_to_clipspace(positions, positions64Low, vec3(0.0), geometry.position);\n DECKGL_FILTER_GL_POSITION(gl_Position, geometry);\n vTexCoord = texCoords;\n vec4 color = vec4(0.0);\n DECKGL_FILTER_COLOR(color, geometry);\n}\n";
2
- export const fs: "\n#define SHADER_NAME bitmask-layer-fragment-shader\nprecision highp float;\n\n#define GLSLIFY 1\nvec4 plasma (float x_4) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0.050980392156862744,0.03137254901960784,0.5294117647058824,1);\n const float e1 = 0.13;\n const vec4 v1 = vec4(0.29411764705882354,0.011764705882352941,0.6313725490196078,1);\n const float e2 = 0.25;\n const vec4 v2 = vec4(0.49019607843137253,0.011764705882352941,0.6588235294117647,1);\n const float e3 = 0.38;\n const vec4 v3 = vec4(0.6588235294117647,0.13333333333333333,0.5882352941176471,1);\n const float e4 = 0.5;\n const vec4 v4 = vec4(0.796078431372549,0.27450980392156865,0.4745098039215686,1);\n const float e5 = 0.63;\n const vec4 v5 = vec4(0.8980392156862745,0.4196078431372549,0.36470588235294116,1);\n const float e6 = 0.75;\n const vec4 v6 = vec4(0.9725490196078431,0.5803921568627451,0.2549019607843137,1);\n const float e7 = 0.88;\n const vec4 v7 = vec4(0.9921568627450981,0.7647058823529411,0.1568627450980392,1);\n const float e8 = 1.0;\n const vec4 v8 = vec4(0.9411764705882353,0.9764705882352941,0.12941176470588237,1);\n float a0 = smoothstep(e0,e1,x_4);\n float a1 = smoothstep(e1,e2,x_4);\n float a2 = smoothstep(e2,e3,x_4);\n float a3 = smoothstep(e3,e4,x_4);\n float a4 = smoothstep(e4,e5,x_4);\n float a5 = smoothstep(e5,e6,x_4);\n float a6 = smoothstep(e6,e7,x_4);\n float a7 = smoothstep(e7,e8,x_4);\n return max(mix(v0,v1,a0)*step(e0,x_4)*step(x_4,e1),\n max(mix(v1,v2,a1)*step(e1,x_4)*step(x_4,e2),\n max(mix(v2,v3,a2)*step(e2,x_4)*step(x_4,e3),\n max(mix(v3,v4,a3)*step(e3,x_4)*step(x_4,e4),\n max(mix(v4,v5,a4)*step(e4,x_4)*step(x_4,e5),\n max(mix(v5,v6,a5)*step(e5,x_4)*step(x_4,e6),\n max(mix(v6,v7,a6)*step(e6,x_4)*step(x_4,e7),mix(v7,v8,a7)*step(e7,x_4)*step(x_4,e8)\n )))))));\n}\n\nvec4 viridis (float x_1) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0.26666666666666666,0.00392156862745098,0.32941176470588235,1);\n const float e1 = 0.13;\n const vec4 v1 = vec4(0.2784313725490196,0.17254901960784313,0.47843137254901963,1);\n const float e2 = 0.25;\n const vec4 v2 = vec4(0.23137254901960785,0.3176470588235294,0.5450980392156862,1);\n const float e3 = 0.38;\n const vec4 v3 = vec4(0.17254901960784313,0.44313725490196076,0.5568627450980392,1);\n const float e4 = 0.5;\n const vec4 v4 = vec4(0.12941176470588237,0.5647058823529412,0.5529411764705883,1);\n const float e5 = 0.63;\n const vec4 v5 = vec4(0.15294117647058825,0.6784313725490196,0.5058823529411764,1);\n const float e6 = 0.75;\n const vec4 v6 = vec4(0.3607843137254902,0.7843137254901961,0.38823529411764707,1);\n const float e7 = 0.88;\n const vec4 v7 = vec4(0.6666666666666666,0.8627450980392157,0.19607843137254902,1);\n const float e8 = 1.0;\n const vec4 v8 = vec4(0.9921568627450981,0.9058823529411765,0.1450980392156863,1);\n float a0 = smoothstep(e0,e1,x_1);\n float a1 = smoothstep(e1,e2,x_1);\n float a2 = smoothstep(e2,e3,x_1);\n float a3 = smoothstep(e3,e4,x_1);\n float a4 = smoothstep(e4,e5,x_1);\n float a5 = smoothstep(e5,e6,x_1);\n float a6 = smoothstep(e6,e7,x_1);\n float a7 = smoothstep(e7,e8,x_1);\n return max(mix(v0,v1,a0)*step(e0,x_1)*step(x_1,e1),\n max(mix(v1,v2,a1)*step(e1,x_1)*step(x_1,e2),\n max(mix(v2,v3,a2)*step(e2,x_1)*step(x_1,e3),\n max(mix(v3,v4,a3)*step(e3,x_1)*step(x_1,e4),\n max(mix(v4,v5,a4)*step(e4,x_1)*step(x_1,e5),\n max(mix(v5,v6,a5)*step(e5,x_1)*step(x_1,e6),\n max(mix(v6,v7,a6)*step(e6,x_1)*step(x_1,e7),mix(v7,v8,a7)*step(e7,x_1)*step(x_1,e8)\n )))))));\n}\n\nvec4 greys (float x_10) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0,1);\n const float e1 = 1.0;\n const vec4 v1 = vec4(1,1,1,1);\n float a0 = smoothstep(e0,e1,x_10);\n return mix(v0,v1,a0)*step(e0,x_10)*step(x_10,e1);\n}\n\nvec4 magma (float x_7) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0.01568627450980392,1);\n const float e1 = 0.13;\n const vec4 v1 = vec4(0.10980392156862745,0.06274509803921569,0.26666666666666666,1);\n const float e2 = 0.25;\n const vec4 v2 = vec4(0.30980392156862746,0.07058823529411765,0.4823529411764706,1);\n const float e3 = 0.38;\n const vec4 v3 = vec4(0.5058823529411764,0.1450980392156863,0.5058823529411764,1);\n const float e4 = 0.5;\n const vec4 v4 = vec4(0.7098039215686275,0.21176470588235294,0.47843137254901963,1);\n const float e5 = 0.63;\n const vec4 v5 = vec4(0.8980392156862745,0.3137254901960784,0.39215686274509803,1);\n const float e6 = 0.75;\n const vec4 v6 = vec4(0.984313725490196,0.5294117647058824,0.3803921568627451,1);\n const float e7 = 0.88;\n const vec4 v7 = vec4(0.996078431372549,0.7607843137254902,0.5294117647058824,1);\n const float e8 = 1.0;\n const vec4 v8 = vec4(0.9882352941176471,0.9921568627450981,0.7490196078431373,1);\n float a0 = smoothstep(e0,e1,x_7);\n float a1 = smoothstep(e1,e2,x_7);\n float a2 = smoothstep(e2,e3,x_7);\n float a3 = smoothstep(e3,e4,x_7);\n float a4 = smoothstep(e4,e5,x_7);\n float a5 = smoothstep(e5,e6,x_7);\n float a6 = smoothstep(e6,e7,x_7);\n float a7 = smoothstep(e7,e8,x_7);\n return max(mix(v0,v1,a0)*step(e0,x_7)*step(x_7,e1),\n max(mix(v1,v2,a1)*step(e1,x_7)*step(x_7,e2),\n max(mix(v2,v3,a2)*step(e2,x_7)*step(x_7,e3),\n max(mix(v3,v4,a3)*step(e3,x_7)*step(x_7,e4),\n max(mix(v4,v5,a4)*step(e4,x_7)*step(x_7,e5),\n max(mix(v5,v6,a5)*step(e5,x_7)*step(x_7,e6),\n max(mix(v6,v7,a6)*step(e6,x_7)*step(x_7,e7),mix(v7,v8,a7)*step(e7,x_7)*step(x_7,e8)\n )))))));\n}\n\nvec4 jet (float x_8) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0.5137254901960784,1);\n const float e1 = 0.125;\n const vec4 v1 = vec4(0,0.23529411764705882,0.6666666666666666,1);\n const float e2 = 0.375;\n const vec4 v2 = vec4(0.0196078431372549,1,1,1);\n const float e3 = 0.625;\n const vec4 v3 = vec4(1,1,0,1);\n const float e4 = 0.875;\n const vec4 v4 = vec4(0.9803921568627451,0,0,1);\n const float e5 = 1.0;\n const vec4 v5 = vec4(0.5019607843137255,0,0,1);\n float a0 = smoothstep(e0,e1,x_8);\n float a1 = smoothstep(e1,e2,x_8);\n float a2 = smoothstep(e2,e3,x_8);\n float a3 = smoothstep(e3,e4,x_8);\n float a4 = smoothstep(e4,e5,x_8);\n return max(mix(v0,v1,a0)*step(e0,x_8)*step(x_8,e1),\n max(mix(v1,v2,a1)*step(e1,x_8)*step(x_8,e2),\n max(mix(v2,v3,a2)*step(e2,x_8)*step(x_8,e3),\n max(mix(v3,v4,a3)*step(e3,x_8)*step(x_8,e4),mix(v4,v5,a4)*step(e4,x_8)*step(x_8,e5)\n ))));\n}\n\nvec4 bone (float x_11) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0,1);\n const float e1 = 0.376;\n const vec4 v1 = vec4(0.32941176470588235,0.32941176470588235,0.4549019607843137,1);\n const float e2 = 0.753;\n const vec4 v2 = vec4(0.6627450980392157,0.7843137254901961,0.7843137254901961,1);\n const float e3 = 1.0;\n const vec4 v3 = vec4(1,1,1,1);\n float a0 = smoothstep(e0,e1,x_11);\n float a1 = smoothstep(e1,e2,x_11);\n float a2 = smoothstep(e2,e3,x_11);\n return max(mix(v0,v1,a0)*step(e0,x_11)*step(x_11,e1),\n max(mix(v1,v2,a1)*step(e1,x_11)*step(x_11,e2),mix(v2,v3,a2)*step(e2,x_11)*step(x_11,e3)\n ));\n}\n\nvec4 copper (float x_6) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0,1);\n const float e1 = 0.804;\n const vec4 v1 = vec4(1,0.6274509803921569,0.4,1);\n const float e2 = 1.0;\n const vec4 v2 = vec4(1,0.7803921568627451,0.4980392156862745,1);\n float a0 = smoothstep(e0,e1,x_6);\n float a1 = smoothstep(e1,e2,x_6);\n return max(mix(v0,v1,a0)*step(e0,x_6)*step(x_6,e1),mix(v1,v2,a1)*step(e1,x_6)*step(x_6,e2)\n );\n}\n\nvec4 density (float x_5) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0.21176470588235294,0.054901960784313725,0.1411764705882353,1);\n const float e1 = 0.13;\n const vec4 v1 = vec4(0.34901960784313724,0.09019607843137255,0.3137254901960784,1);\n const float e2 = 0.25;\n const vec4 v2 = vec4(0.43137254901960786,0.17647058823529413,0.5176470588235295,1);\n const float e3 = 0.38;\n const vec4 v3 = vec4(0.47058823529411764,0.30196078431372547,0.6980392156862745,1);\n const float e4 = 0.5;\n const vec4 v4 = vec4(0.47058823529411764,0.44313725490196076,0.8352941176470589,1);\n const float e5 = 0.63;\n const vec4 v5 = vec4(0.45098039215686275,0.592156862745098,0.8941176470588236,1);\n const float e6 = 0.75;\n const vec4 v6 = vec4(0.5254901960784314,0.7254901960784313,0.8901960784313725,1);\n const float e7 = 0.88;\n const vec4 v7 = vec4(0.6941176470588235,0.8392156862745098,0.8901960784313725,1);\n const float e8 = 1.0;\n const vec4 v8 = vec4(0.9019607843137255,0.9450980392156862,0.9450980392156862,1);\n float a0 = smoothstep(e0,e1,x_5);\n float a1 = smoothstep(e1,e2,x_5);\n float a2 = smoothstep(e2,e3,x_5);\n float a3 = smoothstep(e3,e4,x_5);\n float a4 = smoothstep(e4,e5,x_5);\n float a5 = smoothstep(e5,e6,x_5);\n float a6 = smoothstep(e6,e7,x_5);\n float a7 = smoothstep(e7,e8,x_5);\n return max(mix(v0,v1,a0)*step(e0,x_5)*step(x_5,e1),\n max(mix(v1,v2,a1)*step(e1,x_5)*step(x_5,e2),\n max(mix(v2,v3,a2)*step(e2,x_5)*step(x_5,e3),\n max(mix(v3,v4,a3)*step(e3,x_5)*step(x_5,e4),\n max(mix(v4,v5,a4)*step(e4,x_5)*step(x_5,e5),\n max(mix(v5,v6,a5)*step(e5,x_5)*step(x_5,e6),\n max(mix(v6,v7,a6)*step(e6,x_5)*step(x_5,e7),mix(v7,v8,a7)*step(e7,x_5)*step(x_5,e8)\n )))))));\n}\n\nvec4 inferno (float x_3) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0.01568627450980392,1);\n const float e1 = 0.13;\n const vec4 v1 = vec4(0.12156862745098039,0.047058823529411764,0.2823529411764706,1);\n const float e2 = 0.25;\n const vec4 v2 = vec4(0.3333333333333333,0.058823529411764705,0.42745098039215684,1);\n const float e3 = 0.38;\n const vec4 v3 = vec4(0.5333333333333333,0.13333333333333333,0.41568627450980394,1);\n const float e4 = 0.5;\n const vec4 v4 = vec4(0.7294117647058823,0.21176470588235294,0.3333333333333333,1);\n const float e5 = 0.63;\n const vec4 v5 = vec4(0.8901960784313725,0.34901960784313724,0.2,1);\n const float e6 = 0.75;\n const vec4 v6 = vec4(0.9764705882352941,0.5490196078431373,0.0392156862745098,1);\n const float e7 = 0.88;\n const vec4 v7 = vec4(0.9764705882352941,0.788235294117647,0.19607843137254902,1);\n const float e8 = 1.0;\n const vec4 v8 = vec4(0.9882352941176471,1,0.6431372549019608,1);\n float a0 = smoothstep(e0,e1,x_3);\n float a1 = smoothstep(e1,e2,x_3);\n float a2 = smoothstep(e2,e3,x_3);\n float a3 = smoothstep(e3,e4,x_3);\n float a4 = smoothstep(e4,e5,x_3);\n float a5 = smoothstep(e5,e6,x_3);\n float a6 = smoothstep(e6,e7,x_3);\n float a7 = smoothstep(e7,e8,x_3);\n return max(mix(v0,v1,a0)*step(e0,x_3)*step(x_3,e1),\n max(mix(v1,v2,a1)*step(e1,x_3)*step(x_3,e2),\n max(mix(v2,v3,a2)*step(e2,x_3)*step(x_3,e3),\n max(mix(v3,v4,a3)*step(e3,x_3)*step(x_3,e4),\n max(mix(v4,v5,a4)*step(e4,x_3)*step(x_3,e5),\n max(mix(v5,v6,a5)*step(e5,x_3)*step(x_3,e6),\n max(mix(v6,v7,a6)*step(e6,x_3)*step(x_3,e7),mix(v7,v8,a7)*step(e7,x_3)*step(x_3,e8)\n )))))));\n}\n\nvec4 cool (float x_2) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0.49019607843137253,0,0.7019607843137254,1);\n const float e1 = 0.13;\n const vec4 v1 = vec4(0.4549019607843137,0,0.8549019607843137,1);\n const float e2 = 0.25;\n const vec4 v2 = vec4(0.3843137254901961,0.2901960784313726,0.9294117647058824,1);\n const float e3 = 0.38;\n const vec4 v3 = vec4(0.26666666666666666,0.5725490196078431,0.9058823529411765,1);\n const float e4 = 0.5;\n const vec4 v4 = vec4(0,0.8,0.7725490196078432,1);\n const float e5 = 0.63;\n const vec4 v5 = vec4(0,0.9686274509803922,0.5725490196078431,1);\n const float e6 = 0.75;\n const vec4 v6 = vec4(0,1,0.34509803921568627,1);\n const float e7 = 0.88;\n const vec4 v7 = vec4(0.1568627450980392,1,0.03137254901960784,1);\n const float e8 = 1.0;\n const vec4 v8 = vec4(0.5764705882352941,1,0,1);\n float a0 = smoothstep(e0,e1,x_2);\n float a1 = smoothstep(e1,e2,x_2);\n float a2 = smoothstep(e2,e3,x_2);\n float a3 = smoothstep(e3,e4,x_2);\n float a4 = smoothstep(e4,e5,x_2);\n float a5 = smoothstep(e5,e6,x_2);\n float a6 = smoothstep(e6,e7,x_2);\n float a7 = smoothstep(e7,e8,x_2);\n return max(mix(v0,v1,a0)*step(e0,x_2)*step(x_2,e1),\n max(mix(v1,v2,a1)*step(e1,x_2)*step(x_2,e2),\n max(mix(v2,v3,a2)*step(e2,x_2)*step(x_2,e3),\n max(mix(v3,v4,a3)*step(e3,x_2)*step(x_2,e4),\n max(mix(v4,v5,a4)*step(e4,x_2)*step(x_2,e5),\n max(mix(v5,v6,a5)*step(e5,x_2)*step(x_2,e6),\n max(mix(v6,v7,a6)*step(e6,x_2)*step(x_2,e7),mix(v7,v8,a7)*step(e7,x_2)*step(x_2,e8)\n )))))));\n}\n\nvec4 hot (float x_0) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0,1);\n const float e1 = 0.3;\n const vec4 v1 = vec4(0.9019607843137255,0,0,1);\n const float e2 = 0.6;\n const vec4 v2 = vec4(1,0.8235294117647058,0,1);\n const float e3 = 1.0;\n const vec4 v3 = vec4(1,1,1,1);\n float a0 = smoothstep(e0,e1,x_0);\n float a1 = smoothstep(e1,e2,x_0);\n float a2 = smoothstep(e2,e3,x_0);\n return max(mix(v0,v1,a0)*step(e0,x_0)*step(x_0,e1),\n max(mix(v1,v2,a1)*step(e1,x_0)*step(x_0,e2),mix(v2,v3,a2)*step(e2,x_0)*step(x_0,e3)\n ));\n}\n\nvec4 spring (float x_14) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(1,0,1,1);\n const float e1 = 1.0;\n const vec4 v1 = vec4(1,1,0,1);\n float a0 = smoothstep(e0,e1,x_14);\n return mix(v0,v1,a0)*step(e0,x_14)*step(x_14,e1);\n}\n\nvec4 summer (float x_9) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0.5019607843137255,0.4,1);\n const float e1 = 1.0;\n const vec4 v1 = vec4(1,1,0.4,1);\n float a0 = smoothstep(e0,e1,x_9);\n return mix(v0,v1,a0)*step(e0,x_9)*step(x_9,e1);\n}\n\nvec4 autumn (float x_13) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(1,0,0,1);\n const float e1 = 1.0;\n const vec4 v1 = vec4(1,1,0,1);\n float a0 = smoothstep(e0,e1,x_13);\n return mix(v0,v1,a0)*step(e0,x_13)*step(x_13,e1);\n}\n\nvec4 winter (float x_12) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,1,1);\n const float e1 = 1.0;\n const vec4 v1 = vec4(0,1,0.5019607843137255,1);\n float a0 = smoothstep(e0,e1,x_12);\n return mix(v0,v1,a0)*step(e0,x_12)*step(x_12,e1);\n}\n\n\n// Note: can have a maximum of 16 textures in most browsers\n// Reference: https://webglreport.com/\n\n// Data (mask) texture\nuniform sampler2D channel0;\nuniform sampler2D channel1;\nuniform sampler2D channel2;\nuniform sampler2D channel3;\nuniform sampler2D channel4;\nuniform sampler2D channel5;\nuniform sampler2D channel6;\n\n// Color texture\nuniform float hovered;\n\n// Channel-specific properties\nuniform bool channelsVisible[7];\nuniform float channelOpacities[7];\nuniform bool channelIsStaticColorMode[7]; // TODO: should this be a single float?\nuniform bool channelIsSetColorMode[7]; // TODO: should this be a single float?\n\n// TODO: can array of tuples/vec2 be used?\nuniform float channelColormapRangeStarts[7];\nuniform float channelColormapRangeEnds[7];\n\nuniform float multiFeatureTexSize;\n\n// Use one expressionTex for all channels, using an offset mechanism.\nuniform sampler2D valueTex;\nuniform float valueTexOffsets[7];\nuniform float valueTexHeight;\n\n// Textures for set colors, using the same offset mechanism.\nuniform sampler2D colorTex;\nuniform float colorTexOffsets[7];\nuniform float colorTexHeight;\n\n\n// Static colors\n// TODO: For some reason I cannot use uniform vec3 colors[7]; and i cannot figure out why.\nuniform vec3 color0;\nuniform vec3 color1;\nuniform vec3 color2;\nuniform vec3 color3;\nuniform vec3 color4;\nuniform vec3 color5;\nuniform vec3 color6;\n\n// Info for edge-only mode\nuniform float scaleFactor;\nuniform bool channelsFilled[7];\nuniform float channelStrokeWidths[7];\n\n// opacity\nuniform float opacity;\n\nvarying vec2 vTexCoord;\n\nvec3 sampleAndGetData(sampler2D dataTex, vec2 coord, bool isFilled, float strokeWidth, bool isOn) {\n float sampledData = texture(dataTex, coord).r;\n float clampedSampledData = max(0., min(sampledData, 1.));\n\n bool isEdge = true;\n\n if(!isFilled) {\n vec2 uTextureSize = vec2(2048.0, 2048.0);\n vec2 onePixel = vec2(1.0, 1.0) / uTextureSize;\n\n // Vary the edgeSize based on user-defined stroke width.\n float edgeSize = 150.0 * strokeWidth * scaleFactor;\n\n float pixN = texture(dataTex, coord + vec2(0.0, onePixel.y * edgeSize)).r;\n float pixS = texture(dataTex, coord - vec2(0.0, onePixel.y * edgeSize)).r;\n float pixW = texture(dataTex, coord + vec2(onePixel.x * edgeSize, 0.0)).r;\n float pixE = texture(dataTex, coord - vec2(onePixel.x * edgeSize, 0.0)).r;\n\n float pixNW = texture(dataTex, coord + vec2(onePixel.y * edgeSize, onePixel.y * edgeSize)).r;\n float pixNE = texture(dataTex, coord + vec2(-1.0 * onePixel.x * edgeSize, onePixel.y * edgeSize)).r;\n float pixSW = texture(dataTex, coord - vec2(onePixel.x * edgeSize, onePixel.y * edgeSize)).r;\n float pixSE = texture(dataTex, coord - vec2(-1.0 * onePixel.x * edgeSize, onePixel.y * edgeSize)).r;\n\n isEdge = (pixN != sampledData || pixS != sampledData || pixW != sampledData || pixE != sampledData || pixNW != sampledData || pixNE != sampledData || pixSW != sampledData || pixSE != sampledData);\n }\n // Return a tuple of (sampledData, isEdge)\n return vec3(clampedSampledData * float(isOn), sampledData, float(isEdge));\n}\n\nvec4 dataToColor(vec3 sampledDataAndIsEdge, bool isStaticColorMode, vec3 channelColor, float channelOpacity, float valueOffset, float rangeStart, float rangeEnd, bool isSetColorMode, float setColorOffset) {\n float clampedSampledDataAndIsOn = sampledDataAndIsEdge.x;\n float sampledData = sampledDataAndIsEdge.y;\n float isEdge = sampledDataAndIsEdge.z;\n \n\n vec4 hoveredColor = float(sampledData == hovered && sampledData > 0. && hovered > 0.) * vec4(0., 0., 1., 1.);\n \n // Colors are laid out corresponding to ids in row-major order in the texture. So if width of the texture is 10, and you want ID 25,\n // you need coordinate (1, 4) (i.e 2 rows down, and 5 columns over indexed from 0 for a total of 25 units covered in row major order).\n float offsetSampledData = sampledData + valueOffset - 1.0;\n vec2 colorTexCoord = vec2(mod(offsetSampledData, multiFeatureTexSize) / multiFeatureTexSize, floor(offsetSampledData / multiFeatureTexSize) / (valueTexHeight - 1.));\n\n // Get expression value\n float expressionValue = texture(valueTex, colorTexCoord).r / 255.;\n float scaledExpressionValue = (expressionValue - rangeStart) / max(0.005, (rangeEnd - rangeStart));\n\n\n // Get set color index value\n vec2 setIndicesTexCoord = vec2(mod(offsetSampledData, multiFeatureTexSize) / multiFeatureTexSize, floor(offsetSampledData / multiFeatureTexSize) / (valueTexHeight - 1.));\n float setColorIndex = texture(valueTex, setIndicesTexCoord).r;\n\n // Initialize to the default \"null\" color.\n vec3 setColor = vec3(200. / 255., 200. / 255., 200. / 255.);\n if(setColorIndex != 0.) {\n // Subtract one from setColorIndex because we have already checked for the \"null\" value.\n setColorIndex = setColorIndex - 1.;\n\n float setColorOffsetR = (setColorIndex + setColorOffset) * 3.0 + 0.0;\n vec2 setColorTexCoordR = vec2(mod(setColorOffsetR, multiFeatureTexSize) / multiFeatureTexSize, floor(setColorOffsetR / multiFeatureTexSize) / (colorTexHeight - 1.));\n float setColorR = texture(colorTex, setColorTexCoordR).r / 255.;\n\n float setColorOffsetG = (setColorIndex + setColorOffset) * 3.0 + 1.0;\n vec2 setColorTexCoordG = vec2(mod(setColorOffsetG, multiFeatureTexSize) / multiFeatureTexSize, floor(setColorOffsetG / multiFeatureTexSize) / (colorTexHeight - 1.));\n float setColorG = texture(colorTex, setColorTexCoordG).r / 255.;\n\n float setColorOffsetB = (setColorIndex + setColorOffset) * 3.0 + 2.0;\n vec2 setColorTexCoordB = vec2(mod(setColorOffsetB, multiFeatureTexSize) / multiFeatureTexSize, floor(setColorOffsetB / multiFeatureTexSize) / (colorTexHeight - 1.));\n float setColorB = texture(colorTex, setColorTexCoordB).r / 255.;\n\n setColor = vec3(setColorR, setColorG, setColorB);\n }\n\n \n vec4 sampledColor = (1. - (float(isStaticColorMode) + float(isSetColorMode))) * vec4(COLORMAP_FUNC(clamp(scaledExpressionValue, 0.0, 1.0)).rgb, channelOpacity) + float(isStaticColorMode) * vec4(channelColor.rgb, channelOpacity) + float(isSetColorMode) * vec4(setColor, channelOpacity);\n // Only return a color if the data is non-zero.\n \n return clampedSampledDataAndIsOn * isEdge * sampledColor;\n}\n\nvoid main() {\n\n // Get the color and alpha value for each channel.\n vec3 dat0 = sampleAndGetData(channel0, vTexCoord, channelsFilled[0], channelStrokeWidths[0], channelsVisible[0]);\n vec3 dat1 = sampleAndGetData(channel1, vTexCoord, channelsFilled[1], channelStrokeWidths[1], channelsVisible[1]);\n vec3 dat2 = sampleAndGetData(channel2, vTexCoord, channelsFilled[2], channelStrokeWidths[2], channelsVisible[2]);\n vec3 dat3 = sampleAndGetData(channel3, vTexCoord, channelsFilled[3], channelStrokeWidths[3], channelsVisible[3]);\n vec3 dat4 = sampleAndGetData(channel4, vTexCoord, channelsFilled[4], channelStrokeWidths[4], channelsVisible[4]);\n vec3 dat5 = sampleAndGetData(channel5, vTexCoord, channelsFilled[5], channelStrokeWidths[5], channelsVisible[5]);\n vec3 dat6 = sampleAndGetData(channel6, vTexCoord, channelsFilled[6], channelStrokeWidths[6], channelsVisible[6]);\n \n vec4 val0 = dataToColor(dat0, channelIsStaticColorMode[0], color0, channelOpacities[0], valueTexOffsets[0], channelColormapRangeStarts[0], channelColormapRangeEnds[0], channelIsSetColorMode[0], colorTexOffsets[0]);\n vec4 val1 = dataToColor(dat1, channelIsStaticColorMode[1], color1, channelOpacities[1], valueTexOffsets[1], channelColormapRangeStarts[1], channelColormapRangeEnds[1], channelIsSetColorMode[1], colorTexOffsets[1]);\n vec4 val2 = dataToColor(dat2, channelIsStaticColorMode[2], color2, channelOpacities[2], valueTexOffsets[2], channelColormapRangeStarts[2], channelColormapRangeEnds[2], channelIsSetColorMode[2], colorTexOffsets[2]);\n vec4 val3 = dataToColor(dat3, channelIsStaticColorMode[3], color3, channelOpacities[3], valueTexOffsets[3], channelColormapRangeStarts[3], channelColormapRangeEnds[3], channelIsSetColorMode[3], colorTexOffsets[3]);\n vec4 val4 = dataToColor(dat4, channelIsStaticColorMode[4], color4, channelOpacities[4], valueTexOffsets[4], channelColormapRangeStarts[4], channelColormapRangeEnds[4], channelIsSetColorMode[4], colorTexOffsets[4]);\n vec4 val5 = dataToColor(dat5, channelIsStaticColorMode[5], color5, channelOpacities[5], valueTexOffsets[5], channelColormapRangeStarts[5], channelColormapRangeEnds[5], channelIsSetColorMode[5], colorTexOffsets[5]);\n vec4 val6 = dataToColor(dat6, channelIsStaticColorMode[6], color6, channelOpacities[6], valueTexOffsets[6], channelColormapRangeStarts[6], channelColormapRangeEnds[6], channelIsSetColorMode[6], colorTexOffsets[6]);\n \n // If all of the channels are \"empty\", then discard this pixel so that it is not considered during picking.\n float emptyDat = 0.;\n if(dat0.x == emptyDat && dat1.x == emptyDat && dat2.x == emptyDat && dat3.x == emptyDat && dat4.x == emptyDat && dat5.x == emptyDat && dat6.x == emptyDat) {\n discard;\n }\n \n // If the next channel color and the currently stored color (gl_FragColor) are identical,\n // or the next channel color is transparent black,\n // just use the currently stored color. Repeat this for all channels.\n\n // Mix colors where necessary, using the alpha value of the next channel as the weight.\n // Use the maximum alpha value as the resulting alpha value.\n gl_FragColor = val0;\n gl_FragColor = (val1 == gl_FragColor || val1 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val1, val1.a).rgb, max(gl_FragColor.a, val1.a));\n gl_FragColor = (val2 == gl_FragColor || val2 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val2, val2.a).rgb, max(gl_FragColor.a, val2.a));\n gl_FragColor = (val3 == gl_FragColor || val3 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val3, val3.a).rgb, max(gl_FragColor.a, val3.a));\n gl_FragColor = (val4 == gl_FragColor || val4 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val4, val4.a).rgb, max(gl_FragColor.a, val4.a));\n gl_FragColor = (val5 == gl_FragColor || val5 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val5, val5.a).rgb, max(gl_FragColor.a, val5.a));\n gl_FragColor = (val6 == gl_FragColor || val6 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val6, val6.a).rgb, max(gl_FragColor.a, val6.a));\n\n \n\n // TODO: multiply the resulting channel-level opacity value by the layer-level opacity value.\n\n geometry.uv = vTexCoord;\n DECKGL_FILTER_COLOR(gl_FragColor, geometry);\n}\n";
2
+ export const fs: "\n#define SHADER_NAME bitmask-layer-fragment-shader\nprecision highp float;\n\n#define GLSLIFY 1\nvec4 plasma (float x_4) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0.050980392156862744,0.03137254901960784,0.5294117647058824,1);\n const float e1 = 0.13;\n const vec4 v1 = vec4(0.29411764705882354,0.011764705882352941,0.6313725490196078,1);\n const float e2 = 0.25;\n const vec4 v2 = vec4(0.49019607843137253,0.011764705882352941,0.6588235294117647,1);\n const float e3 = 0.38;\n const vec4 v3 = vec4(0.6588235294117647,0.13333333333333333,0.5882352941176471,1);\n const float e4 = 0.5;\n const vec4 v4 = vec4(0.796078431372549,0.27450980392156865,0.4745098039215686,1);\n const float e5 = 0.63;\n const vec4 v5 = vec4(0.8980392156862745,0.4196078431372549,0.36470588235294116,1);\n const float e6 = 0.75;\n const vec4 v6 = vec4(0.9725490196078431,0.5803921568627451,0.2549019607843137,1);\n const float e7 = 0.88;\n const vec4 v7 = vec4(0.9921568627450981,0.7647058823529411,0.1568627450980392,1);\n const float e8 = 1.0;\n const vec4 v8 = vec4(0.9411764705882353,0.9764705882352941,0.12941176470588237,1);\n float a0 = smoothstep(e0,e1,x_4);\n float a1 = smoothstep(e1,e2,x_4);\n float a2 = smoothstep(e2,e3,x_4);\n float a3 = smoothstep(e3,e4,x_4);\n float a4 = smoothstep(e4,e5,x_4);\n float a5 = smoothstep(e5,e6,x_4);\n float a6 = smoothstep(e6,e7,x_4);\n float a7 = smoothstep(e7,e8,x_4);\n return max(mix(v0,v1,a0)*step(e0,x_4)*step(x_4,e1),\n max(mix(v1,v2,a1)*step(e1,x_4)*step(x_4,e2),\n max(mix(v2,v3,a2)*step(e2,x_4)*step(x_4,e3),\n max(mix(v3,v4,a3)*step(e3,x_4)*step(x_4,e4),\n max(mix(v4,v5,a4)*step(e4,x_4)*step(x_4,e5),\n max(mix(v5,v6,a5)*step(e5,x_4)*step(x_4,e6),\n max(mix(v6,v7,a6)*step(e6,x_4)*step(x_4,e7),mix(v7,v8,a7)*step(e7,x_4)*step(x_4,e8)\n )))))));\n}\n\nvec4 viridis (float x_1) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0.26666666666666666,0.00392156862745098,0.32941176470588235,1);\n const float e1 = 0.13;\n const vec4 v1 = vec4(0.2784313725490196,0.17254901960784313,0.47843137254901963,1);\n const float e2 = 0.25;\n const vec4 v2 = vec4(0.23137254901960785,0.3176470588235294,0.5450980392156862,1);\n const float e3 = 0.38;\n const vec4 v3 = vec4(0.17254901960784313,0.44313725490196076,0.5568627450980392,1);\n const float e4 = 0.5;\n const vec4 v4 = vec4(0.12941176470588237,0.5647058823529412,0.5529411764705883,1);\n const float e5 = 0.63;\n const vec4 v5 = vec4(0.15294117647058825,0.6784313725490196,0.5058823529411764,1);\n const float e6 = 0.75;\n const vec4 v6 = vec4(0.3607843137254902,0.7843137254901961,0.38823529411764707,1);\n const float e7 = 0.88;\n const vec4 v7 = vec4(0.6666666666666666,0.8627450980392157,0.19607843137254902,1);\n const float e8 = 1.0;\n const vec4 v8 = vec4(0.9921568627450981,0.9058823529411765,0.1450980392156863,1);\n float a0 = smoothstep(e0,e1,x_1);\n float a1 = smoothstep(e1,e2,x_1);\n float a2 = smoothstep(e2,e3,x_1);\n float a3 = smoothstep(e3,e4,x_1);\n float a4 = smoothstep(e4,e5,x_1);\n float a5 = smoothstep(e5,e6,x_1);\n float a6 = smoothstep(e6,e7,x_1);\n float a7 = smoothstep(e7,e8,x_1);\n return max(mix(v0,v1,a0)*step(e0,x_1)*step(x_1,e1),\n max(mix(v1,v2,a1)*step(e1,x_1)*step(x_1,e2),\n max(mix(v2,v3,a2)*step(e2,x_1)*step(x_1,e3),\n max(mix(v3,v4,a3)*step(e3,x_1)*step(x_1,e4),\n max(mix(v4,v5,a4)*step(e4,x_1)*step(x_1,e5),\n max(mix(v5,v6,a5)*step(e5,x_1)*step(x_1,e6),\n max(mix(v6,v7,a6)*step(e6,x_1)*step(x_1,e7),mix(v7,v8,a7)*step(e7,x_1)*step(x_1,e8)\n )))))));\n}\n\nvec4 greys (float x_10) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0,1);\n const float e1 = 1.0;\n const vec4 v1 = vec4(1,1,1,1);\n float a0 = smoothstep(e0,e1,x_10);\n return mix(v0,v1,a0)*step(e0,x_10)*step(x_10,e1);\n}\n\nvec4 magma (float x_7) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0.01568627450980392,1);\n const float e1 = 0.13;\n const vec4 v1 = vec4(0.10980392156862745,0.06274509803921569,0.26666666666666666,1);\n const float e2 = 0.25;\n const vec4 v2 = vec4(0.30980392156862746,0.07058823529411765,0.4823529411764706,1);\n const float e3 = 0.38;\n const vec4 v3 = vec4(0.5058823529411764,0.1450980392156863,0.5058823529411764,1);\n const float e4 = 0.5;\n const vec4 v4 = vec4(0.7098039215686275,0.21176470588235294,0.47843137254901963,1);\n const float e5 = 0.63;\n const vec4 v5 = vec4(0.8980392156862745,0.3137254901960784,0.39215686274509803,1);\n const float e6 = 0.75;\n const vec4 v6 = vec4(0.984313725490196,0.5294117647058824,0.3803921568627451,1);\n const float e7 = 0.88;\n const vec4 v7 = vec4(0.996078431372549,0.7607843137254902,0.5294117647058824,1);\n const float e8 = 1.0;\n const vec4 v8 = vec4(0.9882352941176471,0.9921568627450981,0.7490196078431373,1);\n float a0 = smoothstep(e0,e1,x_7);\n float a1 = smoothstep(e1,e2,x_7);\n float a2 = smoothstep(e2,e3,x_7);\n float a3 = smoothstep(e3,e4,x_7);\n float a4 = smoothstep(e4,e5,x_7);\n float a5 = smoothstep(e5,e6,x_7);\n float a6 = smoothstep(e6,e7,x_7);\n float a7 = smoothstep(e7,e8,x_7);\n return max(mix(v0,v1,a0)*step(e0,x_7)*step(x_7,e1),\n max(mix(v1,v2,a1)*step(e1,x_7)*step(x_7,e2),\n max(mix(v2,v3,a2)*step(e2,x_7)*step(x_7,e3),\n max(mix(v3,v4,a3)*step(e3,x_7)*step(x_7,e4),\n max(mix(v4,v5,a4)*step(e4,x_7)*step(x_7,e5),\n max(mix(v5,v6,a5)*step(e5,x_7)*step(x_7,e6),\n max(mix(v6,v7,a6)*step(e6,x_7)*step(x_7,e7),mix(v7,v8,a7)*step(e7,x_7)*step(x_7,e8)\n )))))));\n}\n\nvec4 jet (float x_8) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0.5137254901960784,1);\n const float e1 = 0.125;\n const vec4 v1 = vec4(0,0.23529411764705882,0.6666666666666666,1);\n const float e2 = 0.375;\n const vec4 v2 = vec4(0.0196078431372549,1,1,1);\n const float e3 = 0.625;\n const vec4 v3 = vec4(1,1,0,1);\n const float e4 = 0.875;\n const vec4 v4 = vec4(0.9803921568627451,0,0,1);\n const float e5 = 1.0;\n const vec4 v5 = vec4(0.5019607843137255,0,0,1);\n float a0 = smoothstep(e0,e1,x_8);\n float a1 = smoothstep(e1,e2,x_8);\n float a2 = smoothstep(e2,e3,x_8);\n float a3 = smoothstep(e3,e4,x_8);\n float a4 = smoothstep(e4,e5,x_8);\n return max(mix(v0,v1,a0)*step(e0,x_8)*step(x_8,e1),\n max(mix(v1,v2,a1)*step(e1,x_8)*step(x_8,e2),\n max(mix(v2,v3,a2)*step(e2,x_8)*step(x_8,e3),\n max(mix(v3,v4,a3)*step(e3,x_8)*step(x_8,e4),mix(v4,v5,a4)*step(e4,x_8)*step(x_8,e5)\n ))));\n}\n\nvec4 bone (float x_11) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0,1);\n const float e1 = 0.376;\n const vec4 v1 = vec4(0.32941176470588235,0.32941176470588235,0.4549019607843137,1);\n const float e2 = 0.753;\n const vec4 v2 = vec4(0.6627450980392157,0.7843137254901961,0.7843137254901961,1);\n const float e3 = 1.0;\n const vec4 v3 = vec4(1,1,1,1);\n float a0 = smoothstep(e0,e1,x_11);\n float a1 = smoothstep(e1,e2,x_11);\n float a2 = smoothstep(e2,e3,x_11);\n return max(mix(v0,v1,a0)*step(e0,x_11)*step(x_11,e1),\n max(mix(v1,v2,a1)*step(e1,x_11)*step(x_11,e2),mix(v2,v3,a2)*step(e2,x_11)*step(x_11,e3)\n ));\n}\n\nvec4 copper (float x_6) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0,1);\n const float e1 = 0.804;\n const vec4 v1 = vec4(1,0.6274509803921569,0.4,1);\n const float e2 = 1.0;\n const vec4 v2 = vec4(1,0.7803921568627451,0.4980392156862745,1);\n float a0 = smoothstep(e0,e1,x_6);\n float a1 = smoothstep(e1,e2,x_6);\n return max(mix(v0,v1,a0)*step(e0,x_6)*step(x_6,e1),mix(v1,v2,a1)*step(e1,x_6)*step(x_6,e2)\n );\n}\n\nvec4 density (float x_5) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0.21176470588235294,0.054901960784313725,0.1411764705882353,1);\n const float e1 = 0.13;\n const vec4 v1 = vec4(0.34901960784313724,0.09019607843137255,0.3137254901960784,1);\n const float e2 = 0.25;\n const vec4 v2 = vec4(0.43137254901960786,0.17647058823529413,0.5176470588235295,1);\n const float e3 = 0.38;\n const vec4 v3 = vec4(0.47058823529411764,0.30196078431372547,0.6980392156862745,1);\n const float e4 = 0.5;\n const vec4 v4 = vec4(0.47058823529411764,0.44313725490196076,0.8352941176470589,1);\n const float e5 = 0.63;\n const vec4 v5 = vec4(0.45098039215686275,0.592156862745098,0.8941176470588236,1);\n const float e6 = 0.75;\n const vec4 v6 = vec4(0.5254901960784314,0.7254901960784313,0.8901960784313725,1);\n const float e7 = 0.88;\n const vec4 v7 = vec4(0.6941176470588235,0.8392156862745098,0.8901960784313725,1);\n const float e8 = 1.0;\n const vec4 v8 = vec4(0.9019607843137255,0.9450980392156862,0.9450980392156862,1);\n float a0 = smoothstep(e0,e1,x_5);\n float a1 = smoothstep(e1,e2,x_5);\n float a2 = smoothstep(e2,e3,x_5);\n float a3 = smoothstep(e3,e4,x_5);\n float a4 = smoothstep(e4,e5,x_5);\n float a5 = smoothstep(e5,e6,x_5);\n float a6 = smoothstep(e6,e7,x_5);\n float a7 = smoothstep(e7,e8,x_5);\n return max(mix(v0,v1,a0)*step(e0,x_5)*step(x_5,e1),\n max(mix(v1,v2,a1)*step(e1,x_5)*step(x_5,e2),\n max(mix(v2,v3,a2)*step(e2,x_5)*step(x_5,e3),\n max(mix(v3,v4,a3)*step(e3,x_5)*step(x_5,e4),\n max(mix(v4,v5,a4)*step(e4,x_5)*step(x_5,e5),\n max(mix(v5,v6,a5)*step(e5,x_5)*step(x_5,e6),\n max(mix(v6,v7,a6)*step(e6,x_5)*step(x_5,e7),mix(v7,v8,a7)*step(e7,x_5)*step(x_5,e8)\n )))))));\n}\n\nvec4 inferno (float x_3) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0.01568627450980392,1);\n const float e1 = 0.13;\n const vec4 v1 = vec4(0.12156862745098039,0.047058823529411764,0.2823529411764706,1);\n const float e2 = 0.25;\n const vec4 v2 = vec4(0.3333333333333333,0.058823529411764705,0.42745098039215684,1);\n const float e3 = 0.38;\n const vec4 v3 = vec4(0.5333333333333333,0.13333333333333333,0.41568627450980394,1);\n const float e4 = 0.5;\n const vec4 v4 = vec4(0.7294117647058823,0.21176470588235294,0.3333333333333333,1);\n const float e5 = 0.63;\n const vec4 v5 = vec4(0.8901960784313725,0.34901960784313724,0.2,1);\n const float e6 = 0.75;\n const vec4 v6 = vec4(0.9764705882352941,0.5490196078431373,0.0392156862745098,1);\n const float e7 = 0.88;\n const vec4 v7 = vec4(0.9764705882352941,0.788235294117647,0.19607843137254902,1);\n const float e8 = 1.0;\n const vec4 v8 = vec4(0.9882352941176471,1,0.6431372549019608,1);\n float a0 = smoothstep(e0,e1,x_3);\n float a1 = smoothstep(e1,e2,x_3);\n float a2 = smoothstep(e2,e3,x_3);\n float a3 = smoothstep(e3,e4,x_3);\n float a4 = smoothstep(e4,e5,x_3);\n float a5 = smoothstep(e5,e6,x_3);\n float a6 = smoothstep(e6,e7,x_3);\n float a7 = smoothstep(e7,e8,x_3);\n return max(mix(v0,v1,a0)*step(e0,x_3)*step(x_3,e1),\n max(mix(v1,v2,a1)*step(e1,x_3)*step(x_3,e2),\n max(mix(v2,v3,a2)*step(e2,x_3)*step(x_3,e3),\n max(mix(v3,v4,a3)*step(e3,x_3)*step(x_3,e4),\n max(mix(v4,v5,a4)*step(e4,x_3)*step(x_3,e5),\n max(mix(v5,v6,a5)*step(e5,x_3)*step(x_3,e6),\n max(mix(v6,v7,a6)*step(e6,x_3)*step(x_3,e7),mix(v7,v8,a7)*step(e7,x_3)*step(x_3,e8)\n )))))));\n}\n\nvec4 cool (float x_2) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0.49019607843137253,0,0.7019607843137254,1);\n const float e1 = 0.13;\n const vec4 v1 = vec4(0.4549019607843137,0,0.8549019607843137,1);\n const float e2 = 0.25;\n const vec4 v2 = vec4(0.3843137254901961,0.2901960784313726,0.9294117647058824,1);\n const float e3 = 0.38;\n const vec4 v3 = vec4(0.26666666666666666,0.5725490196078431,0.9058823529411765,1);\n const float e4 = 0.5;\n const vec4 v4 = vec4(0,0.8,0.7725490196078432,1);\n const float e5 = 0.63;\n const vec4 v5 = vec4(0,0.9686274509803922,0.5725490196078431,1);\n const float e6 = 0.75;\n const vec4 v6 = vec4(0,1,0.34509803921568627,1);\n const float e7 = 0.88;\n const vec4 v7 = vec4(0.1568627450980392,1,0.03137254901960784,1);\n const float e8 = 1.0;\n const vec4 v8 = vec4(0.5764705882352941,1,0,1);\n float a0 = smoothstep(e0,e1,x_2);\n float a1 = smoothstep(e1,e2,x_2);\n float a2 = smoothstep(e2,e3,x_2);\n float a3 = smoothstep(e3,e4,x_2);\n float a4 = smoothstep(e4,e5,x_2);\n float a5 = smoothstep(e5,e6,x_2);\n float a6 = smoothstep(e6,e7,x_2);\n float a7 = smoothstep(e7,e8,x_2);\n return max(mix(v0,v1,a0)*step(e0,x_2)*step(x_2,e1),\n max(mix(v1,v2,a1)*step(e1,x_2)*step(x_2,e2),\n max(mix(v2,v3,a2)*step(e2,x_2)*step(x_2,e3),\n max(mix(v3,v4,a3)*step(e3,x_2)*step(x_2,e4),\n max(mix(v4,v5,a4)*step(e4,x_2)*step(x_2,e5),\n max(mix(v5,v6,a5)*step(e5,x_2)*step(x_2,e6),\n max(mix(v6,v7,a6)*step(e6,x_2)*step(x_2,e7),mix(v7,v8,a7)*step(e7,x_2)*step(x_2,e8)\n )))))));\n}\n\nvec4 hot (float x_0) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,0,1);\n const float e1 = 0.3;\n const vec4 v1 = vec4(0.9019607843137255,0,0,1);\n const float e2 = 0.6;\n const vec4 v2 = vec4(1,0.8235294117647058,0,1);\n const float e3 = 1.0;\n const vec4 v3 = vec4(1,1,1,1);\n float a0 = smoothstep(e0,e1,x_0);\n float a1 = smoothstep(e1,e2,x_0);\n float a2 = smoothstep(e2,e3,x_0);\n return max(mix(v0,v1,a0)*step(e0,x_0)*step(x_0,e1),\n max(mix(v1,v2,a1)*step(e1,x_0)*step(x_0,e2),mix(v2,v3,a2)*step(e2,x_0)*step(x_0,e3)\n ));\n}\n\nvec4 spring (float x_14) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(1,0,1,1);\n const float e1 = 1.0;\n const vec4 v1 = vec4(1,1,0,1);\n float a0 = smoothstep(e0,e1,x_14);\n return mix(v0,v1,a0)*step(e0,x_14)*step(x_14,e1);\n}\n\nvec4 summer (float x_9) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0.5019607843137255,0.4,1);\n const float e1 = 1.0;\n const vec4 v1 = vec4(1,1,0.4,1);\n float a0 = smoothstep(e0,e1,x_9);\n return mix(v0,v1,a0)*step(e0,x_9)*step(x_9,e1);\n}\n\nvec4 autumn (float x_13) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(1,0,0,1);\n const float e1 = 1.0;\n const vec4 v1 = vec4(1,1,0,1);\n float a0 = smoothstep(e0,e1,x_13);\n return mix(v0,v1,a0)*step(e0,x_13)*step(x_13,e1);\n}\n\nvec4 winter (float x_12) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0,0,1,1);\n const float e1 = 1.0;\n const vec4 v1 = vec4(0,1,0.5019607843137255,1);\n float a0 = smoothstep(e0,e1,x_12);\n return mix(v0,v1,a0)*step(e0,x_12)*step(x_12,e1);\n}\n\n\n// Note: can have a maximum of 16 textures in most browsers\n// Reference: https://webglreport.com/\n\n// Data (mask) texture\nuniform sampler2D channel0;\nuniform sampler2D channel1;\nuniform sampler2D channel2;\nuniform sampler2D channel3;\nuniform sampler2D channel4;\nuniform sampler2D channel5;\nuniform sampler2D channel6;\n\n// Color texture\nuniform float hovered;\n\n// Channel-specific properties\nuniform bool channelsVisible[7];\nuniform float channelOpacities[7];\nuniform bool channelIsStaticColorMode[7]; // TODO: should this be a single float?\nuniform bool channelIsSetColorMode[7]; // TODO: should this be a single float?\n\nuniform int channelColormapFuncIndices[7];\nuniform float channelColormapRangeStarts[7];\nuniform float channelColormapRangeEnds[7];\n\nuniform float multiFeatureTexSize;\n\n// Use one expressionTex for all channels, using an offset mechanism.\nuniform sampler2D valueTex;\nuniform float valueTexOffsets[7];\nuniform float valueTexHeight;\n\n// Textures for set colors, using the same offset mechanism.\nuniform sampler2D colorTex;\nuniform float colorTexOffsets[7];\nuniform float colorTexHeight;\n\n\n// Static colors\n// TODO: For some reason I cannot use uniform vec3 colors[7]; and i cannot figure out why.\nuniform vec3 color0;\nuniform vec3 color1;\nuniform vec3 color2;\nuniform vec3 color3;\nuniform vec3 color4;\nuniform vec3 color5;\nuniform vec3 color6;\n\n// Info for edge-only mode\nuniform float scaleFactor;\nuniform bool channelsFilled[7];\nuniform float channelStrokeWidths[7];\n\n// opacity\nuniform float opacity;\n\nvarying vec2 vTexCoord;\n\nvec3 sampleAndGetData(sampler2D dataTex, vec2 coord, bool isFilled, float strokeWidth, bool isOn) {\n float sampledData = texture(dataTex, coord).r;\n float clampedSampledData = max(0., min(sampledData, 1.));\n\n bool isEdge = true;\n\n if(!isFilled) {\n vec2 uTextureSize = vec2(2048.0, 2048.0);\n vec2 onePixel = vec2(1.0, 1.0) / uTextureSize;\n\n // Vary the edgeSize based on user-defined stroke width.\n float edgeSize = 150.0 * strokeWidth * scaleFactor;\n\n float pixN = texture(dataTex, coord + vec2(0.0, onePixel.y * edgeSize)).r;\n float pixS = texture(dataTex, coord - vec2(0.0, onePixel.y * edgeSize)).r;\n float pixW = texture(dataTex, coord + vec2(onePixel.x * edgeSize, 0.0)).r;\n float pixE = texture(dataTex, coord - vec2(onePixel.x * edgeSize, 0.0)).r;\n\n float pixNW = texture(dataTex, coord + vec2(onePixel.y * edgeSize, onePixel.y * edgeSize)).r;\n float pixNE = texture(dataTex, coord + vec2(-1.0 * onePixel.x * edgeSize, onePixel.y * edgeSize)).r;\n float pixSW = texture(dataTex, coord - vec2(onePixel.x * edgeSize, onePixel.y * edgeSize)).r;\n float pixSE = texture(dataTex, coord - vec2(-1.0 * onePixel.x * edgeSize, onePixel.y * edgeSize)).r;\n\n isEdge = (pixN != sampledData || pixS != sampledData || pixW != sampledData || pixE != sampledData || pixNW != sampledData || pixNE != sampledData || pixSW != sampledData || pixSE != sampledData);\n }\n // Return a tuple of (sampledData, isEdge)\n return vec3(clampedSampledData * float(isOn), sampledData, float(isEdge));\n}\n\nvec3 colormapFunc(float clampedScaledExpressionValue, int colormapIndex) {\n // Map indices of GLSL_COLORMAPS array to their function calls.\n // GLSL_COLORMAPS is defined in ./constants.js and needs to stay manually synced.\n // 0: 'plasma',\n // 1: 'viridis',\n // 2: 'jet',\n // 3: 'greys',\n\n if (colormapIndex <= 0) {\n // This should also match -1, to account for a failed Array.indexOf lookup.\n return plasma(clampedScaledExpressionValue).rgb;\n }\n if (colormapIndex == 1) {\n return viridis(clampedScaledExpressionValue).rgb;\n }\n if (colormapIndex == 2) {\n return jet(clampedScaledExpressionValue).rgb;\n }\n if (colormapIndex == 3) {\n return greys(clampedScaledExpressionValue).rgb;\n }\n}\n\nvec4 dataToColor(vec3 sampledDataAndIsEdge, bool isStaticColorMode, vec3 channelColor, float channelOpacity, float valueOffset, int colormapFuncIndex, float rangeStart, float rangeEnd, bool isSetColorMode, float setColorOffset) {\n float clampedSampledDataAndIsOn = sampledDataAndIsEdge.x;\n float sampledData = sampledDataAndIsEdge.y;\n float isEdge = sampledDataAndIsEdge.z;\n \n\n vec4 hoveredColor = float(sampledData == hovered && sampledData > 0. && hovered > 0.) * vec4(0., 0., 1., 1.);\n \n // Colors are laid out corresponding to ids in row-major order in the texture. So if width of the texture is 10, and you want ID 25,\n // you need coordinate (1, 4) (i.e 2 rows down, and 5 columns over indexed from 0 for a total of 25 units covered in row major order).\n float offsetSampledData = sampledData + valueOffset - 1.0;\n vec2 colorTexCoord = vec2(mod(offsetSampledData, multiFeatureTexSize) / multiFeatureTexSize, floor(offsetSampledData / multiFeatureTexSize) / (valueTexHeight - 1.));\n\n // Get expression value\n float expressionValue = texture(valueTex, colorTexCoord).r / 255.;\n float scaledExpressionValue = (expressionValue - rangeStart) / max(0.005, (rangeEnd - rangeStart));\n\n\n // Get set color index value\n vec2 setIndicesTexCoord = vec2(mod(offsetSampledData, multiFeatureTexSize) / multiFeatureTexSize, floor(offsetSampledData / multiFeatureTexSize) / (valueTexHeight - 1.));\n float setColorIndex = texture(valueTex, setIndicesTexCoord).r;\n\n // Initialize to the default \"null\" color.\n vec3 setColor = vec3(200. / 255., 200. / 255., 200. / 255.);\n if(setColorIndex != 0.) {\n // Subtract one from setColorIndex because we have already checked for the \"null\" value.\n setColorIndex = setColorIndex - 1.;\n\n float setColorOffsetR = (setColorIndex + setColorOffset) * 3.0 + 0.0;\n vec2 setColorTexCoordR = vec2(mod(setColorOffsetR, multiFeatureTexSize) / multiFeatureTexSize, floor(setColorOffsetR / multiFeatureTexSize) / (colorTexHeight - 1.));\n float setColorR = texture(colorTex, setColorTexCoordR).r / 255.;\n\n float setColorOffsetG = (setColorIndex + setColorOffset) * 3.0 + 1.0;\n vec2 setColorTexCoordG = vec2(mod(setColorOffsetG, multiFeatureTexSize) / multiFeatureTexSize, floor(setColorOffsetG / multiFeatureTexSize) / (colorTexHeight - 1.));\n float setColorG = texture(colorTex, setColorTexCoordG).r / 255.;\n\n float setColorOffsetB = (setColorIndex + setColorOffset) * 3.0 + 2.0;\n vec2 setColorTexCoordB = vec2(mod(setColorOffsetB, multiFeatureTexSize) / multiFeatureTexSize, floor(setColorOffsetB / multiFeatureTexSize) / (colorTexHeight - 1.));\n float setColorB = texture(colorTex, setColorTexCoordB).r / 255.;\n\n setColor = vec3(setColorR, setColorG, setColorB);\n }\n\n \n vec4 sampledColor = (1. - (float(isStaticColorMode) + float(isSetColorMode))) * vec4(colormapFunc(clamp(scaledExpressionValue, 0.0, 1.0), colormapFuncIndex).rgb, channelOpacity) + float(isStaticColorMode) * vec4(channelColor.rgb, channelOpacity) + float(isSetColorMode) * vec4(setColor, channelOpacity);\n // Only return a color if the data is non-zero.\n \n return clampedSampledDataAndIsOn * isEdge * sampledColor;\n}\n\nvoid main() {\n\n // Get the color and alpha value for each channel.\n vec3 dat0 = sampleAndGetData(channel0, vTexCoord, channelsFilled[0], channelStrokeWidths[0], channelsVisible[0]);\n vec3 dat1 = sampleAndGetData(channel1, vTexCoord, channelsFilled[1], channelStrokeWidths[1], channelsVisible[1]);\n vec3 dat2 = sampleAndGetData(channel2, vTexCoord, channelsFilled[2], channelStrokeWidths[2], channelsVisible[2]);\n vec3 dat3 = sampleAndGetData(channel3, vTexCoord, channelsFilled[3], channelStrokeWidths[3], channelsVisible[3]);\n vec3 dat4 = sampleAndGetData(channel4, vTexCoord, channelsFilled[4], channelStrokeWidths[4], channelsVisible[4]);\n vec3 dat5 = sampleAndGetData(channel5, vTexCoord, channelsFilled[5], channelStrokeWidths[5], channelsVisible[5]);\n vec3 dat6 = sampleAndGetData(channel6, vTexCoord, channelsFilled[6], channelStrokeWidths[6], channelsVisible[6]);\n\n vec4 val0 = dataToColor(dat0, channelIsStaticColorMode[0], color0, channelOpacities[0], valueTexOffsets[0], channelColormapFuncIndices[0], channelColormapRangeStarts[0], channelColormapRangeEnds[0], channelIsSetColorMode[0], colorTexOffsets[0]);\n vec4 val1 = dataToColor(dat1, channelIsStaticColorMode[1], color1, channelOpacities[1], valueTexOffsets[1], channelColormapFuncIndices[1], channelColormapRangeStarts[1], channelColormapRangeEnds[1], channelIsSetColorMode[1], colorTexOffsets[1]);\n vec4 val2 = dataToColor(dat2, channelIsStaticColorMode[2], color2, channelOpacities[2], valueTexOffsets[2], channelColormapFuncIndices[2], channelColormapRangeStarts[2], channelColormapRangeEnds[2], channelIsSetColorMode[2], colorTexOffsets[2]);\n vec4 val3 = dataToColor(dat3, channelIsStaticColorMode[3], color3, channelOpacities[3], valueTexOffsets[3], channelColormapFuncIndices[3], channelColormapRangeStarts[3], channelColormapRangeEnds[3], channelIsSetColorMode[3], colorTexOffsets[3]);\n vec4 val4 = dataToColor(dat4, channelIsStaticColorMode[4], color4, channelOpacities[4], valueTexOffsets[4], channelColormapFuncIndices[4], channelColormapRangeStarts[4], channelColormapRangeEnds[4], channelIsSetColorMode[4], colorTexOffsets[4]);\n vec4 val5 = dataToColor(dat5, channelIsStaticColorMode[5], color5, channelOpacities[5], valueTexOffsets[5], channelColormapFuncIndices[5], channelColormapRangeStarts[5], channelColormapRangeEnds[5], channelIsSetColorMode[5], colorTexOffsets[5]);\n vec4 val6 = dataToColor(dat6, channelIsStaticColorMode[6], color6, channelOpacities[6], valueTexOffsets[6], channelColormapFuncIndices[6], channelColormapRangeStarts[6], channelColormapRangeEnds[6], channelIsSetColorMode[6], colorTexOffsets[6]);\n\n // If all of the channels are \"empty\", then discard this pixel so that it is not considered during picking.\n float emptyDat = 0.;\n if(dat0.x == emptyDat && dat1.x == emptyDat && dat2.x == emptyDat && dat3.x == emptyDat && dat4.x == emptyDat && dat5.x == emptyDat && dat6.x == emptyDat) {\n discard;\n }\n \n // If the next channel color and the currently stored color (gl_FragColor) are identical,\n // or the next channel color is transparent black,\n // just use the currently stored color. Repeat this for all channels.\n\n // Mix colors where necessary, using the alpha value of the next channel as the weight.\n // Use the maximum alpha value as the resulting alpha value.\n gl_FragColor = val0;\n gl_FragColor = (val1 == gl_FragColor || val1 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val1, val1.a).rgb, max(gl_FragColor.a, val1.a));\n gl_FragColor = (val2 == gl_FragColor || val2 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val2, val2.a).rgb, max(gl_FragColor.a, val2.a));\n gl_FragColor = (val3 == gl_FragColor || val3 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val3, val3.a).rgb, max(gl_FragColor.a, val3.a));\n gl_FragColor = (val4 == gl_FragColor || val4 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val4, val4.a).rgb, max(gl_FragColor.a, val4.a));\n gl_FragColor = (val5 == gl_FragColor || val5 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val5, val5.a).rgb, max(gl_FragColor.a, val5.a));\n gl_FragColor = (val6 == gl_FragColor || val6 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val6, val6.a).rgb, max(gl_FragColor.a, val6.a));\n\n \n\n // TODO: multiply the resulting channel-level opacity value by the layer-level opacity value.\n\n geometry.uv = vTexCoord;\n DECKGL_FILTER_COLOR(gl_FragColor, geometry);\n}\n";
3
3
  //# sourceMappingURL=bitmask-layer-beta-shaders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bitmask-layer-beta-shaders.d.ts","sourceRoot":"","sources":["../src/bitmask-layer-beta-shaders.js"],"names":[],"mappings":"AAEA,0mBAoBE;AAEF,kmwBA6LE"}
1
+ {"version":3,"file":"bitmask-layer-beta-shaders.d.ts","sourceRoot":"","sources":["../src/bitmask-layer-beta-shaders.js"],"names":[],"mappings":"AAEA,0mBAoBE;AAEF,kkyBAoNE"}
@@ -47,7 +47,7 @@ uniform float channelOpacities[7];
47
47
  uniform bool channelIsStaticColorMode[7]; // TODO: should this be a single float?
48
48
  uniform bool channelIsSetColorMode[7]; // TODO: should this be a single float?
49
49
 
50
- // TODO: can array of tuples/vec2 be used?
50
+ uniform int channelColormapFuncIndices[7];
51
51
  uniform float channelColormapRangeStarts[7];
52
52
  uniform float channelColormapRangeEnds[7];
53
53
 
@@ -113,7 +113,30 @@ vec3 sampleAndGetData(sampler2D dataTex, vec2 coord, bool isFilled, float stroke
113
113
  return vec3(clampedSampledData * float(isOn), sampledData, float(isEdge));
114
114
  }
115
115
 
116
- vec4 dataToColor(vec3 sampledDataAndIsEdge, bool isStaticColorMode, vec3 channelColor, float channelOpacity, float valueOffset, float rangeStart, float rangeEnd, bool isSetColorMode, float setColorOffset) {
116
+ vec3 colormapFunc(float clampedScaledExpressionValue, int colormapIndex) {
117
+ // Map indices of GLSL_COLORMAPS array to their function calls.
118
+ // GLSL_COLORMAPS is defined in ./constants.js and needs to stay manually synced.
119
+ // 0: 'plasma',
120
+ // 1: 'viridis',
121
+ // 2: 'jet',
122
+ // 3: 'greys',
123
+
124
+ if (colormapIndex <= 0) {
125
+ // This should also match -1, to account for a failed Array.indexOf lookup.
126
+ return plasma(clampedScaledExpressionValue).rgb;
127
+ }
128
+ if (colormapIndex == 1) {
129
+ return viridis(clampedScaledExpressionValue).rgb;
130
+ }
131
+ if (colormapIndex == 2) {
132
+ return jet(clampedScaledExpressionValue).rgb;
133
+ }
134
+ if (colormapIndex == 3) {
135
+ return greys(clampedScaledExpressionValue).rgb;
136
+ }
137
+ }
138
+
139
+ vec4 dataToColor(vec3 sampledDataAndIsEdge, bool isStaticColorMode, vec3 channelColor, float channelOpacity, float valueOffset, int colormapFuncIndex, float rangeStart, float rangeEnd, bool isSetColorMode, float setColorOffset) {
117
140
  float clampedSampledDataAndIsOn = sampledDataAndIsEdge.x;
118
141
  float sampledData = sampledDataAndIsEdge.y;
119
142
  float isEdge = sampledDataAndIsEdge.z;
@@ -157,7 +180,7 @@ vec4 dataToColor(vec3 sampledDataAndIsEdge, bool isStaticColorMode, vec3 channel
157
180
  }
158
181
 
159
182
 
160
- vec4 sampledColor = (1. - (float(isStaticColorMode) + float(isSetColorMode))) * vec4(COLORMAP_FUNC(clamp(scaledExpressionValue, 0.0, 1.0)).rgb, channelOpacity) + float(isStaticColorMode) * vec4(channelColor.rgb, channelOpacity) + float(isSetColorMode) * vec4(setColor, channelOpacity);
183
+ vec4 sampledColor = (1. - (float(isStaticColorMode) + float(isSetColorMode))) * vec4(colormapFunc(clamp(scaledExpressionValue, 0.0, 1.0), colormapFuncIndex).rgb, channelOpacity) + float(isStaticColorMode) * vec4(channelColor.rgb, channelOpacity) + float(isSetColorMode) * vec4(setColor, channelOpacity);
161
184
  // Only return a color if the data is non-zero.
162
185
 
163
186
  return clampedSampledDataAndIsOn * isEdge * sampledColor;
@@ -173,15 +196,15 @@ void main() {
173
196
  vec3 dat4 = sampleAndGetData(channel4, vTexCoord, channelsFilled[4], channelStrokeWidths[4], channelsVisible[4]);
174
197
  vec3 dat5 = sampleAndGetData(channel5, vTexCoord, channelsFilled[5], channelStrokeWidths[5], channelsVisible[5]);
175
198
  vec3 dat6 = sampleAndGetData(channel6, vTexCoord, channelsFilled[6], channelStrokeWidths[6], channelsVisible[6]);
176
-
177
- vec4 val0 = dataToColor(dat0, channelIsStaticColorMode[0], color0, channelOpacities[0], valueTexOffsets[0], channelColormapRangeStarts[0], channelColormapRangeEnds[0], channelIsSetColorMode[0], colorTexOffsets[0]);
178
- vec4 val1 = dataToColor(dat1, channelIsStaticColorMode[1], color1, channelOpacities[1], valueTexOffsets[1], channelColormapRangeStarts[1], channelColormapRangeEnds[1], channelIsSetColorMode[1], colorTexOffsets[1]);
179
- vec4 val2 = dataToColor(dat2, channelIsStaticColorMode[2], color2, channelOpacities[2], valueTexOffsets[2], channelColormapRangeStarts[2], channelColormapRangeEnds[2], channelIsSetColorMode[2], colorTexOffsets[2]);
180
- vec4 val3 = dataToColor(dat3, channelIsStaticColorMode[3], color3, channelOpacities[3], valueTexOffsets[3], channelColormapRangeStarts[3], channelColormapRangeEnds[3], channelIsSetColorMode[3], colorTexOffsets[3]);
181
- vec4 val4 = dataToColor(dat4, channelIsStaticColorMode[4], color4, channelOpacities[4], valueTexOffsets[4], channelColormapRangeStarts[4], channelColormapRangeEnds[4], channelIsSetColorMode[4], colorTexOffsets[4]);
182
- vec4 val5 = dataToColor(dat5, channelIsStaticColorMode[5], color5, channelOpacities[5], valueTexOffsets[5], channelColormapRangeStarts[5], channelColormapRangeEnds[5], channelIsSetColorMode[5], colorTexOffsets[5]);
183
- vec4 val6 = dataToColor(dat6, channelIsStaticColorMode[6], color6, channelOpacities[6], valueTexOffsets[6], channelColormapRangeStarts[6], channelColormapRangeEnds[6], channelIsSetColorMode[6], colorTexOffsets[6]);
184
-
199
+
200
+ vec4 val0 = dataToColor(dat0, channelIsStaticColorMode[0], color0, channelOpacities[0], valueTexOffsets[0], channelColormapFuncIndices[0], channelColormapRangeStarts[0], channelColormapRangeEnds[0], channelIsSetColorMode[0], colorTexOffsets[0]);
201
+ vec4 val1 = dataToColor(dat1, channelIsStaticColorMode[1], color1, channelOpacities[1], valueTexOffsets[1], channelColormapFuncIndices[1], channelColormapRangeStarts[1], channelColormapRangeEnds[1], channelIsSetColorMode[1], colorTexOffsets[1]);
202
+ vec4 val2 = dataToColor(dat2, channelIsStaticColorMode[2], color2, channelOpacities[2], valueTexOffsets[2], channelColormapFuncIndices[2], channelColormapRangeStarts[2], channelColormapRangeEnds[2], channelIsSetColorMode[2], colorTexOffsets[2]);
203
+ vec4 val3 = dataToColor(dat3, channelIsStaticColorMode[3], color3, channelOpacities[3], valueTexOffsets[3], channelColormapFuncIndices[3], channelColormapRangeStarts[3], channelColormapRangeEnds[3], channelIsSetColorMode[3], colorTexOffsets[3]);
204
+ vec4 val4 = dataToColor(dat4, channelIsStaticColorMode[4], color4, channelOpacities[4], valueTexOffsets[4], channelColormapFuncIndices[4], channelColormapRangeStarts[4], channelColormapRangeEnds[4], channelIsSetColorMode[4], colorTexOffsets[4]);
205
+ vec4 val5 = dataToColor(dat5, channelIsStaticColorMode[5], color5, channelOpacities[5], valueTexOffsets[5], channelColormapFuncIndices[5], channelColormapRangeStarts[5], channelColormapRangeEnds[5], channelIsSetColorMode[5], colorTexOffsets[5]);
206
+ vec4 val6 = dataToColor(dat6, channelIsStaticColorMode[6], color6, channelOpacities[6], valueTexOffsets[6], channelColormapFuncIndices[6], channelColormapRangeStarts[6], channelColormapRangeEnds[6], channelIsSetColorMode[6], colorTexOffsets[6]);
207
+
185
208
  // If all of the channels are "empty", then discard this pixel so that it is not considered during picking.
186
209
  float emptyDat = 0.;
187
210
  if(dat0.x == emptyDat && dat1.x == emptyDat && dat2.x == emptyDat && dat3.x == emptyDat && dat4.x == emptyDat && dat5.x == emptyDat && dat6.x == emptyDat) {
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.js"],"names":[],"mappings":"AAEA,sCAKE;AACF,6CAA8C;AAC9C,0DAA2D"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.js"],"names":[],"mappings":"AAEA,sCAOE;AACF,6CAA8C;AAC9C,0DAA2D"}
@@ -1,6 +1,8 @@
1
1
  // List of the GLSL colormaps available,
2
2
  // to validate against before string replacing.
3
3
  export const GLSL_COLORMAPS = [
4
+ // NOTE: the ordering of these is important,
5
+ // as the shader code in bitmask-layer-beta-shaders hardcodes their indices.
4
6
  'plasma',
5
7
  'viridis',
6
8
  'jet',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitessce/gl",
3
- "version": "3.6.17",
3
+ "version": "3.7.0",
4
4
  "author": "HIDIVE Lab at HMS",
5
5
  "homepage": "http://vitessce.io",
6
6
  "repository": {
@@ -56,8 +56,8 @@
56
56
  "math.gl": "^3.5.6",
57
57
  "mathjs": "^9.2.0",
58
58
  "nebula.gl": "0.23.8",
59
- "@vitessce/utils": "3.6.17",
60
- "@vitessce/globals": "3.6.17"
59
+ "@vitessce/utils": "3.7.0",
60
+ "@vitessce/globals": "3.7.0"
61
61
  },
62
62
  "devDependencies": {
63
63
  "glsl-colormap": "^1.0.1",
@@ -65,7 +65,7 @@
65
65
  "react-dom": "^18.0.0"
66
66
  },
67
67
  "scripts": {
68
- "bundle": "pnpm exec vite build -c ../../scripts/vite.config.js",
68
+ "bundle": "pnpm exec vite build -c ../../scripts/vite.config.mjs",
69
69
  "test": "pnpm exec vitest --run",
70
70
  "glslify": "cat src/glsl/colormaps.in.glsl | glslify > src/glsl/colormaps.out.glsl"
71
71
  },
@@ -69,16 +69,10 @@ const defaultProps = {
69
69
  export default class BitmaskLayer extends XRLayer {
70
70
  // eslint-disable-next-line class-methods-use-this
71
71
  getShaders() {
72
- const { colormap } = this.props;
73
72
  return {
74
73
  fs,
75
74
  vs,
76
75
  modules: [project32, picking],
77
- defines: {
78
- [COLORMAP_SHADER_PLACEHOLDER]: GLSL_COLORMAPS.includes(colormap)
79
- ? colormap
80
- : GLSL_COLORMAP_DEFAULT,
81
- },
82
76
  };
83
77
  }
84
78
 
@@ -170,8 +164,6 @@ export default class BitmaskLayer extends XRLayer {
170
164
  channelOpacities,
171
165
  channelColors,
172
166
  channelsVisible,
173
- // TODO: use `channelFeatureValueColormaps` in shader,
174
- // figure out how to call multiple GLSL colormap functions
175
167
  channelFeatureValueColormaps,
176
168
  channelFeatureValueColormapRanges,
177
169
  channelIsStaticColorMode,
@@ -242,6 +234,12 @@ export default class BitmaskLayer extends XRLayer {
242
234
  // There are six texture entries on the shaders
243
235
  MAX_CHANNELS - channelStrokeWidths.length,
244
236
  ),
237
+ channelColormapFuncIndices: padWithDefault(
238
+ channelFeatureValueColormaps.map(d => GLSL_COLORMAPS.indexOf(d)),
239
+ 0,
240
+ // There are six texture entries on the shaders
241
+ MAX_CHANNELS - channelFeatureValueColormaps.length,
242
+ ),
245
243
  channelColormapRangeStarts: padWithDefault(
246
244
  channelFeatureValueColormapRanges.map(r => r?.[0] || 0.0),
247
245
  0.0,
@@ -49,7 +49,7 @@ uniform float channelOpacities[7];
49
49
  uniform bool channelIsStaticColorMode[7]; // TODO: should this be a single float?
50
50
  uniform bool channelIsSetColorMode[7]; // TODO: should this be a single float?
51
51
 
52
- // TODO: can array of tuples/vec2 be used?
52
+ uniform int channelColormapFuncIndices[7];
53
53
  uniform float channelColormapRangeStarts[7];
54
54
  uniform float channelColormapRangeEnds[7];
55
55
 
@@ -115,7 +115,30 @@ vec3 sampleAndGetData(sampler2D dataTex, vec2 coord, bool isFilled, float stroke
115
115
  return vec3(clampedSampledData * float(isOn), sampledData, float(isEdge));
116
116
  }
117
117
 
118
- vec4 dataToColor(vec3 sampledDataAndIsEdge, bool isStaticColorMode, vec3 channelColor, float channelOpacity, float valueOffset, float rangeStart, float rangeEnd, bool isSetColorMode, float setColorOffset) {
118
+ vec3 colormapFunc(float clampedScaledExpressionValue, int colormapIndex) {
119
+ // Map indices of GLSL_COLORMAPS array to their function calls.
120
+ // GLSL_COLORMAPS is defined in ./constants.js and needs to stay manually synced.
121
+ // 0: 'plasma',
122
+ // 1: 'viridis',
123
+ // 2: 'jet',
124
+ // 3: 'greys',
125
+
126
+ if (colormapIndex <= 0) {
127
+ // This should also match -1, to account for a failed Array.indexOf lookup.
128
+ return plasma(clampedScaledExpressionValue).rgb;
129
+ }
130
+ if (colormapIndex == 1) {
131
+ return viridis(clampedScaledExpressionValue).rgb;
132
+ }
133
+ if (colormapIndex == 2) {
134
+ return jet(clampedScaledExpressionValue).rgb;
135
+ }
136
+ if (colormapIndex == 3) {
137
+ return greys(clampedScaledExpressionValue).rgb;
138
+ }
139
+ }
140
+
141
+ vec4 dataToColor(vec3 sampledDataAndIsEdge, bool isStaticColorMode, vec3 channelColor, float channelOpacity, float valueOffset, int colormapFuncIndex, float rangeStart, float rangeEnd, bool isSetColorMode, float setColorOffset) {
119
142
  float clampedSampledDataAndIsOn = sampledDataAndIsEdge.x;
120
143
  float sampledData = sampledDataAndIsEdge.y;
121
144
  float isEdge = sampledDataAndIsEdge.z;
@@ -159,7 +182,7 @@ vec4 dataToColor(vec3 sampledDataAndIsEdge, bool isStaticColorMode, vec3 channel
159
182
  }
160
183
 
161
184
 
162
- vec4 sampledColor = (1. - (float(isStaticColorMode) + float(isSetColorMode))) * vec4(COLORMAP_FUNC(clamp(scaledExpressionValue, 0.0, 1.0)).rgb, channelOpacity) + float(isStaticColorMode) * vec4(channelColor.rgb, channelOpacity) + float(isSetColorMode) * vec4(setColor, channelOpacity);
185
+ vec4 sampledColor = (1. - (float(isStaticColorMode) + float(isSetColorMode))) * vec4(colormapFunc(clamp(scaledExpressionValue, 0.0, 1.0), colormapFuncIndex).rgb, channelOpacity) + float(isStaticColorMode) * vec4(channelColor.rgb, channelOpacity) + float(isSetColorMode) * vec4(setColor, channelOpacity);
163
186
  // Only return a color if the data is non-zero.
164
187
 
165
188
  return clampedSampledDataAndIsOn * isEdge * sampledColor;
@@ -175,15 +198,15 @@ void main() {
175
198
  vec3 dat4 = sampleAndGetData(channel4, vTexCoord, channelsFilled[4], channelStrokeWidths[4], channelsVisible[4]);
176
199
  vec3 dat5 = sampleAndGetData(channel5, vTexCoord, channelsFilled[5], channelStrokeWidths[5], channelsVisible[5]);
177
200
  vec3 dat6 = sampleAndGetData(channel6, vTexCoord, channelsFilled[6], channelStrokeWidths[6], channelsVisible[6]);
178
-
179
- vec4 val0 = dataToColor(dat0, channelIsStaticColorMode[0], color0, channelOpacities[0], valueTexOffsets[0], channelColormapRangeStarts[0], channelColormapRangeEnds[0], channelIsSetColorMode[0], colorTexOffsets[0]);
180
- vec4 val1 = dataToColor(dat1, channelIsStaticColorMode[1], color1, channelOpacities[1], valueTexOffsets[1], channelColormapRangeStarts[1], channelColormapRangeEnds[1], channelIsSetColorMode[1], colorTexOffsets[1]);
181
- vec4 val2 = dataToColor(dat2, channelIsStaticColorMode[2], color2, channelOpacities[2], valueTexOffsets[2], channelColormapRangeStarts[2], channelColormapRangeEnds[2], channelIsSetColorMode[2], colorTexOffsets[2]);
182
- vec4 val3 = dataToColor(dat3, channelIsStaticColorMode[3], color3, channelOpacities[3], valueTexOffsets[3], channelColormapRangeStarts[3], channelColormapRangeEnds[3], channelIsSetColorMode[3], colorTexOffsets[3]);
183
- vec4 val4 = dataToColor(dat4, channelIsStaticColorMode[4], color4, channelOpacities[4], valueTexOffsets[4], channelColormapRangeStarts[4], channelColormapRangeEnds[4], channelIsSetColorMode[4], colorTexOffsets[4]);
184
- vec4 val5 = dataToColor(dat5, channelIsStaticColorMode[5], color5, channelOpacities[5], valueTexOffsets[5], channelColormapRangeStarts[5], channelColormapRangeEnds[5], channelIsSetColorMode[5], colorTexOffsets[5]);
185
- vec4 val6 = dataToColor(dat6, channelIsStaticColorMode[6], color6, channelOpacities[6], valueTexOffsets[6], channelColormapRangeStarts[6], channelColormapRangeEnds[6], channelIsSetColorMode[6], colorTexOffsets[6]);
186
-
201
+
202
+ vec4 val0 = dataToColor(dat0, channelIsStaticColorMode[0], color0, channelOpacities[0], valueTexOffsets[0], channelColormapFuncIndices[0], channelColormapRangeStarts[0], channelColormapRangeEnds[0], channelIsSetColorMode[0], colorTexOffsets[0]);
203
+ vec4 val1 = dataToColor(dat1, channelIsStaticColorMode[1], color1, channelOpacities[1], valueTexOffsets[1], channelColormapFuncIndices[1], channelColormapRangeStarts[1], channelColormapRangeEnds[1], channelIsSetColorMode[1], colorTexOffsets[1]);
204
+ vec4 val2 = dataToColor(dat2, channelIsStaticColorMode[2], color2, channelOpacities[2], valueTexOffsets[2], channelColormapFuncIndices[2], channelColormapRangeStarts[2], channelColormapRangeEnds[2], channelIsSetColorMode[2], colorTexOffsets[2]);
205
+ vec4 val3 = dataToColor(dat3, channelIsStaticColorMode[3], color3, channelOpacities[3], valueTexOffsets[3], channelColormapFuncIndices[3], channelColormapRangeStarts[3], channelColormapRangeEnds[3], channelIsSetColorMode[3], colorTexOffsets[3]);
206
+ vec4 val4 = dataToColor(dat4, channelIsStaticColorMode[4], color4, channelOpacities[4], valueTexOffsets[4], channelColormapFuncIndices[4], channelColormapRangeStarts[4], channelColormapRangeEnds[4], channelIsSetColorMode[4], colorTexOffsets[4]);
207
+ vec4 val5 = dataToColor(dat5, channelIsStaticColorMode[5], color5, channelOpacities[5], valueTexOffsets[5], channelColormapFuncIndices[5], channelColormapRangeStarts[5], channelColormapRangeEnds[5], channelIsSetColorMode[5], colorTexOffsets[5]);
208
+ vec4 val6 = dataToColor(dat6, channelIsStaticColorMode[6], color6, channelOpacities[6], valueTexOffsets[6], channelColormapFuncIndices[6], channelColormapRangeStarts[6], channelColormapRangeEnds[6], channelIsSetColorMode[6], colorTexOffsets[6]);
209
+
187
210
  // If all of the channels are "empty", then discard this pixel so that it is not considered during picking.
188
211
  float emptyDat = 0.;
189
212
  if(dat0.x == emptyDat && dat1.x == emptyDat && dat2.x == emptyDat && dat3.x == emptyDat && dat4.x == emptyDat && dat5.x == emptyDat && dat6.x == emptyDat) {
package/src/constants.js CHANGED
@@ -1,6 +1,8 @@
1
1
  // List of the GLSL colormaps available,
2
2
  // to validate against before string replacing.
3
3
  export const GLSL_COLORMAPS = [
4
+ // NOTE: the ordering of these is important,
5
+ // as the shader code in bitmask-layer-beta-shaders hardcodes their indices.
4
6
  'plasma',
5
7
  'viridis',
6
8
  'jet',