Skip to content

Commit

Permalink
GPU Aggregation (6/8): HexagonLayer (#9098)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pessimistress authored Aug 23, 2024
1 parent fdbb88a commit 427a95b
Show file tree
Hide file tree
Showing 12 changed files with 967 additions and 1,283 deletions.
7 changes: 5 additions & 2 deletions examples/website/3d-heatmap/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function getTooltip({object}: PickingInfo) {
}
const lat = object.position[1];
const lng = object.position[0];
const count = object.points.length;
const count = object.count;

return `\
latitude: ${Number.isFinite(lat) ? lat.toFixed(6) : ''}
Expand All @@ -85,6 +85,7 @@ export default function App({
const layers = [
new HexagonLayer<DataPoint>({
id: 'heatmap',
// gpuAggregation: true,
colorRange,
coverage,
data,
Expand Down Expand Up @@ -126,6 +127,8 @@ export async function renderToDOM(container: HTMLDivElement) {
root.render(<App />);

const data = (await load(DATA_URL, CSVLoader)).data;
const points: DataPoint[] = data.map(d => [d.lng, d.lat]);
const points: DataPoint[] = data
.map(d => (Number.isFinite(d.lng) ? [d.lng, d.lat] : null))
.filter(Boolean);
root.render(<App data={points} />);
}
127 changes: 0 additions & 127 deletions modules/aggregation-layers/src/hexagon-layer/hexagon-aggregator.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// deck.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors

import {getHexbinCentroidGLSL} from './hexbin';

export default /* glsl */ `\
#version 300 es
#define SHADER_NAME hexagon-cell-layer-vertex-shader
in vec3 positions;
in vec3 normals;
in vec2 instancePositions;
in float instanceElevationValues;
in float instanceColorValues;
in vec3 instancePickingColors;
// Custom uniforms
uniform float opacity;
uniform bool extruded;
uniform float coverage;
uniform float radius;
uniform vec2 hexOriginCommon;
uniform vec2 colorDomain;
uniform sampler2D colorRange;
uniform vec2 elevationDomain;
uniform vec2 elevationRange;
// Result
out vec4 vColor;
${getHexbinCentroidGLSL}
float interp(float value, vec2 domain, vec2 range) {
float r = min(max((value - domain.x) / (domain.y - domain.x), 0.), 1.);
return mix(range.x, range.y, r);
}
vec4 interp(float value, vec2 domain, sampler2D range) {
float r = min(max((value - domain.x) / (domain.y - domain.x), 0.), 1.);
return texture(range, vec2(r, 0.5));
}
void main(void) {
geometry.pickingColor = instancePickingColors;
if (isnan(instanceColorValues)) {
gl_Position = vec4(0.);
return;
}
vec2 commonPosition = hexbinCentroid(instancePositions, radius) + (hexOriginCommon - project.commonOrigin.xy);
commonPosition += positions.xy * radius * coverage;
geometry.position = vec4(commonPosition, 0.0, 1.0);
geometry.normal = project_normal(normals);
// calculate z, if 3d not enabled set to 0
float elevation = 0.0;
if (extruded) {
elevation = interp(instanceElevationValues, elevationDomain, elevationRange);
elevation = project_size(elevation);
// cylindar gemoetry height are between -1.0 to 1.0, transform it to between 0, 1
geometry.position.z = (positions.z + 1.0) / 2.0 * elevation;
}
gl_Position = project_common_position_to_clipspace(geometry.position);
DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
vColor = interp(instanceColorValues, colorDomain, colorRange);
vColor.a *= opacity;
if (extruded) {
vColor.rgb = lighting_getLightColor(vColor.rgb, project.cameraPosition, geometry.position.xyz, geometry.normal);
}
DECKGL_FILTER_COLOR(vColor, geometry);
}
`;
111 changes: 111 additions & 0 deletions modules/aggregation-layers/src/hexagon-layer/hexagon-cell-layer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// deck.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors

import {Texture} from '@luma.gl/core';
import {UpdateParameters, Color} from '@deck.gl/core';
import {ColumnLayer} from '@deck.gl/layers';
import {colorRangeToTexture} from '../utils/color-utils';
import vs from './hexagon-cell-layer-vertex.glsl';

/** Proprties added by HexagonCellLayer. */
export type _HexagonCellLayerProps = {
hexOriginCommon: [number, number];
colorDomain: () => [number, number];
colorRange?: Color[];
elevationDomain: () => [number, number];
elevationRange: [number, number];
};

export default class HexagonCellLayer<ExtraPropsT extends {} = {}> extends ColumnLayer<
null,
ExtraPropsT & Required<_HexagonCellLayerProps>
> {
static layerName = 'HexagonCellLayer';

state!: ColumnLayer['state'] & {
colorTexture: Texture;
};

getShaders() {
return {
...super.getShaders(),
vs
};
}

initializeState() {
super.initializeState();

const attributeManager = this.getAttributeManager()!;
attributeManager.remove([
'instanceElevations',
'instanceFillColors',
'instanceLineColors',
'instanceStrokeWidths'
]);
attributeManager.addInstanced({
instancePositions: {
size: 2,
type: 'float32',
accessor: 'getBin'
},
instanceColorValues: {
size: 1,
type: 'float32',
accessor: 'getColorValue'
},
instanceElevationValues: {
size: 1,
type: 'float32',
accessor: 'getElevationValue'
}
});
}

updateState(params: UpdateParameters<this>) {
super.updateState(params);

const {props, oldProps} = params;
const model = this.state.fillModel!;

if (oldProps.colorRange !== props.colorRange) {
this.state.colorTexture?.destroy();
this.state.colorTexture = colorRangeToTexture(this.context.device, props.colorRange);
model.setBindings({colorRange: this.state.colorTexture});
}
}

finalizeState(context) {
super.finalizeState(context);

this.state.colorTexture?.destroy();
}

draw({uniforms}) {
// Use dynamic domain from the aggregator
const colorDomain = this.props.colorDomain();
const elevationDomain = this.props.elevationDomain();
const {radius, hexOriginCommon, elevationRange, elevationScale, extruded, coverage} =
this.props;
const fillModel = this.state.fillModel!;

if (fillModel.vertexArray.indexBuffer) {
// indices are for drawing wireframe, disable them
// TODO - this should be handled in ColumnLayer?
fillModel.setIndexBuffer(null);
}
fillModel.setVertexCount(this.state.fillVertexCount);
fillModel.setUniforms(uniforms);
fillModel.setUniforms({
extruded,
coverage,
colorDomain,
elevationDomain,
radius,
hexOriginCommon,
elevationRange: [elevationRange[0] * elevationScale, elevationRange[1] * elevationScale]
});
fillModel.draw(this.context.renderPass);
}
}
Loading

0 comments on commit 427a95b

Please sign in to comment.