diff --git a/debug/image.html b/debug/image.html
index 646e5d8671b..b5bf1400502 100644
--- a/debug/image.html
+++ b/debug/image.html
@@ -36,12 +36,15 @@
"id": "background",
"type": "background",
"paint": {
- "background-color": "rgb(4,7,14)"
+ "background-color": "rgb(128,128,128)"
}
}, {
"id": "image",
"type": "raster",
- "source": "image"
+ "source": "image",
+ "paint": {
+ "raster-resampling": "nearest"
+ }
}]
};
diff --git a/src/render/draw_raster.js b/src/render/draw_raster.js
index 8f788414677..3454c34cef3 100644
--- a/src/render/draw_raster.js
+++ b/src/render/draw_raster.js
@@ -56,18 +56,20 @@ function drawRaster(painter: Painter, sourceCache: SourceCache, layer: RasterSty
let parentScaleBy, parentTL;
+ const textureFilter = layer.paint.get('raster-resampling') === 'nearest' ? gl.NEAREST : gl.LINEAR;
+
context.activeTexture.set(gl.TEXTURE0);
- tile.texture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE, gl.LINEAR_MIPMAP_NEAREST);
+ tile.texture.bind(textureFilter, gl.CLAMP_TO_EDGE, gl.LINEAR_MIPMAP_NEAREST);
context.activeTexture.set(gl.TEXTURE1);
if (parentTile) {
- parentTile.texture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE, gl.LINEAR_MIPMAP_NEAREST);
+ parentTile.texture.bind(textureFilter, gl.CLAMP_TO_EDGE, gl.LINEAR_MIPMAP_NEAREST);
parentScaleBy = Math.pow(2, parentTile.tileID.overscaledZ - tile.tileID.overscaledZ);
parentTL = [tile.tileID.canonical.x * parentScaleBy % 1, tile.tileID.canonical.y * parentScaleBy % 1];
} else {
- tile.texture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE, gl.LINEAR_MIPMAP_NEAREST);
+ tile.texture.bind(textureFilter, gl.CLAMP_TO_EDGE, gl.LINEAR_MIPMAP_NEAREST);
}
// cross-fade parameters
diff --git a/src/style-spec/reference/v8.json b/src/style-spec/reference/v8.json
index c404deed477..529e27c2cf0 100644
--- a/src/style-spec/reference/v8.json
+++ b/src/style-spec/reference/v8.json
@@ -5013,6 +5013,32 @@
},
"property-type": "data-constant"
},
+ "raster-resampling": {
+ "type": "enum",
+ "doc": "The resampling/interpolation method to use for overscaling, also known as texture magnification filter",
+ "values": {
+ "linear": {
+ "doc": "(Bi)linear filtering interpolates pixel values using the weighted average of the four closest original source pixels creating a smooth but blurry look when overscaled"
+ },
+ "nearest": {
+ "doc": "Nearest neighbor filtering interpolates pixel values using the nearest original source pixel creating a sharp but pixelated look when overscaled"
+ }
+ },
+ "default": "linear",
+ "sdk-support": {
+ "basic functionality": {
+ "js": "0.47.0"
+ },
+ "data-driven styling": {}
+ },
+ "expression": {
+ "interpolated": false,
+ "parameters": [
+ "zoom"
+ ]
+ },
+ "property-type": "data-constant"
+ },
"raster-fade-duration": {
"type": "number",
"default": 300,
diff --git a/src/style/style_layer/raster_style_layer_properties.js b/src/style/style_layer/raster_style_layer_properties.js
index aab591ac770..e0193d510b2 100644
--- a/src/style/style_layer/raster_style_layer_properties.js
+++ b/src/style/style_layer/raster_style_layer_properties.js
@@ -22,6 +22,7 @@ export type PaintProps = {|
"raster-brightness-max": DataConstantProperty,
"raster-saturation": DataConstantProperty,
"raster-contrast": DataConstantProperty,
+ "raster-resampling": DataConstantProperty<"linear" | "nearest">,
"raster-fade-duration": DataConstantProperty,
|};
@@ -32,6 +33,7 @@ const paint: Properties = new Properties({
"raster-brightness-max": new DataConstantProperty(styleSpec["paint_raster"]["raster-brightness-max"]),
"raster-saturation": new DataConstantProperty(styleSpec["paint_raster"]["raster-saturation"]),
"raster-contrast": new DataConstantProperty(styleSpec["paint_raster"]["raster-contrast"]),
+ "raster-resampling": new DataConstantProperty(styleSpec["paint_raster"]["raster-resampling"]),
"raster-fade-duration": new DataConstantProperty(styleSpec["paint_raster"]["raster-fade-duration"]),
});
diff --git a/test/README.md b/test/README.md
index f76c4692731..ed53f9218df 100644
--- a/test/README.md
+++ b/test/README.md
@@ -13,7 +13,7 @@ There are two test suites associated with Mapbox GL JS
To run individual tests:
- Unit tests: `yarn test-unit path/to/file.test.js` where the path begins within the `/test/unit/` directory
- - Render tests: `yarn test-render render-test-name`
+ - Render tests: `yarn test-render render-test-name` (e.g. `yarn test-render background-color/default`)
## Writing Unit Tests
diff --git a/test/integration/render-tests/image/raster-resampling/expected.png b/test/integration/render-tests/image/raster-resampling/expected.png
new file mode 100644
index 00000000000..759c8e5c07e
Binary files /dev/null and b/test/integration/render-tests/image/raster-resampling/expected.png differ
diff --git a/test/integration/render-tests/image/raster-resampling/style.json b/test/integration/render-tests/image/raster-resampling/style.json
new file mode 100644
index 00000000000..4bad88bbe2e
--- /dev/null
+++ b/test/integration/render-tests/image/raster-resampling/style.json
@@ -0,0 +1,49 @@
+{
+ "version": 8,
+ "metadata": {
+ "test": {
+ "width": 64,
+ "height": 64
+ }
+ },
+ "center": [
+ -122.514526,
+ 37.562984
+ ],
+ "zoom": 20,
+ "sources": {
+ "image": {
+ "type": "image",
+ "coordinates": [
+ [
+ -122.51596391201019,
+ 37.56238816766053
+ ],
+ [
+ -122.51467645168304,
+ 37.56410183312965
+ ],
+ [
+ -122.51309394836426,
+ 37.563391708549425
+ ],
+ [
+ -122.51423120498657,
+ 37.56161849366671
+ ]
+ ],
+ "url": "local://image/0.png"
+ }
+ },
+ "layers": [
+ {
+ "id": "image",
+ "type": "raster",
+ "source": "image",
+ "paint": {
+ "raster-fade-duration": 0,
+ "raster-resampling": "nearest"
+ }
+ }
+ ]
+}
diff --git a/test/integration/render-tests/raster-resampling/default/expected.png b/test/integration/render-tests/raster-resampling/default/expected.png
new file mode 100644
index 00000000000..4db0b165ef2
Binary files /dev/null and b/test/integration/render-tests/raster-resampling/default/expected.png differ
diff --git a/test/integration/render-tests/raster-resampling/default/style.json b/test/integration/render-tests/raster-resampling/default/style.json
new file mode 100644
index 00000000000..ec0fa9ef2af
--- /dev/null
+++ b/test/integration/render-tests/raster-resampling/default/style.json
@@ -0,0 +1,33 @@
+{
+ "version": 8,
+ "metadata": {
+ "test": {
+ "height": 256
+ }
+ },
+ "center": [
+ 13.418056,
+ 52.499167
+ ],
+ "zoom": 20,
+ "sources": {
+ "satellite": {
+ "type": "raster",
+ "tiles": [
+ "local://tiles/{z}-{x}-{y}.satellite.png"
+ ],
+ "maxzoom": 17,
+ "tileSize": 256
+ }
+ },
+ "layers": [
+ {
+ "id": "raster",
+ "type": "raster",
+ "source": "satellite",
+ "paint": {
+ "raster-fade-duration": 0
+ }
+ }
+ ]
+}
diff --git a/test/integration/render-tests/raster-resampling/function/expected.png b/test/integration/render-tests/raster-resampling/function/expected.png
new file mode 100644
index 00000000000..f4f7bce7123
Binary files /dev/null and b/test/integration/render-tests/raster-resampling/function/expected.png differ
diff --git a/test/integration/render-tests/raster-resampling/function/style.json b/test/integration/render-tests/raster-resampling/function/style.json
new file mode 100644
index 00000000000..2ac91b44c55
--- /dev/null
+++ b/test/integration/render-tests/raster-resampling/function/style.json
@@ -0,0 +1,45 @@
+{
+ "version": 8,
+ "metadata": {
+ "test": {
+ "height": 256
+ }
+ },
+ "center": [
+ 13.418056,
+ 52.499167
+ ],
+ "zoom": 20,
+ "sources": {
+ "satellite": {
+ "type": "raster",
+ "tiles": [
+ "local://tiles/{z}-{x}-{y}.satellite.png"
+ ],
+ "maxzoom": 17,
+ "tileSize": 256
+ }
+ },
+ "layers": [
+ {
+ "id": "raster",
+ "type": "raster",
+ "source": "satellite",
+ "paint": {
+ "raster-fade-duration": 0,
+ "raster-resampling": {
+ "stops": [
+ [
+ 19,
+ "linear"
+ ],
+ [
+ 20,
+ "nearest"
+ ]
+ ]
+ }
+ }
+ }
+ ]
+}
diff --git a/test/integration/render-tests/raster-resampling/literal/expected.png b/test/integration/render-tests/raster-resampling/literal/expected.png
new file mode 100644
index 00000000000..f4f7bce7123
Binary files /dev/null and b/test/integration/render-tests/raster-resampling/literal/expected.png differ
diff --git a/test/integration/render-tests/raster-resampling/literal/style.json b/test/integration/render-tests/raster-resampling/literal/style.json
new file mode 100644
index 00000000000..daf15580f02
--- /dev/null
+++ b/test/integration/render-tests/raster-resampling/literal/style.json
@@ -0,0 +1,34 @@
+{
+ "version": 8,
+ "metadata": {
+ "test": {
+ "height": 256
+ }
+ },
+ "center": [
+ 13.418056,
+ 52.499167
+ ],
+ "zoom": 20,
+ "sources": {
+ "satellite": {
+ "type": "raster",
+ "tiles": [
+ "local://tiles/{z}-{x}-{y}.satellite.png"
+ ],
+ "maxzoom": 17,
+ "tileSize": 256
+ }
+ },
+ "layers": [
+ {
+ "id": "raster",
+ "type": "raster",
+ "source": "satellite",
+ "paint": {
+ "raster-fade-duration": 0,
+ "raster-resampling": "nearest"
+ }
+ }
+ ]
+}