layer0 = {
const { Layer, project32, picking, BitmapLayer } = deck;
const { Model, Geometry, Texture2D, isWebGL2 } = luma;
const DEFAULT_TEXTURE_PARAMETERS = {
[GL.TEXTURE_MIN_FILTER]: GL.NEAREST,
[GL.TEXTURE_MAG_FILTER]: GL.NEAREST,
[GL.TEXTURE_WRAP_S]: GL.CLAMP_TO_EDGE,
[GL.TEXTURE_WRAP_T]: GL.CLAMP_TO_EDGE,
};
class HeatmapBitmapLayer extends Layer {
getShaders() {
return super.getShaders({ vs, fs, modules: [ project32, picking ] });
}
initializeState() {
const attributeManager = this.getAttributeManager();
attributeManager.remove(['instancePickingColors']);
const noAlloc = true;
attributeManager.add({
indices: {
size: 1,
isIndexed: true,
update: attribute => (attribute.value = this.state.mesh.indices),
noAlloc
},
positions: {
size: 3,
type: GL.DOUBLE,
fp64: this.use64bitPositions(),
update: attribute => (attribute.value = this.state.mesh.positions),
noAlloc
},
texCoords: {
size: 2,
update: attribute => (attribute.value = this.state.mesh.texCoords),
noAlloc
}
});
}
updateState({ props, oldProps, changeFlags }) {
// setup model first
if (changeFlags.extensionsChanged) {
const {gl} = this.context;
if (this.state.model) {
this.state.model.delete();
}
this.setState({model: this._getModel(gl)});
this.getAttributeManager().invalidateAll();
}
if (props.image !== oldProps.image) {
this.loadTexture(props.image);
}
const attributeManager = this.getAttributeManager();
if (props.bounds !== oldProps.bounds) {
const oldMesh = this.state.mesh;
const mesh = this._createMesh();
this.state.model.setVertexCount(mesh.vertexCount);
for (const key in mesh) {
if (oldMesh && oldMesh[key] !== mesh[key]) {
attributeManager.invalidate(key);
}
}
this.setState({mesh});
}
}
finalizeState() {
super.finalizeState();
if (this.state.bitmapTexture) {
this.state.bitmapTexture.delete();
}
}
_createMesh() {
const { bounds } = this.props;
let normalizedBounds = bounds;
// bounds as [minX, minY, maxX, maxY]
if (Number.isFinite(bounds[0])) {
/*
(minX0, maxY3) ---- (maxX2, maxY3)
| |
| |
| |
(minX0, minY1) ---- (maxX2, minY1)
*/
normalizedBounds = [
[bounds[0], bounds[1]],
[bounds[0], bounds[3]],
[bounds[2], bounds[3]],
[bounds[2], bounds[1]]
];
}
return createMesh(normalizedBounds, this.context.viewport.resolution);
}
_getModel(gl) {
if (!gl) {
return null;
}
/*
0,0 --- 1,0
| |
0,1 --- 1,1
*/
return new Model(
gl,
Object.assign({}, this.getShaders(), {
id: this.props.id,
geometry: new Geometry({
drawMode: GL.TRIANGLES,
vertexCount: 6
}),
isInstanced: false
})
);
}
draw(opts) {
const { uniforms } = opts;
const { bitmapTexture, model } = this.state;
const { image } = this.props;
const { bounds } = this.props;
console.log(bounds);
// // TODO fix zFighting
// Render the image
if (bitmapTexture && model) {
model
.setUniforms(
Object.assign({}, uniforms, {
uBitmapTexture: bitmapTexture,
uTextureSize: [0.0 + bounds[2] - bounds[0], 0.0 + bounds[3] - bounds[1]],
})
)
.draw();
}
}
loadTexture(image) {
const { gl } = this.context;
const noWebGL2 = !isWebGL2(gl);
if(this.state.bitmapTexture) {
this.state.bitmapTexture.delete();
}
if(image instanceof Texture2D) {
this.setState({ bitmapTexture: image });
} else if(image) {
this.setState({
bitmapTexture: new Texture2D(gl, {
data: image,
parameters: DEFAULT_TEXTURE_PARAMETERS,
//format: noWebGL2 ? GL.LUMINANCE : GL.R8UI,
format: GL.LUMINANCE,
width: 4,
height: 3
}),
});
}
}
}
HeatmapBitmapLayer.layerName = 'HeatmapBitmapLayer';
HeatmapBitmapLayer.defaultProps = defaultProps;
const layer = new HeatmapBitmapLayer({
id: `bitmap-${Date.now()}`,
image: imageData,
bounds: [-viewWidth/2, -viewHeight/2, viewWidth/2, viewHeight/2]
});
deckgl.setProps({ layers: [layer] });
return layer;
}