Skip to content

Commit

Permalink
fix LineString update value of LineGradientProperty, maptalks/issues#782
Browse files Browse the repository at this point in the history
  • Loading branch information
fuzhenn committed Nov 15, 2024
1 parent 569c5e2 commit f41b228
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 14 deletions.
97 changes: 84 additions & 13 deletions packages/vt/src/layer/plugins/painters/LineGradientPainter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,76 @@ import { mat4 } from '@maptalks/gl';
import vert from './glsl/line.vert';
import frag from './glsl/line.gradient.frag';
import { prepareFnTypeData } from './util/fn_type_util';
import { ID_PROP } from '../../vector/util/convert_to_feature';
import { LINE_GRADIENT_PROP_KEY } from '../../vector/util/symbols';

const GRADIENTS_COUNT_TO_WARN = 2048;

class LineGradientPainter extends LinePainter {

postCreateGeometry(lineGeometry) {
this.generateGradProperties(lineGeometry);
}

startFrame(...args) {
super.startFrame(...args);
this._updateMeshGradient();
}

_updateMeshGradient() {
if (this._changedMeshes) {
for (let i = 0; i < this._changedMeshes.length; i++) {
if (!this._changedMeshes[i] || !this._changedMeshes[i].isValid()) {
continue;
}
const { geometry, material } = this._changedMeshes[i];
const { symbolIndex } = geometry.properties;
this.generateGradProperties({ geometry, symbolIndex });
const texture = this._genGradientTexture(geometry.properties.gradients);
const oldTexture = material.get('lineGradientTexture');
if (oldTexture) {
oldTexture.destroy();
}
geometry.generateBuffers(this.regl);
material.set('lineGradientTexture', texture);
material.set('lineGradientTextureHeight', texture.height);
}
delete this._changedMeshes;
}
}

onFeatureChange(feature, meshes) {
if (!this._changedMeshes) {
this._changedMeshes = [];
}
for (let i = 0; i < meshes.length; i++) {
if (!meshes[i] || !meshes[i].isValid()) {
continue;
}
const geometry = meshes[i].geometry;
const { features } = geometry.properties;
if (!features) {
continue;
}
const id = feature && feature[ID_PROP];
if (features[id]) {
features[id].feature.properties[LINE_GRADIENT_PROP_KEY] = feature.properties[LINE_GRADIENT_PROP_KEY];
this._changedMeshes.push(meshes[i]);
this.setToRedraw();
}
}
}

needRebuildOnGometryPropertiesChanged() {
return false;
}

generateGradProperties(lineGeometry) {
const { symbolIndex, geometry } = lineGeometry;
const { features } = geometry.properties;
const symbol = this.getSymbol(symbolIndex);
const gradProp = symbol['lineGradientProperty'];
const featureIndexes = geometry.data.aPickingId;
const featureIndexes = geometry.properties.aPickingId || geometry.data.aPickingId;
const aGradIndex = new Uint8Array(featureIndexes.length);
const gradients = [];
const gradientIndex = new Map();
Expand Down Expand Up @@ -47,6 +106,13 @@ class LineGradientPainter extends LinePainter {
}
aGradIndex[i] = gradIndex;
}
if (geometry.data.aGradIndex) {
const aGradIndex = geometry.data.aGradIndex;
//TODO webgpu
if (aGradIndex && aGradIndex.buffer && aGradIndex.buffer.destroy) {
aGradIndex.buffer.destroy();
}
}
geometry.data.aGradIndex = aGradIndex;
geometry.properties.gradients = gradients;
}
Expand All @@ -68,20 +134,10 @@ class LineGradientPainter extends LinePainter {
const symbol = this.getSymbol(symbolIndex);
this.setLineUniforms(symbol, uniforms);

const gradients = geometry.properties.gradients;
const height = gradients.length * 2;
const texture = this.regl.texture({
width: 256,
height,
data: createGradient(gradients),
format: 'rgba',
mag: 'linear', //very important
min: 'linear', //very important
flipY: false,
});

const texture = this._genGradientTexture(geometry.properties.gradients);
uniforms['lineGradientTexture'] = texture;
uniforms['lineGradientTextureHeight'] = texture.height;

if (ref === undefined) {
geometry.generateBuffers(this.regl);
}
Expand All @@ -105,6 +161,21 @@ class LineGradientPainter extends LinePainter {
return mesh;
}

_genGradientTexture(gradients) {
const height = gradients.length * 2;
//TODO webgpu
const texture = this.regl.texture({
width: 256,
height,
data: createGradient(gradients),
format: 'rgba',
mag: 'linear', //very important
min: 'linear', //very important
flipY: false,
});
return texture;
}

createFnTypeConfig(map, symbolDef) {
return this.createShapeFnTypeConfigs(map, symbolDef);
}
Expand Down
8 changes: 8 additions & 0 deletions packages/vt/src/layer/plugins/painters/Painter.js
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,14 @@ class Painter {
return false;
}

needRebuildOnGometryPropertiesChanged() {
return true;
}

onFeatureChange() {

}

getPolygonOffset() {
const layer = this.layer;
return {
Expand Down
10 changes: 9 additions & 1 deletion packages/vt/src/layer/vector/Vector3DLayerRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1395,7 +1395,15 @@ class Vector3DLayerRenderer extends maptalks.renderer.CanvasRenderer {
}
this.features[uid] = convertToFeature(geo, this._kidGen);
this._refreshFeatures(this.features[uid], uid);
this._markRebuild();
if (this._markerMeshes && this._markerMeshes.length && this._markerPainter.needRebuildOnGometryPropertiesChanged() ||
this._lineMeshes && this._lineMeshes.length && this._linePainter.needRebuildOnGometryPropertiesChanged() ||
this.meshes && this.meshes.length && this.painter.needRebuildOnGometryPropertiesChanged()) {
this._markRebuild();
} else {
this.painter.onFeatureChange(this.features[uid], this.meshes);
}


redraw(this);
}

Expand Down
29 changes: 29 additions & 0 deletions packages/vt/test/specs/update.vector.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,35 @@ describe('vector layers update style specs', () => {
layer.addTo(map);
});

it('should can update symbol.lineGradientProperty, maptalks/issues#782', done => {
const line = new maptalks.LineString([[-1, 0], [1, 0]], {
symbol: {
lineGradientProperty: 'gradients',
lineWidth: 20
},
properties: {
gradients: [0, 'red', 0.7, 'yellow', 1, 'green']
}
});
const layer = new LineStringLayer('vector', line);
const renderer = map.getRenderer();
const x = renderer.canvas.width, y = renderer.canvas.height;
layer.once('canvasisdirty', () => {
const pixel = readPixel(layer.getRenderer().canvas, x / 2, y / 2);
assert.deepEqual(pixel, [255, 184, 0, 255]);
layer.once('canvasisdirty', () => {
const pixel = readPixel(layer.getRenderer().canvas, x / 2, y / 2);
assert.deepEqual(pixel, [0, 0, 255, 255]);
done();
});
line.setProperties({
gradients: [0, 'blue', 0.7, 'blue', 1, 'blue']
});

});
layer.addTo(map);
});

it('should can update symbol with function-type lineColor, fuzhenn/maptalks-ide#3099', done => {
const line = new maptalks.LineString([[-1, 0], [1, 0]]);
line.setSymbol({
Expand Down

0 comments on commit f41b228

Please sign in to comment.