Companion
Properties
CustomLayerRenderParameters.zoom for the frame currently being rendered in com.mapbox.maps.CustomLayerHost.render. Cleared after render.
Last CustomLayerRenderParameters.zoom from CustomLayerMatrixBridge.pushToCameraSync. Not cleared with customLayerRenderZoom so async CPU work (instanced wind gather) uses the same Mercator scale as the custom-layer projection matrices instead of MapboxMap.cameraState.zoom, which can diverge during pinch-zoom and causes rapid sub-pixel jitter.
Filled by CustomLayerMatrixBridge each com.mapbox.maps.CustomLayerHost.render frame. Encoded raster com.xweather.mapsgl.gl.RenderPass uses these (paired) so tiles share the same clip-space transform as the Mapbox basemap under pitch/bearing; do not mix with camera projection/view for that path.
Functions
Scale (tile zoom) then bearing (Z) then pitch (X), using post-multiplication so each rotation applies in map/tangent space: M = T_scale × R_z(-bearing) × R_x(pitch). The previous left-multiplication chain (R_x × R_z × T) put the map plane in the wrong orientation relative to the perspective camera except at specific bearing/pitch combos.
CPU instance Mercator XY uses world pixels at zBuild (512×2^zBuild). Custom-layer P/MV are for zoomForCustomLayerInstancing. Apply this factor to stored positions in the vertex shader so they match the current matrices between async instance rebuilds (removes zoom jitter).
Zoom aligned with Mapbox custom-layer CustomLayerRenderParameters for this frame / last render.