Skip to content

Commit e9ec48e

Browse files
author
Shaojing Li
committed
More 64-bit layers (visgl#387)
* Add 64-bit support for IconLayer, HexagonLayer, GridLayer, PointDensityHexagonLayer and PointDensityGridLayer; * Fix a bug in vertex shader of the 64-bit ScatterplotLayer * UpdateModel needs to called before updateUniforms * Address review comments
1 parent 194bd0e commit e9ec48e

17 files changed

Lines changed: 446 additions & 78 deletions

File tree

src/layers/core/arc-layer/arc-layer.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,6 @@ export default class ArcLayer extends Layer {
6161
instanceSourceColors: {size: 4, type: GL.UNSIGNED_BYTE, accessor: 'getSourceColor', update: this.calculateInstanceSourceColors},
6262
instanceTargetColors: {size: 4, type: GL.UNSIGNED_BYTE, accessor: 'getTargetColor', update: this.calculateInstanceTargetColors}
6363
});
64-
65-
if (this.props.fp64) {
66-
this.state.attributeManager.addInstanced({
67-
instancePositions64Low: {size: 4, accessor: ['getSourcePosition', 'getTargetPosition'], update: this.calculateInstancePositions64Low}
68-
});
69-
}
7064
/* eslint-enable max-len */
7165
}
7266

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Inspired by screen-grid-layer vertex shader in deck.gl
2+
3+
/* vertex shader for the grid-layer */
4+
#define SHADER_NAME grid-layer-vs
5+
6+
attribute vec3 positions;
7+
attribute vec3 normals;
8+
9+
attribute vec4 instancePositions;
10+
attribute vec2 instancePositions64xyLow;
11+
attribute vec4 instanceColors;
12+
attribute vec3 instancePickingColors;
13+
14+
// Picking uniforms
15+
// Set to 1.0 if rendering picking buffer, 0.0 if rendering for display
16+
uniform float renderPickingBuffer;
17+
uniform vec3 selectedPickingColor;
18+
19+
// Custom uniforms
20+
uniform float extruded;
21+
uniform float lonOffset;
22+
uniform float latOffset;
23+
uniform float opacity;
24+
uniform float elevationScale;
25+
26+
// A magic number to scale elevation so that 1 unit approximate to 1 meter
27+
#define ELEVATION_SCALE 0.8
28+
29+
// Result
30+
varying vec4 vColor;
31+
32+
float isPicked(vec3 pickingColors, vec3 selectedColor) {
33+
return float(pickingColors.x == selectedColor.x
34+
&& pickingColors.y == selectedColor.y
35+
&& pickingColors.z == selectedColor.z);
36+
}
37+
38+
39+
void main(void) {
40+
41+
// vec2 instancePositions64x = vec2(instancePositions.x, instancePositions64xyLow.x);
42+
// vec2 instancePositions64y = vec2(instancePositions.y, instancePositions64xyLow.y);
43+
// vec2 offsetInstancePosition64x = sum_fp64(instancePositions64x, vec2((positions.x + 1.0 ) * lonOffset / 2.0, 0.0));
44+
// vec2 offsetInstancePosition64y = sum_fp64(instancePositions64y, vec2((positions.y + 1.0 ) * latOffset / 2.0, 0.0));
45+
vec4 instancePositions64xy = vec4(instancePositions.x + (positions.x + 1.0) * lonOffset / 2.0, instancePositions64xyLow.x, instancePositions.y + (positions.y + 1.0) * latOffset / 2.0, instancePositions64xyLow.y);
46+
47+
vec2 projected_coord_xy[2];
48+
project_position_fp64(instancePositions64xy, projected_coord_xy);
49+
50+
float elevation = 0.0;
51+
52+
if (extruded > 0.5) {
53+
elevation = project_scale(instancePositions.w * (positions.z + 1.0) * ELEVATION_SCALE * elevationScale) + 1.0;
54+
}
55+
56+
vec2 vertex_pos_modelspace[4];
57+
vertex_pos_modelspace[0] = projected_coord_xy[0];
58+
vertex_pos_modelspace[1] = projected_coord_xy[1];
59+
vertex_pos_modelspace[2] = vec2(elevation, 0.0);
60+
vertex_pos_modelspace[3] = vec2(1.0, 0.0);
61+
62+
vec4 position_worldspace = vec4(vertex_pos_modelspace[0].x, vertex_pos_modelspace[1].x, vertex_pos_modelspace[2].x, vertex_pos_modelspace[3].x);
63+
64+
gl_Position = project_to_clipspace_fp64(vertex_pos_modelspace);
65+
66+
if (renderPickingBuffer < 0.5) {
67+
68+
// TODO: we should allow the user to specify the color for "selected element"
69+
// check whether a bar is currently picked.
70+
float selected = isPicked(instancePickingColors, selectedPickingColor);
71+
72+
float lightWeight = 1.0;
73+
74+
if (extruded > 0.5) {
75+
lightWeight = getLightWeight(
76+
position_worldspace,
77+
normals
78+
);
79+
}
80+
81+
vec3 lightWeightedColor = lightWeight * instanceColors.rgb;
82+
vec4 color = vec4(lightWeightedColor, instanceColors.a * opacity) / 255.0;
83+
vColor = color;
84+
85+
} else {
86+
87+
vec4 pickingColor = vec4(instancePickingColors / 255.0, 1.0);
88+
vColor = pickingColor;
89+
90+
}
91+
}

src/layers/core/grid-layer/grid-layer-vertex.glsl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ uniform float elevationScale;
2828
// Result
2929
varying vec4 vColor;
3030

31+
// whether is point picked
32+
float isPicked(vec3 pickingColors, vec3 selectedColor) {
33+
return float(pickingColors.x == selectedColor.x
34+
&& pickingColors.y == selectedColor.y
35+
&& pickingColors.z == selectedColor.z);
36+
}
37+
3138
void main(void) {
3239

3340
// cube gemoetry vertics are between -1 to 1, scale and transform it to between 0, 1

src/layers/core/grid-layer/grid-layer.js

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {assembleShaders} from '../../../shader-utils';
2323
import {GL, Model, CubeGeometry} from 'luma.gl';
2424
import {readFileSync} from 'fs';
2525
import {join} from 'path';
26+
import {fp64ify} from '../../../lib/utils/fp64';
2627

2728
const DEFAULT_COLOR = [255, 0, 255, 255];
2829

@@ -41,7 +42,8 @@ const defaultProps = {
4142
specularRatio: 0.8,
4243
lightsStrength: [1.0, 0.0, 0.8, 0.0],
4344
numberOfLights: 2
44-
}
45+
},
46+
fp64: false
4547
};
4648

4749
export default class GridLayer extends Layer {
@@ -60,20 +62,20 @@ export default class GridLayer extends Layer {
6062
*/
6163

6264
getShaders() {
63-
const vertex = readFileSync(join(__dirname, './grid-layer-vertex.glsl'), 'utf8');
64-
const picking = readFileSync(join(__dirname, './picking.glsl'), 'utf8');
65-
const vs = picking.concat(vertex);
66-
67-
return {
68-
vs,
65+
return this.props.fp64 ? {
66+
vs: readFileSync(join(__dirname, './grid-layer-64-vertex.glsl'), 'utf8'),
67+
fs: readFileSync(join(__dirname, './grid-layer-fragment.glsl'), 'utf8'),
68+
modules: ['fp64', 'project64', 'lighting']
69+
} : {
70+
vs: readFileSync(join(__dirname, './grid-layer-vertex.glsl'), 'utf8'),
6971
fs: readFileSync(join(__dirname, './grid-layer-fragment.glsl'), 'utf8'),
7072
modules: ['lighting']
7173
};
7274
}
7375

7476
initializeState() {
7577
const {gl} = this.context;
76-
this.setState({model: this._createModel(gl)});
78+
this.setState({model: this._getModel(gl)});
7779

7880
const {attributeManager} = this.state;
7981
/* eslint-disable max-len */
@@ -84,12 +86,36 @@ export default class GridLayer extends Layer {
8486
/* eslint-enable max-len */
8587
}
8688

87-
updateState(opt) {
88-
super.updateState(opt);
89+
updateAttribute({props, oldProps, changeFlags}) {
90+
if (props.fp64 !== oldProps.fp64) {
91+
const {attributeManager} = this.state;
92+
attributeManager.invalidateAll();
93+
94+
if (props.fp64 === true) {
95+
attributeManager.addInstanced({
96+
instancePositions64xyLow: {
97+
size: 2,
98+
accessor: 'getPosition',
99+
update: this.calculateInstancePositions64xyLow
100+
}
101+
});
102+
} else {
103+
attributeManager.remove([
104+
'instancePositions64xyLow'
105+
]);
106+
}
107+
108+
}
109+
}
110+
111+
updateState({props, oldProps, changeFlags}) {
112+
super.updateState({props, oldProps, changeFlags});
113+
this.updateModel({props, oldProps, changeFlags});
114+
this.updateAttribute({props, oldProps, changeFlags});
89115
this.updateUniforms();
90116
}
91117

92-
_createModel(gl) {
118+
_getModel(gl) {
93119
const geometry = new CubeGeometry({});
94120
const shaders = assembleShaders(gl, this.getShaders());
95121

@@ -135,6 +161,17 @@ export default class GridLayer extends Layer {
135161
}
136162
}
137163

164+
calculateInstancePositions64xyLow(attribute) {
165+
const {data, getPosition} = this.props;
166+
const {value} = attribute;
167+
let i = 0;
168+
for (const point of data) {
169+
const position = getPosition(point);
170+
value[i++] = fp64ify(position[0])[1];
171+
value[i++] = fp64ify(position[1])[1];
172+
}
173+
}
174+
138175
calculateInstanceColors(attribute) {
139176
const {data, getColor} = this.props;
140177
const {value, size} = attribute;

src/layers/core/grid-layer/picking.glsl

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#define SHADER_NAME extruded-hexagon-layer-vs
2+
3+
attribute vec3 positions;
4+
attribute vec3 normals;
5+
6+
attribute vec3 instancePositions;
7+
attribute vec2 instancePositions64xyLow;
8+
attribute vec4 instanceColors;
9+
attribute vec3 instancePickingColors;
10+
11+
// Picking uniforms
12+
// Set to 1.0 if rendering picking buffer, 0.0 if rendering for display
13+
uniform float renderPickingBuffer;
14+
uniform vec3 selectedPickingColor;
15+
16+
// Custom uniforms
17+
uniform float opacity;
18+
uniform float radius;
19+
uniform float angle;
20+
uniform float extruded;
21+
uniform float coverage;
22+
uniform float elevationScale;
23+
24+
// Result
25+
varying vec4 vColor;
26+
27+
// A magic number to scale elevation so that 1 unit approximate to 1 meter.
28+
#define ELEVATION_SCALE 0.8
29+
30+
float isPicked(vec3 pickingColors, vec3 selectedColor) {
31+
return float(pickingColors.x == selectedColor.x
32+
&& pickingColors.y == selectedColor.y
33+
&& pickingColors.z == selectedColor.z);
34+
}
35+
36+
void main(void) {
37+
38+
// rotate primitive position and normal
39+
mat2 rotationMatrix = mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
40+
41+
vec2 rPos = rotationMatrix * positions.xz;
42+
vec2 rNorm = rotationMatrix * normals.xz;
43+
44+
vec3 rotatedPositions = vec3(rPos.x, positions.y, rPos.y);
45+
vec3 rotatedNormals = vec3(rNorm.x, normals.y, rNorm.y);
46+
47+
// calculate elevation, if 3d not enabled set to 0
48+
// cylindar gemoetry height are between -0.5 to 0.5, transform it to between 0, 1
49+
float elevation = 0.0;
50+
51+
if (extruded > 0.5) {
52+
elevation = project_scale(instancePositions.z * (positions.y + 0.5) * ELEVATION_SCALE * elevationScale);
53+
}
54+
55+
float dotRadius = radius * clamp(coverage, 0.0, 1.0);
56+
// // project center of hexagon
57+
58+
// vec4 centroidPosition = vec4(project_position(instancePositions.xy), elevation, 0.0);
59+
// vec4 position_worldspace = centroidPosition + vec4(vec2(rotatedPositions.xz * dotRadius), 0., 1.);
60+
// gl_Position = project_to_clipspace(position_worldspace);
61+
62+
vec4 instancePositions64xy = vec4(instancePositions.x, instancePositions64xyLow.x, instancePositions.y, instancePositions64xyLow.y);
63+
vec2 projected_coord_xy[2];
64+
project_position_fp64(instancePositions64xy, projected_coord_xy);
65+
66+
vec2 vertex_pos_localspace[4];
67+
vec4_fp64(vec4(rotatedPositions.xz * dotRadius, 0.0, 1.0), vertex_pos_localspace);
68+
69+
vec2 vertex_pos_modelspace[4];
70+
vertex_pos_modelspace[0] = sum_fp64(vertex_pos_localspace[0], projected_coord_xy[0]);
71+
vertex_pos_modelspace[1] = sum_fp64(vertex_pos_localspace[1], projected_coord_xy[1]);
72+
vertex_pos_modelspace[2] = sum_fp64(vertex_pos_localspace[2], vec2(elevation, 0.0));
73+
vertex_pos_modelspace[3] = vec2(1.0, 0.0);
74+
75+
vec4 position_worldspace = vec4(vertex_pos_modelspace[0].x, vertex_pos_modelspace[1].x, vertex_pos_modelspace[2].x, vertex_pos_modelspace[3].x);
76+
77+
gl_Position = project_to_clipspace_fp64(vertex_pos_modelspace);
78+
79+
// render display
80+
if (renderPickingBuffer < 0.5) {
81+
82+
// TODO: we should allow the user to specify the color for "selected element"
83+
// check whether hexagon is currently picked.
84+
float selected = isPicked(instancePickingColors, selectedPickingColor);
85+
86+
// Light calculations
87+
// Worldspace is the linear space after Mercator projection
88+
89+
vec3 normals_worldspace = rotatedNormals;
90+
91+
float lightWeight = 1.0;
92+
93+
if (extruded > 0.5) {
94+
lightWeight = getLightWeight(
95+
position_worldspace,
96+
normals_worldspace
97+
);
98+
}
99+
100+
vec3 lightWeightedColor = lightWeight * instanceColors.rgb;
101+
102+
// Color: Either opacity-multiplied instance color, or picking color
103+
vec4 color = vec4(lightWeightedColor, opacity * instanceColors.a) / 255.0;
104+
105+
vColor = color;
106+
107+
} else {
108+
109+
vec4 pickingColor = vec4(instancePickingColors / 255.0, 1.0);
110+
vColor = pickingColor;
111+
112+
}
113+
}

src/layers/core/hexagon-layer/hexagon-layer-vertex.glsl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ varying vec4 vColor;
2626
// A magic number to scale elevation so that 1 unit approximate to 1 meter.
2727
#define ELEVATION_SCALE 0.8
2828

29+
// whether is point picked
30+
float isPicked(vec3 pickingColors, vec3 selectedColor) {
31+
return float(pickingColors.x == selectedColor.x
32+
&& pickingColors.y == selectedColor.y
33+
&& pickingColors.z == selectedColor.z);
34+
}
2935

3036
void main(void) {
3137

0 commit comments

Comments
 (0)