@deck.gl/experimental-layers
Version:
Experimental layers for deck.gl
193 lines (173 loc) • 4.85 kB
JavaScript
import { Layer } from '@deck.gl/core';
import { Model, Geometry } from 'luma.gl';
import tripsVertex from './trips-layer-vertex.glsl';
import tripsFragment from './trips-layer-fragment.glsl';
const defaultProps = {
trailLength: {
type: 'number',
value: 120,
min: 0
},
currentTime: {
type: 'number',
value: 0,
min: 0
},
getPath: {
type: 'accessor',
value: d => d.path
},
getColor: {
type: 'accessor',
value: d => d.color
}
};
export default class TripsLayer extends Layer {
initializeState() {
const gl = this.context.gl;
const attributeManager = this.getAttributeManager();
const model = this.getModel(gl);
attributeManager.add({
indices: {
size: 1,
update: this.calculateIndices,
isIndexed: true
},
positions: {
size: 3,
update: this.calculatePositions
},
colors: {
size: 3,
accessor: 'getColor',
update: this.calculateColors
}
});
gl.getExtension('OES_element_index_uint');
this.setState({
model
});
}
updateState(_ref) {
let props = _ref.props,
dataChanged = _ref.changeFlags.dataChanged;
if (dataChanged) {
this.countVertices(props.data);
this.state.attributeManager.invalidateAll();
}
}
getModel(gl) {
return new Model(gl, {
id: this.props.id,
vs: tripsVertex,
fs: tripsFragment,
geometry: new Geometry({
id: this.props.id,
drawMode: 'LINES'
}),
vertexCount: 0,
isIndexed: true,
// TODO-state-management: onBeforeRender can go to settings, onAfterRender, we should
// move this settings of corresponding draw.
onBeforeRender: () => {
gl.enable(gl.BLEND);
gl.enable(gl.POLYGON_OFFSET_FILL);
gl.polygonOffset(2.0, 1.0);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
gl.blendEquation(gl.FUNC_ADD);
},
onAfterRender: () => {
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.disable(gl.POLYGON_OFFSET_FILL);
}
});
}
countVertices(data) {
if (!data) {
return;
}
const getPath = this.props.getPath;
let vertexCount = 0;
const pathLengths = data.reduce((acc, d) => {
const l = getPath(d).length;
vertexCount += l;
return [...acc, l];
}, []);
this.setState({
pathLengths,
vertexCount
});
}
draw(_ref2) {
let uniforms = _ref2.uniforms;
const _this$props = this.props,
trailLength = _this$props.trailLength,
currentTime = _this$props.currentTime;
this.state.model.render(Object.assign({}, uniforms, {
trailLength,
currentTime
}));
}
calculateIndices(attribute) {
const _this$state = this.state,
pathLengths = _this$state.pathLengths,
vertexCount = _this$state.vertexCount;
const indicesCount = (vertexCount - pathLengths.length) * 2;
const indices = new Uint32Array(indicesCount);
let offset = 0;
let index = 0;
for (let i = 0; i < pathLengths.length; i++) {
const l = pathLengths[i];
indices[index++] = offset;
for (let j = 1; j < l - 1; j++) {
indices[index++] = j + offset;
indices[index++] = j + offset;
}
indices[index++] = offset + l - 1;
offset += l;
}
attribute.value = indices;
this.state.model.setVertexCount(indicesCount);
}
calculatePositions(attribute) {
const _this$props2 = this.props,
data = _this$props2.data,
getPath = _this$props2.getPath;
const vertexCount = this.state.vertexCount;
const positions = new Float32Array(vertexCount * 3);
let index = 0;
for (let i = 0; i < data.length; i++) {
const path = getPath(data[i]);
for (let j = 0; j < path.length; j++) {
const pt = path[j];
positions[index++] = pt[0];
positions[index++] = pt[1];
positions[index++] = pt[2];
}
}
attribute.value = positions;
}
calculateColors(attribute) {
const _this$props3 = this.props,
data = _this$props3.data,
getColor = _this$props3.getColor;
const _this$state2 = this.state,
pathLengths = _this$state2.pathLengths,
vertexCount = _this$state2.vertexCount;
const colors = new Float32Array(vertexCount * 3);
let index = 0;
for (let i = 0; i < data.length; i++) {
const color = getColor(data[i]);
const l = pathLengths[i];
for (let j = 0; j < l; j++) {
colors[index++] = color[0];
colors[index++] = color[1];
colors[index++] = color[2];
}
}
attribute.value = colors;
}
}
TripsLayer.layerName = 'TripsLayer';
TripsLayer.defaultProps = defaultProps;
//# sourceMappingURL=trips-layer.js.map