diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a537770..e7aac62f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,25 @@ * feat(geotiff): New internal method to fetch multiple tiles concurrently, with range coalescing by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/530 * feat(geotiff): route fetchTiles through batched, range-coalescing getTiles by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/531 +## v0.8.0 - 2026-06-10 + +### What's Changed + +* fix: Remove NAIP Mosaic caching override by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/554 +* fix: Use fp64 emulation to fix lack of precision (jitter) at high zooms by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/559 +* fix: traverse tiles across world copies (#517) by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/518 +* feat: Initial Globe view support by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/563 +* feat: per-origin HTTP concurrency limiter for COG layers by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/557 +* fix: Use https links for umbra COG by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/571 +* fix(geotiff): revert ConcurrencyLimiter to a chunkd SourceMiddleware by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/572 +* feat: reprojector initial-triangulation seed + clamp Web Mercator meshes to ±85.051° by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/574 +* feat: NLDAS-3 icechunk example by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/577 +* fix: Support parsing ESRI WKT String for ESRI-created custom CRS by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/579 +* fix: clamp Web Mercator mesh for south-up affines by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/590 +* fix: destroy tile textures on eviction (#591) by @kylebarron in https://github.com/developmentseed/deck.gl-raster/pull/594 + +**Full Changelog**: https://github.com/developmentseed/deck.gl-raster/compare/v0.7.0...v0.8.0 + ## v0.7.0 - 2026-05-13 ### Breaking Changes diff --git a/docs/blog/v0.8-release.md b/docs/blog/v0.8-release.md new file mode 100644 index 00000000..d9efd7b7 --- /dev/null +++ b/docs/blog/v0.8-release.md @@ -0,0 +1,120 @@ +--- +slug: v0-8-release +title: deck.gl-raster v0.8 +date: 2026-06-10 +authors: + - kylebarron +tags: [release] +--- + +deck.gl-raster enables GPU-accelerated [Cloud-Optimized GeoTIFF][cogeo] (COG) and [Zarr] visualization in [deck.gl]. + +This release includes initial support for globe rendering, performance improvements, fixed reprojection and precision bugs, and a new Icechunk example. + +[cogeo]: https://cogeo.org/ +[Zarr]: https://zarr.dev/ +[deck.gl]: https://deck.gl/ + +{/* truncate */} + +## Preliminary GlobeView support + +We've landed preliminary support for deck.gl's [`GlobeView`]. + +**Some projections may render with some distortion**. This initial implementation takes a simpler rendering approach, using a fixed number of resampling points, instead of the more accurate dynamic resampling approach used in the standard Web Mercator [`MapView`]. + +[`GlobeView`]: https://deck.gl/docs/api-reference/core/globe-view +[`MapView`]: https://deck.gl/docs/api-reference/core/map-view + +![](../static/img/initial-globe-view.gif) + +See [#563](https://github.com/developmentseed/deck.gl-raster/pull/563) for the existing implementation and follow [#578](https://github.com/developmentseed/deck.gl-raster/pull/578) for the improved reprojection work. + +## Improved request latency for MosaicLayer + +Previously, scrolling around a map with a `MosaicLayer` would generate many, many requests of images that were only briefly in view and that aren't cancelled when panning around the map. + +**Before**: we fetch almost 300MB of data before loading the data in the end viewport location. It takes so long to load the data because it keeps loading off-screen tiles. + +_Note: the gif is 30 seconds long. It may look stuck, but pay attention to the download gauge in the bottom right counting upwards, representing off-screen requests._ + +![](../static/img/mosaic-layer-request-cancellation-before.gif) + +**After**, the request cancellation is working much better. As we scroll around the map, off-screen tiles are immediately cancelled, so the latency of loading new tiles is vastly reduced. + +![](../static/img/mosaic-layer-request-cancellation-after.gif) + + +See [#557](https://github.com/developmentseed/deck.gl-raster/pull/557) for more info. + +## Fixed reprojection for images extending beyond ±85° latitude + +The Web Mercator projection is only defined below 85.05°N and above 85.05°S. Previously, for datasets that extended beyond that region, the reprojection process would position images incorrectly. + +Now, reprojection should be both faster and accurate. + +**Before**, the rendered image is further north than the basemap's (correct) rendering of Scandinavia underneath: + +![](../static/img/polar-reprojection-web-mercator-bounds-before.png) + +**After**, the rendered image is correctly on top of the basemap: + +![](../static/img/polar-reprojection-web-mercator-bounds-after.png) + +See [#574](https://github.com/developmentseed/deck.gl-raster/pull/574) for more info. + +## Icechunk example + +We created a new [Icechunk](https://icechunk.io/en/stable/)-based [example][nldas-icechunk-example] with the `ZarrLayer`. It reads [NLDAS-3](https://ldas.gsfc.nasa.gov/nldas/v3) temperature data directly from a public Icechunk repository. + +This dataset is [virtualized](https://github.com/zarr-developers/VirtualiZarr)! All tile data requests are being made into _NetCDF_ data files. + +[nldas-icechunk-example]: https://developmentseed.org/deck.gl-raster/examples/nldas-icechunk/ + +[![](../static/img/nldas-3-icechunk.jpg)][nldas-icechunk-example] + +See [#577](https://github.com/developmentseed/deck.gl-raster/pull/577) for more info. + +## Fix image jitter at high zooms + +Previously, viewing a high-resolution raster dataset — like in the NAIP example, which has 30-centimeter resolution — the image would noticeably _jitter_ around the screen when zoomed in at high resolution. + +[NAIP example]: https://developmentseed.org/deck.gl-raster/examples/naip-mosaic/ + +This was because the GPU used float32 positions to locate the image on the map, and float32 wasn't enough precision to precisely position the image. The jitter came from switching between float32 units of least precision on either side of the actual float64 value. + +Though GPUs only natively support 32-bit floats, we fixed this by using emulated float64 values. Because of how the rendering works, this only causes a tiny amount of overhead. + +**Before**: + +![](../static/img/fp64-jitter-before.gif) + +**After**, we now smoothly zoom in and out at high zooms: + +![](../static/img/fp64-jitter-after.gif) + +See [#559](https://github.com/developmentseed/deck.gl-raster/pull/559) for more info. + +## Fix rendering across multiple "world copies" + +When you're viewing a map over the antimeridian, deck.gl is actually rendering _two copies_ of the map: one for the world on the left side of the antimeridian and another for the world on the right side. + +**Before**, we didn't render image data into both maps: + +![](../static/img/world-copies-before.gif) + +**After**, we now seamlessly render on both sides of the antimeridian. + +![](../static/img/world-copies-after.gif) + +This is **separate** from being able to render images that themselves _cross_ the antimeridian. In the above screencasts, the example COG has bounds from `[-180, 180]`, so it's on either side of the antimeridian but doesn't cross it. + +See [#518](https://github.com/developmentseed/deck.gl-raster/pull/518) for more info. + +## Fixed GPU memory leak for COGLayer and ZarrLayer + +We fixed a GPU memory leak in tiled layers with default rendering. + +If you're defining your own `getTileData` that manually creates luma.gl `Texture` objects, make sure you also define `onTileUnload` which calls `Texture.destroy()`. + +See [#591](https://github.com/developmentseed/deck.gl-raster/pull/591) for more info. diff --git a/docs/static/img/fp64-jitter-after.gif b/docs/static/img/fp64-jitter-after.gif new file mode 100644 index 00000000..81db62c7 Binary files /dev/null and b/docs/static/img/fp64-jitter-after.gif differ diff --git a/docs/static/img/fp64-jitter-before.gif b/docs/static/img/fp64-jitter-before.gif new file mode 100644 index 00000000..b999d94a Binary files /dev/null and b/docs/static/img/fp64-jitter-before.gif differ diff --git a/docs/static/img/initial-globe-view.gif b/docs/static/img/initial-globe-view.gif new file mode 100644 index 00000000..c91b1089 Binary files /dev/null and b/docs/static/img/initial-globe-view.gif differ diff --git a/docs/static/img/mosaic-layer-request-cancellation-after.gif b/docs/static/img/mosaic-layer-request-cancellation-after.gif new file mode 100644 index 00000000..1f146cb2 Binary files /dev/null and b/docs/static/img/mosaic-layer-request-cancellation-after.gif differ diff --git a/docs/static/img/mosaic-layer-request-cancellation-before.gif b/docs/static/img/mosaic-layer-request-cancellation-before.gif new file mode 100644 index 00000000..aa180144 Binary files /dev/null and b/docs/static/img/mosaic-layer-request-cancellation-before.gif differ diff --git a/docs/static/img/nldas-3-icechunk.jpg b/docs/static/img/nldas-3-icechunk.jpg new file mode 100644 index 00000000..66dcc02f Binary files /dev/null and b/docs/static/img/nldas-3-icechunk.jpg differ diff --git a/docs/static/img/polar-reprojection-web-mercator-bounds-after.png b/docs/static/img/polar-reprojection-web-mercator-bounds-after.png new file mode 100644 index 00000000..53cd2882 Binary files /dev/null and b/docs/static/img/polar-reprojection-web-mercator-bounds-after.png differ diff --git a/docs/static/img/polar-reprojection-web-mercator-bounds-before.png b/docs/static/img/polar-reprojection-web-mercator-bounds-before.png new file mode 100644 index 00000000..6f643c9a Binary files /dev/null and b/docs/static/img/polar-reprojection-web-mercator-bounds-before.png differ diff --git a/docs/static/img/world-copies-after.gif b/docs/static/img/world-copies-after.gif new file mode 100644 index 00000000..17d77ac3 Binary files /dev/null and b/docs/static/img/world-copies-after.gif differ diff --git a/docs/static/img/world-copies-before.gif b/docs/static/img/world-copies-before.gif new file mode 100644 index 00000000..9d338edb Binary files /dev/null and b/docs/static/img/world-copies-before.gif differ diff --git a/examples/nldas-icechunk/src/App.tsx b/examples/nldas-icechunk/src/App.tsx index 5f87ec7a..bda35f8e 100644 --- a/examples/nldas-icechunk/src/App.tsx +++ b/examples/nldas-icechunk/src/App.tsx @@ -59,7 +59,7 @@ const COLORMAP_ROW_COUNT = Object.keys(COLORMAP_INDEX).length; * Kelvin (the data's native unit, which the rescale shader expects); only the * label is shown in the friendlier °C, with Kelvin in parentheses. */ -const kelvinToCelsius = (k: number) => Math.round(k - 273.15); +const kelvinToCelsius = (k: number) => (k - 273.15).toFixed(1); export default function App() { const mapRef = useRef(null); @@ -216,7 +216,7 @@ export default function App() { - Rescale range: {kelvinToCelsius(rescaleMin)}°C ({rescaleMin} K) –{" "} + Rescale range: {kelvinToCelsius(rescaleMin)}°C ({rescaleMin} K) -{" "} {kelvinToCelsius(rescaleMax)}°C ({rescaleMax} K) } diff --git a/examples/nldas-icechunk/src/nldas/metadata.ts b/examples/nldas-icechunk/src/nldas/metadata.ts index 46f61bbe..99d79e4b 100644 --- a/examples/nldas-icechunk/src/nldas/metadata.ts +++ b/examples/nldas-icechunk/src/nldas/metadata.ts @@ -44,7 +44,7 @@ export const RESCALE_MAX = 305; /** Bounds + step for the rescale slider (Kelvin). */ export const RESCALE_SLIDER_MIN = 240; export const RESCALE_SLIDER_MAX = 320; -export const RESCALE_SLIDER_STEP = 1; +export const RESCALE_SLIDER_STEP = 0.1; /** * Synthetic GeoZarr-compliant attrs (the virtual store is not GeoZarr).