wde_terrain/render/dependencies/
terrain_buffer.rs1use bevy::{ecs::system::SystemParamItem, prelude::*};
2use wde_renderer::prelude::*;
3
4use crate::{
5 manager::{CHUNK_HEIGHT, CHUNK_RENDER_SUBDIVISIONS, CHUNK_SIZE},
6 render::renderer_gpu::TerrainRendererGPU
7};
8
9const MAX_TERRAIN_TILES: usize = 1000;
11
12#[repr(C)]
13#[derive(Clone, Copy, Debug, bytemuck::Pod, bytemuck::Zeroable)]
14pub struct TerrainDescription {
15 pub tile_size: [f32; 3],
16 pub tile_subdivisions: f32
17}
18#[repr(C)]
19#[derive(Clone, Copy, Debug, bytemuck::Pod, bytemuck::Zeroable)]
20pub struct TerrainTileDescription {
21 pub pos: [f32; 2],
22 pub lod: f32,
23 pub _padding: f32
24}
25
26#[derive(Asset, Clone, Debug, Default, TypePath)]
28pub struct TerrainBuffer;
29impl TerrainBuffer {
30 pub const DESC_BIND: u32 = 0;
31 pub const TILES_BIND: u32 = 1;
32}
33impl RenderData for TerrainBuffer {
34 type Params = ();
35
36 fn describe(_params: &mut SystemParamItem<Self::Params>, builder: &mut RenderDataBuilder) {
37 builder.add_buffer(
38 Self::DESC_BIND,
39 Buffer {
40 label: "ssbo-terrain-description-buffer".to_string(),
41 size: std::mem::size_of::<TerrainDescription>(),
42 usage: BufferUsage::UNIFORM | BufferUsage::COPY_DST,
43 content: Some(
44 bytemuck::cast_slice(&[TerrainDescription {
45 tile_size: [CHUNK_SIZE, CHUNK_HEIGHT, CHUNK_SIZE],
46 tile_subdivisions: CHUNK_RENDER_SUBDIVISIONS as f32
47 }])
48 .into()
49 )
50 }
51 );
52 builder.add_buffer(
53 Self::TILES_BIND,
54 Buffer {
55 label: "ssbo-terrain-tiles-buffer".to_string(),
56 size: std::mem::size_of::<TerrainTileDescription>() * MAX_TERRAIN_TILES,
57 usage: BufferUsage::STORAGE | BufferUsage::COPY_DST,
58 content: None
59 }
60 );
61 }
62}
63
64#[derive(Asset, Clone, TypePath, Default)]
65pub struct TerrainBufferBinding;
66impl RenderBinding for TerrainBufferBinding {
67 type Params = SRenderData<TerrainBuffer>;
68
69 fn describe(
70 &mut self,
71 buffer: &SystemParamItem<Self::Params>,
72 builder: &mut RenderBindingBuilder
73 ) {
74 builder.add_buffer(buffer, TerrainBuffer::DESC_BIND);
75 builder.add_buffer(buffer, TerrainBuffer::TILES_BIND);
76 }
77
78 fn label(&self) -> &str {
79 "terrain_buffer_binding"
80 }
81}
82
83pub(crate) fn update_terrain_tiles_buffer(
85 render_instance: Res<RenderInstance>,
86 terrain_buffer: ResRenderData<TerrainBuffer>,
87 buffers: Res<RenderAssets<GpuBuffer>>,
88 terrain_tiles: Res<TerrainRendererGPU>,
89 mut is_set: Local<bool>
90) {
91 if *is_set || !terrain_tiles.ready {
93 return;
94 }
95
96 let terrain_buffer = match terrain_buffer.iter().next() {
98 Some((_, buffer)) => buffer,
99 None => return
100 };
101 let tile_buffer = match buffers.get(
102 &terrain_buffer
103 .get_buffer(TerrainBuffer::TILES_BIND)
104 .unwrap()
105 ) {
106 Some(buffer) => buffer,
107 None => return
108 };
109
110 let data: Vec<TerrainTileDescription> = terrain_tiles
112 .tiles
113 .iter()
114 .map(|tile| TerrainTileDescription {
115 pos: [tile.position.x as f32, tile.position.y as f32],
116 lod: 1.0,
117 _padding: 0.0
118 })
119 .collect();
120
121 let render_instance = render_instance.0.read().unwrap();
123 tile_buffer
124 .buffer
125 .write(&render_instance, bytemuck::cast_slice(&data), 0);
126
127 *is_set = true;
128}