Skip to content

feat: support the sky style property - #4534

Open
ClayWarren wants to merge 41 commits into
maplibre:mainfrom
ClayWarren:codex/sky-style-spec-4414
Open

feat: support the sky style property#4534
ClayWarren wants to merge 41 commits into
maplibre:mainfrom
ClayWarren:codex/sky-style-spec-4414

Conversation

@ClayWarren

Copy link
Copy Markdown

Addresses #4414.

Summary

  • add the style model, parser, observer, transition, and zoom-expression plumbing for all seven sky root properties:
    • sky-color
    • horizon-color
    • fog-color
    • fog-ground-blend
    • horizon-fog-blend
    • sky-horizon-blend
    • atmosphere-blend
  • render the planar sky gradient before map layers and the physical globe atmosphere after translucent geometry
  • provide shader and depth-state implementations for OpenGL, Metal, Vulkan, and WebGPU
  • expose generated Android and Darwin SDK APIs, including expressions and transitions
  • cover defaults, parsing, replacement/removal, zoom expressions, SDK generation, and representative GPU output

The behavior and defaults follow MapLibre GL JS PR #3645, with the physical atmosphere updated to match the current GL JS sky pass.

Dependency and deferred terrain fog

This is intentionally stacked on draft globe PR #4533 at 6bddd1111f4d41a5d3130d9a78375b97b9e2a35d. A visible atmosphere-blend implementation needs the globe camera matrices, depth pass, and projection-transition state introduced there. The sky-only review range is the globe head through this branch.

The three fog-related properties are fully parsed, evaluated, transitioned, and exposed through the native SDKs, but do not yet affect pixels. Native still lacks the Terrain3D fog compositor that would consume fog-color, fog-ground-blend, and horizon-fog-blend. That rendering work should follow Terrain3D issue #252 / draft Terrain3D PR #4190 as a separate PR. Planar sky-color, horizon-color, and sky-horizon-blend, plus globe atmosphere-blend, are rendered here.

Validation

  • repository pre-commit suite on every changed file: passed, including pinned clang-format and buildifier
  • Release Metal build of the core library, mbgl-test-runner, and mbgl-render-test-runner: passed
  • focused C++ style tests: 5/5 passed
    • defaults
    • setters/getters and dynamic property lookup
    • constants and transitions
    • float/color zoom expressions
    • style presence, replacement, removal, and invalid input
  • Metal render fixtures: 3/3 passed
    • planar sky gradient
    • zoom-expression interpolation
    • physical globe atmosphere with a non-zero bearing
  • targeted C++ object builds for OpenGL, Metal, Vulkan, and WebGPU: passed
  • generated style-code idempotency checks: passed
  • Android Java 11 and JNI C++20 syntax checks: passed
  • Darwin generator and Objective-C++ syntax checks: passed

The full 1,058-test native suite was also started and showed no failures before reaching the existing Map.StyleNetworkErrorRetry exponential-backoff test; that long network-retry run was stopped rather than reported as a full-suite pass. Metal is the runtime render backend exercised locally; OpenGL, Vulkan, and WebGPU have compile coverage in this validation. A full Android Gradle build was not available because this checkout has no Android SDK.

AI assistance

OpenAI Codex using GPT-5.6 Sol with ultra reasoning assisted with repository analysis, implementation, test generation, diff review, and validation under Clay Warren's direction. The prompts asked it to implement #4414 using MapLibre GL JS #3645 as the behavior oracle, assess the #4533 dependency, cover the native render backends and mobile APIs, keep commits reviewable, and run proportionate upstream checks.

This PR is intentionally a draft. Clay Warren must personally read and review all AI-assisted code before marking it ready for maintainer review.

Globe phase 11a of the design proposal (maplibre#4525): Platform SDK: the GLFW app.

Oracle: The GLFW app by hand.

Consolidates from core/projection-property:
- feat(glfw): toggle the globe with F9
- refactor(core): second review pass over the globe branch
- refactor(core): name the projection types
…phase 7)

Globe phase 7 of the design proposal (maplibre#4525): Tile cover: convex volumes, horizon plane, wrap, no world copies.

Oracle: antimeridian-lod, tile-count assertions in tile_cover.test.cpp.

Consolidates from core/projection-property:
- feat(core): unproject, anchored zoom and constrain on the globe
- feat(core): render lines on the globe (Metal)
- feat(core): cover the globe with the tiles the camera can see
- refactor(core): review pass over the globe branch
- feat(core): let the globe zoom out below zero toward the poles
- perf(core): cover the globe without heap allocations per tile
- fix(core): cover the globe with the tiles GL JS covers
- refactor(core): second review pass over the globe branch
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
Globe phase 8 of the design proposal (maplibre#4525): Symbols and collision.

Oracle: The collision-*, text-* and icon-text-* globe tests.

Consolidates from core/projection-property:
- feat(core): render lines on the globe (Metal)
- feat(core): render symbols on the globe (Metal)
- feat(core): cover the globe with the tiles the camera can see
- feat(core): hand the globe over to Mercator at high zoom
- refactor(core): review pass over the globe branch
- perf(core): project each line-label vertex once per symbol on the globe
- fix(core): hide a line label with any vertex behind the globe
- fix(core): project neighbour tile borders with the Mercator matrix on the globe
- refactor(core): second review pass over the globe branch
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
Globe phase 9a of the design proposal (maplibre#4525): Remaining layer families on Metal: lines.

Oracle: The line globe tests.

Consolidates from core/projection-property:
- feat(core): render lines on the globe (Metal)
- feat(core): render raster, hillshade and color-relief layers on the globe (Metal)
- feat(core): render symbols on the globe (Metal)
- refactor(core): review pass over the globe branch
- fix(core): keep globe line widths in pixels at high latitude
- test(core): port GL JS's checks into the globe unit tests
- refactor(core): second review pass over the globe branch
- test(core): port five more GL JS globe render tests
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
…phase 9b)

Globe phase 9b of the design proposal (maplibre#4525): Remaining layer families on Metal: circle, heatmap.

Oracle: The circle and heatmap globe tests.

Consolidates from core/projection-property:
- feat(core): render circles and heatmaps on the globe (Metal)
- feat(core): render raster, hillshade and color-relief layers on the globe (Metal)
- feat(core): render symbols on the globe (Metal)
- refactor(core): review pass over the globe branch
- refactor(core): second review pass over the globe branch
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
… 9e)

Globe phase 9e of the design proposal (maplibre#4525): The blend: the globe preset's transition to Mercator between zoom 11 and 12, keeping tiles across the hand-off.

Oracle: zoom-transition; Map.GlobeHandOffKeepsTiles.

Consolidates from core/projection-property:
- feat(core): hand the globe over to Mercator at high zoom
- refactor(core): review pass over the globe branch
- perf(core): keep tiles across the globe's Mercator hand-off
- test(core): port GL JS's checks into the globe unit tests
- refactor(core): second review pass over the globe branch
- refactor(core): name the projection types
- test(core): port five more GL JS globe render tests
- test(core): run the globe hand-off test on its own run loop
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
…lobe on Metal (globe phase 9c)

Globe phase 9c of the design proposal (maplibre#4525): Remaining layer families on Metal: raster, hillshade, color-relief; the globe tile mesh.

Oracle: raster-planet, raster-pole, hillshade, color-relief globe tests.

Consolidates from core/projection-property:
- feat(core): render raster, hillshade and color-relief layers on the globe (Metal)
- feat(core): render fill-extrusions on the globe (Metal)
- refactor(core): review pass over the globe branch
- feat(core): let the globe zoom out below zero toward the poles
- refactor(core): second review pass over the globe branch
- test(core): port five more GL JS globe render tests
- test(core): port the GL JS globe raster tests
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
- test(core): unignore the globe tests Linux OpenGL renders
… 9d)

Globe phase 9d of the design proposal (maplibre#4525): Remaining layer families on Metal: fill-extrusion, with the depth prepass 3D layers need.

Oracle: The fill-extrusion globe tests.

Consolidates from core/projection-property:
- feat(core): render fill-extrusions on the globe (Metal)
- feat(core): render symbols on the globe (Metal)
- refactor(core): review pass over the globe branch
- perf(core): draw the globe depth prepass only when a 3D layer needs it
- fix(core): coarsen a subdivided polygon that would overflow a segment instead of dropping the tile
- refactor(core): second review pass over the globe branch
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
Globe phase 12c of the design proposal (maplibre#4525): Corrective tail: collision debug boxes.

Oracle: The collision-box globe tests.

Consolidates from core/projection-property:
- fix(core): draw collision boxes on the globe
…hase 9f)

Globe phase 9f of the design proposal (maplibre#4525): Stencil clip masks drawn from the globe tile meshes, culled on the far side.

Oracle: Every globe test with overlapping tiles; fill-planet-tiles on an iPhone.

Consolidates from core/projection-property:
- feat(core): clip layers to their tiles on the globe (Metal)
- test(core): port five more GL JS globe render tests
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
- fix(core): cull the far side of the globe clip masks
Globe phase 10c of the design proposal (maplibre#4525): WebGPU globe prelude variant, clip mask, cull modes.

Oracle: The globe tests on the WebGPU manifests (Dawn and wgpu).

Consolidates from core/projection-property:
- feat(core): render the globe on Vulkan, WebGPU and OpenGL
- refactor(core): review pass over the globe branch
- refactor(core): second review pass over the globe branch
- perf(core): drop the globe's mesh caches when the style goes back to Mercator
- fix(webgpu): honour the drawables' cull modes
- fix(core): cull the far side of the globe clip masks
… to every shader group (globe phase 10d)

Globe phase 10d of the design proposal (maplibre#4525): Phase 10, after the three backend ports: the shader-group lookup takes the projection variant as a required parameter ahead of the attribute name on the base class and on the Metal, OpenGL, Vulkan and WebGPU implementations, and every caller passes it explicitly

Oracle: compiles on all four backends; render tests unchanged on every manifest

Consolidates from core/projection-property:
- refactor(core): second review pass over the globe branch
- fix(core): draw the Vulkan globe clip mask with the whole projection block
Globe phase 9i of the design proposal (maplibre#4525): CustomLayerRenderParameters carry the projection; custom drawable layers project on the globe; the depth prepass runs for them.

Oracle: custom; test/api/custom_layer.test.cpp.

Consolidates from core/projection-property:
- feat(core): hand custom layers the globe projection
- test(core): port GL JS's checks into the globe unit tests
- refactor(core): second review pass over the globe branch
- fix(core): project custom drawable layers on the globe
- fix(core): run the globe depth prepass for custom layers
…hase 12b)

Globe phase 12b of the design proposal (maplibre#4525): Corrective tail: image sources.

Oracle: The ported GL JS globe raster tests.

Consolidates from core/projection-property:
- feat(core): render raster, hillshade and color-relief layers on the globe (Metal)
- refactor(core): second review pass over the globe branch
- test(core): port five more GL JS globe render tests
- fix(core): draw image sources on the globe by their own quad
- test(core): port the GL JS globe raster tests
- fix(core): draw tile borders on the globe
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
- test(core): unignore the globe tests Linux OpenGL renders
…d macOS (globe phase 12g)

Globe phase 12g of the design proposal (maplibre#4525): Corrective tail: Map::isLocationOccluded and the SDKs' view-based annotations.

Oracle: Transform.GlobeLocationOcclusion; MLNAnnotationViewTests.

Consolidates from core/projection-property:
- refactor(core): review pass over the globe branch
- refactor(core): second review pass over the globe branch
- fix(core): treat a coordinate behind the globe as offscreen on iOS and macOS
…timeridian (globe phase 12h)

Globe phase 12h of the design proposal (maplibre#4525): Corrective tail: the tile cover's wrap across the antimeridian.

Oracle: Transform.GlobeCenterLongitudeStaysContinuous; TileCover.GlobeCoverSurvivesTheAntimeridian.

Consolidates from core/projection-property:
- fix(core): keep the globe's center longitude continuous across the antimeridian
Globe phase 11b of the design proposal (maplibre#4525): Platform SDK: iOS example app and the iOS Metal expectations an iPhone rasterizes differently.

Oracle: iOS render tests on device; the example app.

Consolidates from core/projection-property:
- test(core): iOS Metal expectations for the globe tests an iPhone rasterizes differently
- feat(ios): add a globe style to the example app
Globe phase 11c of the design proposal (maplibre#4525): Platform SDK: Android test app.

Oracle: compileOpenglDebugKotlin; the test app.

Consolidates from core/projection-property:
- feat(android): add a globe example to the test app
Globe phase 12a of the design proposal (maplibre#4525): Corrective tail: layer translation on the sphere.

Oracle: The *-translate globe tests.

Consolidates from core/projection-property:
- refactor(core): second review pass over the globe branch
- fix(core): apply *-translate on the globe
- test(core): port the GL JS globe raster tests
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
- test(core): unignore the globe tests Linux OpenGL renders
- test(core): rerender the Linux OpenGL expectations without the mask bug
…or the globe (globe phase 5)

Globe phase 5 of the design proposal (maplibre#4525): Subdivision at the generators, tile meshes with pole caps, granularity through the worker.

Oracle: fill-planet-tiles, fill-seams, fill-planet-pole.

Consolidates from core/projection-property:
- feat(core): subdivide fill and line geometry for the globe
- feat(core): tile meshes with pole caps for the globe background; paint 2D layers in order on the globe
- feat(core): unproject, anchored zoom and constrain on the globe
- feat(core): render raster, hillshade and color-relief layers on the globe (Metal)
- feat(core): render fill-extrusions on the globe (Metal)
- refactor(core): review pass over the globe branch
- fix(core): coarsen a subdivided polygon that would overflow a segment instead of dropping the tile
- perf(core): stop copying every line feature's coordinates on Mercator
- test(core): port GL JS's checks into the globe unit tests
- refactor(core): second review pass over the globe branch
- fix(core): draw tile borders on the globe
- fix(core): include <limits> for the segment vertex cap
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
- build(core): include earcut in subdivision.cpp without MSVC's conversion warnings
…e phase 6)

Globe phase 6 of the design proposal (maplibre#4525): Unproject, gestures, easeTo/flyTo, constrain.

Oracle: Unit tests on TransformState (ray-sphere, horizon clamp, pan); the GLFW app by hand.

Consolidates from core/projection-property:
- feat(core): unproject, anchored zoom and constrain on the globe
- feat(core): render raster, hillshade and color-relief layers on the globe (Metal)
- refactor(core): review pass over the globe branch
- feat(core): let the globe zoom out below zero toward the poles
- fix(core): keep minzoom-0 layers and image sources at negative globe zoom
- perf(core): cache the globe view state on the transform state
- fix(core): treat an unknown projection name as Mercator
- test(core): port GL JS's checks into the globe unit tests
- refactor(core): second review pass over the globe branch
- refactor(core): name the projection types
- test(core): keep maxBounds on the globe
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
Globe phase 9g of the design proposal (maplibre#4525): The location indicator layer family on the globe, rebuilt on projection change, quads without an image left undrawn.

Oracle: LocationIndicator.{Mercator,Globe}PuckAtItsLocation.

Consolidates from core/projection-property:
- fix(core): place the location indicator on the globe
- test(core): skip the location-indicator tests where the layer is not registered
- fix(core): rebuild the location indicator when the projection changes
- test(core): skip the globe puck test on OpenGL's own location indicator renderer
- fix(core): keep a location indicator quad without an image out of the draw
Globe phase 9h of the design proposal (maplibre#4525): The debug layer's tile borders on the globe.

Oracle: debug-tile-borders.

Consolidates from core/projection-property:
- fix(core): draw tile borders on the globe
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS antimeridian and seam tests
- test(core): unignore the globe tests Linux OpenGL renders
- test(core): rerender the Linux OpenGL expectations without the mask bug
Globe phase 10a of the design proposal (maplibre#4525): OpenGL globe prelude variant, clip masks, uniform-block tables, Linux OpenGL expectations.

Oracle: The globe tests on the Linux OpenGL manifest.

Consolidates from core/projection-property:
- feat(core): render the globe on Vulkan, WebGPU and OpenGL
- refactor(core): review pass over the globe branch
- feat(core): clip layers to their tiles on the globe (OpenGL)
- fix(core): skip uniform blocks a shader variant does not reference on OpenGL
- refactor(core): second review pass over the globe branch
- test(core): port five more GL JS globe render tests
- fix(gl): set the stencil mode of a 3D layer group that has no clip tiles
- test(core): render the globe tests on Linux OpenGL
- test(core): keep only the tests OpenGL has not rendered in its ignore list
- test(core): put the Linux OpenGL expectations where the runner looks
- fix(gl): bind the projection block for every shader that projects through it
- test(core): unignore the globe tests Linux OpenGL renders
- fix(core): cull the far side of the globe clip masks
- test(core): rerender the Linux OpenGL expectations without the mask bug
- test(core): bundle the Linux OpenGL expectations for the Bazel render test
- refactor(gl): drop the duplicate drawable include from the context
- build(gl): forward-declare the GL passes before befriending them
Globe phase 10b of the design proposal (maplibre#4525): Vulkan globe prelude variant and clip mask.

Oracle: The globe tests on the Vulkan manifests.

Consolidates from core/projection-property:
- feat(core): render the globe on Vulkan, WebGPU and OpenGL
- refactor(core): review pass over the globe branch
- refactor(core): second review pass over the globe branch
- fix(core): cull the far side of the globe clip masks
… (globe phase 12f)

Globe phase 12f of the design proposal (maplibre#4525): Corrective tail: variable anchors and the ported text tests.

Oracle: The text-* globe tests.

Consolidates from core/projection-property:
- test(core): port five more GL JS globe render tests
- fix(core): place variable-anchor labels where the globe collides them
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
- test(core): unignore the globe tests Linux OpenGL renders
…globe phase 12d)

Globe phase 12d of the design proposal (maplibre#4525): Corrective tail: camera behaviours.

Oracle: The ported GL JS camera unit tests.

Consolidates from core/projection-property:
- fix(core): ease, fly and fit bounds on the globe the way GL JS does
- fix(core): zoom around an anchor near the globe's horizon the way GL JS does
…be phase 12e)

Globe phase 12e of the design proposal (maplibre#4525): Corrective tail: the antimeridian and seam tests, with the three residuals ignored for their stated reasons.

Oracle: antimeridian-overdraw, fill-seams.

Consolidates from core/projection-property:
- test(core): port GL JS's checks into the globe unit tests
- test(core): port five more GL JS globe render tests
- fix(core): draw antimeridian-crossing geometry once on the globe
- test(core): port the GL JS antimeridian and seam tests
- test(core): port the GL JS globe text tests
- test(core): unignore the globe tests Linux OpenGL renders
- test(core): ignore the three antimeridian-overdraw residuals with their reasons
… UBO (globe phase 1)

Globe phase 1 of the design proposal (maplibre#4525): Seam: ProjectionBase + ProjectionData through LayerTweaker into the UBOs, Mercator only, all four backends.

Oracle: Every existing render test, every manifest, pixel-identical (allowed unchanged).

Consolidates from core/projection-property:
- refactor(core): introduce the projection seam behind TransformState
- feat(core): carry ProjectionData into a per-drawable projection UBO on all backends
- refactor(core): review pass over the globe branch
- test(core): port GL JS's checks into the globe unit tests
- refactor(core): second review pass over the globe branch
…l family to it (globe phase 2)

Globe phase 2 of the design proposal (maplibre#4525): Prelude functions on all four backends (Mercator variant only); the fill family switched to projectTile.

Oracle: Same: every existing render test pixel-identical.

Consolidates from core/projection-property:
- feat(core): add projectTile() to the shader preludes and switch the fill family to it
Globe phase 3 of the design proposal (maplibre#4525): projection root property: parser, codegen, expression type, Style API, transition scalar plumbed to the (still Mercator) transform.

Oracle: Unit tests on parser and expression; render tests unchanged.

Consolidates from core/projection-property:
- feat(core): parse the projection root style property
- refactor(core): review pass over the globe branch
- fix(core): treat an unknown projection name as Mercator
- test(core): port GL JS's checks into the globe unit tests
- refactor(core): second review pass over the globe branch
- test(core): expect the warning for a non-object projection
- fix(node): convert projection definitions in expression results
…hase 4)

Globe phase 4 of the design proposal (maplibre#4525): Globe prelude variant + VerticalPerspectiveProjection project/tile-matrix on Metal, fill and background only, no subdivision.

Oracle: First ported GL JS globe render tests (fill-planet-solid, background) on the macOS Metal manifest.

Consolidates from core/projection-property:
- feat(core): render fill and background on the globe (Metal)
- feat(core): tile meshes with pole caps for the globe background; paint 2D layers in order on the globe
- refactor(core): review pass over the globe branch
- test(core): port GL JS's checks into the globe unit tests
- refactor(core): second review pass over the globe branch
- test(core): port five more GL JS globe render tests
- docs(core): describe the globe in the projections section
- refactor(core): say why the globe's depth offset is subtracted in clip space
- test(core): render the globe tests on Linux OpenGL
- test(core): port the GL JS globe text tests
- test(core): keep only the tests OpenGL has not rendered in its ignore list
@github-actions github-actions Bot added documentation Improvements or additions to documentation metal build Related to build, configuration or CI/CD android iOS core Changes that affect the C++ core of MapLibre Native node OpenGL Issues related to the OpenGL renderer backend Vulkan WebGPU labels Aug 28, 2026
@ClayWarren
ClayWarren marked this pull request as ready for review August 29, 2026 00:01
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 29, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-29T03:07:15.035473Z 39a9e28 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@ClayWarren
ClayWarren marked this pull request as draft August 29, 2026 00:01

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 72e094d08f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +125 to +131
const shaders::SkyPropsUBO props = {
.sky_color = evaluated->get<style::SkyColor>(),
.horizon_color = evaluated->get<style::SkyHorizonColor>(),
.horizon = horizon,
.horizon_normal = normal,
.viewport_size = {{static_cast<float>(viewportSize.width), static_cast<float>(viewportSize.height)}},
.sky_horizon_blend = evaluated->get<style::SkyHorizonBlend>() * viewportSize.height * 0.5f,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply the exposed fog properties during rendering

When a style or runtime SDK sets fog-color, fog-ground-blend, or horizon-fog-blend, the values and their transitions are evaluated but never consumed by the renderer: this uniform setup reads only SkyColor, SkyHorizonColor, SkyHorizonBlend, and later SkyAtmosphereBlend. Consequently, the three advertised fog APIs silently have no visual effect, particularly in the terrain/globe scenes they are intended to configure; pass their evaluated values into the relevant sky/fog rendering path.

Useful? React with 👍 / 👎.

@ClayWarren
ClayWarren force-pushed the codex/sky-style-spec-4414 branch from 72e094d to e57ca56 Compare August 29, 2026 00:35
Add the sky root-property model, parsing, transitions, observers,
dynamic lookup, generated style bindings, and build registration for
all seven properties.

Keep terrain-dependent fog properties available to the style model
while their pixel rendering remains deferred to Terrain3D.
Add the shared sky render pass plus planar-gradient and physical
atmosphere shaders for OpenGL.

Integrate projection transitions, depth state, and lighting in the
common renderer path.
Port the sky and physical atmosphere shaders to Metal and register
their drawable and build-system integration.
Port the sky and physical atmosphere shaders to Vulkan and register
their drawable and build-system integration.
Port the sky and physical atmosphere shaders to WebGPU and register
their drawable and Bazel/CMake integration.
Cover defaults, setters, transitions, expressions, style replacement
and removal, and representative planar and globe GPU output.
Generate Android sky style APIs for all seven root properties, including expressions and transitions.

Wire nullable style access, JNI ownership, changelog coverage, and instrumentation tests.
Generate iOS and macOS sky APIs with expression and transition support.

Expose nullable style access, framework headers, changelogs, and generated tests.
Apply the pinned clang-format hook to generated Android sky registration and Darwin umbrella imports.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39a9e28994

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/mln/style/style.cpp
Comment on lines +94 to +98
void Style::setProjection(std::unique_ptr<Projection> projection) {
impl->setProjection(std::move(projection));
}

Projection* Style::getProjection() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve projection edits during style revalidation

Both new projection mutation entry points omit impl->mutated = true, unlike the corresponding sky and other mutable-style APIs. When a URL-loaded style receives a cached response followed by a refreshed response, changing the projection through getProjection()->setType(...) or setProjection(...) therefore leaves the guard in Style::Impl::loadURL disabled, allowing the later response to silently overwrite the application’s projection choice; mark these paths as mutations.

Useful? React with 👍 / 👎.

Comment on lines +163 to +168
mat4 matrix;
matrix::perspective(matrix,
state.getFieldOfView(),
static_cast<double>(size.width) / size.height,
0.5,
cameraToCenterDistance + radius * 2.0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply the flipped viewport mode to the globe matrix

When a map is configured with ViewportMode::FlippedY, the Mercator matrix flips Y via Camera::getWorldToCamera, but this newly introduced globe matrix is built identically for both viewport modes. Consequently globe rendering and globe screen/coordinate conversion retain the default Y orientation in embedding environments that require a flipped viewport, even though changing the mode invalidates the matrices; incorporate state.getViewportMode() into this matrix construction.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

android build Related to build, configuration or CI/CD core Changes that affect the C++ core of MapLibre Native documentation Improvements or additions to documentation iOS metal node OpenGL Issues related to the OpenGL renderer backend Vulkan WebGPU

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants