maplibre/background/
queue_system.rs

1use wgpu::util::DeviceExt;
2
3use crate::{
4    context::MapContext,
5    render::{
6        render_phase::{DrawState, LayerItem, RenderPhase},
7        shaders::BackgroundLayerMetadata,
8    },
9    style::layer::LayerPaint,
10    tcs::system::{SystemError, SystemResult},
11};
12
13pub struct BackgroundBuffers {
14    pub metadata_buffer: wgpu::Buffer,
15}
16
17use super::render_commands::DrawBackground;
18
19pub fn queue_system(
20    MapContext {
21        world,
22        style,
23        renderer,
24        ..
25    }: &mut MapContext,
26) -> SystemResult {
27    let Some(mut layer_item_phase) = world.resources.get_mut::<RenderPhase<LayerItem>>() else {
28        return Err(SystemError::Dependencies);
29    };
30
31    let mut metadatas = Vec::new();
32
33    // Note: Background layer is uniquely not tied to any tiles.
34    // We just iterate through the style layers and issue a single quad draw for each background layer.
35    for layer in &style.layers {
36        if layer.type_ == "background" {
37            let c: [f32; 4] = match &layer.paint {
38                Some(paint @ LayerPaint::Background(_)) => paint
39                    .get_color()
40                    .map(|c| c.into())
41                    .unwrap_or([0.0, 0.0, 0.0, 1.0]),
42                _ => [0.0, 0.0, 0.0, 1.0],
43            };
44            let color = [c[0] as f32, c[1] as f32, c[2] as f32, c[3] as f32];
45            let z_index = layer.index as f32;
46            metadatas.push(BackgroundLayerMetadata { color, z_index });
47
48            layer_item_phase.add(LayerItem {
49                draw_function: Box::new(DrawState::<LayerItem, DrawBackground>::new())
50                    as Box<dyn crate::render::render_phase::Draw<LayerItem>>,
51                index: layer.index,
52                is_line: false,
53                style_layer: layer.id.clone(),
54                source_shape: crate::render::tile_view_pattern::TileShape::default(),
55
56                // We provide a dummy tile for background.
57                tile: crate::tcs::tiles::Tile {
58                    coords: crate::coords::WorldTileCoords::default(),
59                },
60            });
61        }
62    }
63
64    if !metadatas.is_empty() {
65        let buffer = renderer
66            .device
67            .create_buffer_init(&wgpu::util::BufferInitDescriptor {
68                label: Some("Background Metadata Buffer"),
69                contents: bytemuck::cast_slice(&metadatas),
70                usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
71            });
72        world.resources.insert(BackgroundBuffers {
73            metadata_buffer: buffer,
74        });
75    }
76
77    Ok(())
78}