Skip to main content

wde_terrain/render/dependencies/
terrain_mesh.rs

1use bevy::prelude::*;
2use wde_renderer::prelude::*;
3
4use crate::{
5    manager::{CHUNK_RENDER_SUBDIVISIONS, CHUNK_SIZE},
6    render::renderer::TERRAIN_LOD_COUNT
7};
8
9/// Flat chunk grids, one per level of detail, displaced by the heightmaps in the vertex shader.
10#[derive(Resource, Default)]
11pub struct TerrainRenderPassMesh {
12    pub lod_meshes: Vec<Handle<Mesh>>
13}
14impl TerrainRenderPassMesh {
15    // Creates the rendering meshes.
16    pub fn init(assets_server: Res<AssetServer>, mut render_pass: ResMut<TerrainRenderPassMesh>) {
17        render_pass.lod_meshes = (0..TERRAIN_LOD_COUNT)
18            .map(|lod| {
19                let subdivisions = CHUNK_RENDER_SUBDIVISIONS >> lod;
20                let mut mesh = PlaneMesh::from(
21                    &format!("terrain_tile_lod{lod}"),
22                    subdivisions,
23                    Vec3::Y,
24                    false
25                );
26                // Cover the chunk, UVs in [0, 1] landing on the heightmap samples
27                for vertex in &mut mesh.vertices {
28                    vertex.position[0] *= CHUNK_SIZE;
29                    vertex.position[2] *= CHUNK_SIZE;
30                    vertex.uv[0] = vertex.position[0] / CHUNK_SIZE + 0.5;
31                    vertex.uv[1] = vertex.position[2] / CHUNK_SIZE + 0.5;
32                }
33                assets_server.add(mesh)
34            })
35            .collect();
36    }
37
38    // Extracts the mesh handles to the render world.
39    pub fn extract_terrain_mesh(
40        mesh_cpu: ExtractWorld<Res<TerrainRenderPassMesh>>,
41        mut mesh: ResMut<TerrainRenderPassMesh>
42    ) {
43        if mesh.lod_meshes.is_empty() && !mesh_cpu.lod_meshes.is_empty() {
44            mesh.lod_meshes = mesh_cpu.lod_meshes.clone();
45        }
46    }
47}