Skip to content

Commit 8613002

Browse files
larsmaxfieldHarelM
andauthored
Implement resampling paint property to raster, hillshade, and color-relief layers (#7194)
* Add resampling handling to raster layer * Remove debugging line * Fix options in setPaintProperty * Fix property typing in Resamplings * Implement 'resampling' in renderers raster (previously 'raster-resampling'), hillshade, color-relief * Add 'resampling' render tests raster, hillshade, color-relief * Add resampling handling tests for RasterStyleLayer * Fix resampling constructor handle RasterStyleLayer * Clearer language in warning, tests * Add resampling test when unequal in constructor * Add CHANGELOG entry * Update bundle size * Update bundle size * Simplify raster resampling handling * Simplify resampling handling Fall back to raster-resampling if resampling undefined * Simplify further (undefined is inherent) * Simplify resampling handling tests * Add layer id to resampling warning * Change console.warn to warnOnce * Fix errant import auto-spacing --------- Co-authored-by: Harel M <harel.mazor@gmail.com>
1 parent 9f20933 commit 8613002

File tree

24 files changed

+399
-5
lines changed

24 files changed

+399
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
### ✨ Features and improvements
44
- Add Etag unmodified support to optimize vector tile reloading ([#7074](https://github.com/maplibre/maplibre-gl-js/pull/7074)) (by [@rivkamatan](https://github.com/rivkamatan and [@wayofthefuture](https://github.com/wayofthefuture))
55
- Add `boxZoom.boxZoomEnd` option to customize the action after Shift-drag box selection ([#6397](https://github.com/maplibre/maplibre-gl-js/issues/6397))
6+
- Implement `resampling` paint property for raster, hillshade, and color-relief layers ([#7074](https://github.com/maplibre/maplibre-gl-js/pull/7194)) (by [@larsmaxfield](https://github.com/larsmaxfield))
67
- Add updateable support for GeoJSON-VT ([#7172](https://github.com/maplibre/maplibre-gl-js/issues/7172)) (by [@wayofthefuture](https://github.com/wayofthefuture) and [HarelM](https://github.com/HarelM))
78
- _...Add new stuff here..._
89

src/render/draw_color_relief.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ function renderColorRelief(
5555
const program = painter.useProgram('colorRelief');
5656
const align = !painter.options.moving;
5757

58+
const textureFilter = layer.paint.get('resampling') === 'nearest' ? gl.NEAREST : gl.LINEAR;
59+
5860
let firstTile = true;
5961
let colorRampSize = 0;
6062

@@ -86,10 +88,10 @@ function renderColorRelief(
8688
if (tile.demTexture) {
8789
const demTexture = tile.demTexture;
8890
demTexture.update(pixelData, {premultiply: false});
89-
demTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
91+
demTexture.bind(textureFilter, gl.CLAMP_TO_EDGE);
9092
} else {
9193
tile.demTexture = new Texture(context, pixelData, gl.RGBA, {premultiply: false});
92-
tile.demTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
94+
tile.demTexture.bind(textureFilter, gl.CLAMP_TO_EDGE);
9395
}
9496

9597
const mesh = projection.getMeshFromTileID(context, coord.canonical, useBorder, true, 'raster');

src/render/draw_hillshade.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ function prepareHillshade(
103103
const context = painter.context;
104104
const gl = context.gl;
105105

106+
const textureFilter = layer.paint.get('resampling') === 'nearest' ? gl.NEAREST : gl.LINEAR;
107+
106108
for (const coord of tileIDs) {
107109
const tile = tileManager.getTile(coord);
108110
const dem = tile.dem;
@@ -138,7 +140,7 @@ function prepareHillshade(
138140

139141
if (!fbo) {
140142
const renderTexture = new Texture(context, {width: tileSize, height: tileSize, data: null}, gl.RGBA);
141-
renderTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
143+
renderTexture.bind(textureFilter, gl.CLAMP_TO_EDGE);
142144

143145
fbo = tile.fbo = context.createFramebuffer(tileSize, tileSize, true, false);
144146
fbo.colorAttachment.set(renderTexture.texture);

src/render/draw_raster.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ function drawTiles(
9595
const colorMode = painter.colorModeForRenderPass();
9696
const align = !painter.options.moving;
9797
const rasterOpacity = layer.paint.get('raster-opacity');
98-
const rasterResampling = layer.paint.get('raster-resampling');
98+
const resampling = layer.paint.get('resampling') ?? layer.paint.get('raster-resampling');
99+
const textureFilter = resampling === 'nearest' ? gl.NEAREST : gl.LINEAR;
99100
const fadeDuration = layer.paint.get('raster-fade-duration');
100101
const isTerrain = !!painter.style.map.terrain;
101102

@@ -107,7 +108,6 @@ function drawTiles(
107108
rasterOpacity === 1 ? DepthMode.ReadWrite : DepthMode.ReadOnly, gl.LESS);
108109

109110
const tile = tileManager.getTile(coord);
110-
const textureFilter = rasterResampling === 'nearest' ? gl.NEAREST : gl.LINEAR;
111111

112112
// create and bind first texture
113113
context.activeTexture.set(gl.TEXTURE0);
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import {describe, test, expect, vi} from 'vitest';
2+
import {type LayerSpecification} from '@maplibre/maplibre-gl-style-spec';
3+
import {createStyleLayer} from '../create_style_layer';
4+
import {extend} from '../../util/util';
5+
6+
function createLayerSpec(properties?): LayerSpecification {
7+
return extend({
8+
type: 'raster',
9+
id: 'raster',
10+
source: 'rasterSource'
11+
}, properties);
12+
}
13+
14+
describe('RasterStyleLayer correctly handles "resampling" and "raster-resampling" paint properties', () => {
15+
16+
test('"raster-resampling" is undefined when instantiated with "resampling"', () => {
17+
const layerSpec = createLayerSpec();
18+
const layer = createStyleLayer(layerSpec, {});
19+
20+
const rasterResampling = layer.getPaintProperty('raster-resampling');
21+
expect(rasterResampling).toEqual(undefined);
22+
});
23+
24+
test('"resampling" is undefined when instantiated with "raster-resampling"', () => {
25+
const layerSpec = createLayerSpec();
26+
const layer = createStyleLayer(layerSpec, {});
27+
28+
const resampling = layer.getPaintProperty('resampling');
29+
expect(resampling).toEqual(undefined);
30+
});
31+
32+
test('warns when both "resampling" and "raster-resampling" are specified upon instantiation', () => {
33+
const originalWarn = console.warn;
34+
console.warn = vi.fn();
35+
36+
const layerSpec = createLayerSpec({
37+
paint: {
38+
resampling: 'nearest',
39+
'raster-resampling': 'nearest',
40+
}
41+
});
42+
createStyleLayer(layerSpec, {});
43+
expect(console.warn).toHaveBeenCalledTimes(1);
44+
console.warn = originalWarn;
45+
});
46+
47+
});

src/style/style_layer/raster_style_layer.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {StyleLayer} from '../style_layer';
2+
import {warnOnce} from '../../util/util';
23

34
import properties, {type RasterPaintPropsPossiblyEvaluated} from './raster_style_layer_properties.g';
45
import {type Transitionable, type Transitioning, type PossiblyEvaluated} from '../properties';
@@ -14,6 +15,10 @@ export class RasterStyleLayer extends StyleLayer {
1415
paint: PossiblyEvaluated<RasterPaintProps, RasterPaintPropsPossiblyEvaluated>;
1516

1617
constructor(layer: LayerSpecification, globalState: Record<string, any>) {
18+
const resampling = layer.paint?.['resampling'];
19+
if (resampling && layer.paint?.['raster-resampling']) {
20+
warnOnce(`Raster layer "${layer.id}" paint properties "resampling" and "raster-resampling" are both specified, but only "resampling" needs to be specified. Defaulting to "resampling" (${resampling}).`);
21+
}
1722
super(layer, properties, globalState);
1823
}
1924
}
36.4 KB
Loading
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"version": 8,
3+
"metadata": {
4+
"test": {
5+
"height": 256,
6+
"width": 256
7+
}
8+
},
9+
"center": [-113.26903, 35.9654],
10+
"zoom": 15,
11+
"sources": {
12+
"source": {
13+
"type": "raster-dem",
14+
"tiles": [
15+
"local://tiles/{z}-{x}-{y}.terrain.png"
16+
],
17+
"maxzoom": 12,
18+
"tileSize": 256
19+
}
20+
},
21+
"layers": [
22+
{
23+
"id": "color-relief",
24+
"type": "color-relief",
25+
"source": "source",
26+
"paint": {
27+
"color-relief-color": [
28+
"interpolate",
29+
["linear"],
30+
["elevation"],
31+
1310, "#000",
32+
1430, "#FFF"
33+
]
34+
}
35+
}
36+
]
37+
}
1.83 KB
Loading
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"version": 8,
3+
"metadata": {
4+
"test": {
5+
"height": 256,
6+
"width": 256
7+
}
8+
},
9+
"center": [-113.26903, 35.9654],
10+
"zoom": 15,
11+
"sources": {
12+
"source": {
13+
"type": "raster-dem",
14+
"tiles": [
15+
"local://tiles/{z}-{x}-{y}.terrain.png"
16+
],
17+
"maxzoom": 12,
18+
"tileSize": 256
19+
}
20+
},
21+
"layers": [
22+
{
23+
"id": "color-relief",
24+
"type": "color-relief",
25+
"source": "source",
26+
"paint": {
27+
"color-relief-color": [
28+
"interpolate",
29+
["linear"],
30+
["elevation"],
31+
1310, "#000",
32+
1430, "#FFF"
33+
],
34+
"resampling": {
35+
"stops": [
36+
[
37+
14,
38+
"linear"
39+
],
40+
[
41+
15,
42+
"nearest"
43+
]
44+
]
45+
}
46+
}
47+
}
48+
]
49+
}

0 commit comments

Comments
 (0)