feat(client): implement face culling and voxel rendering
This commit is contained in:
parent
203cc2a671
commit
61a7fb0ed5
|
|
@ -14,3 +14,5 @@ winit = "0.30.13"
|
||||||
renderer = { path = "../renderer" }
|
renderer = { path = "../renderer" }
|
||||||
raw-window-handle = "0.6.2"
|
raw-window-handle = "0.6.2"
|
||||||
ash-window = "0.13.0"
|
ash-window = "0.13.0"
|
||||||
|
serde_json = "1.0.149"
|
||||||
|
shared = { version = "0.1.0", path = "../shared" }
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
//!
|
//!
|
||||||
//! This crate handles window creation, input processing, and drives the
|
//! This crate handles window creation, input processing, and drives the
|
||||||
//! renderer to display the game world.
|
//! renderer to display the game world.
|
||||||
|
mod meshing;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||||
|
|
@ -75,6 +76,24 @@ impl ApplicationHandler for App {
|
||||||
|
|
||||||
self.window = Some(window);
|
self.window = Some(window);
|
||||||
self.renderer = Some(renderer);
|
self.renderer = Some(renderer);
|
||||||
|
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
|
let config_str = std::fs::read_to_string("assets/data/worldgen/default.json")
|
||||||
|
.expect("Failed to read worldgen config");
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
|
let worldgen_config: shared::generator::WorldGenConfig = serde_json::from_str(&config_str)
|
||||||
|
.expect("Failed to parse worldgen config");
|
||||||
|
|
||||||
|
let seed = 4_813_530;
|
||||||
|
|
||||||
|
let generator = shared::generator::VoxelGenerator::new(worldgen_config, seed);
|
||||||
|
let chunk = generator.generate_chunk(shared::world::ChunkPos::new(0, 0, 0));
|
||||||
|
|
||||||
|
let (vertices, indices) = meshing::generate_mesh(&chunk);
|
||||||
|
tracing::info!("Generated Mesh with {} vertices and {} indices!", vertices.len(), indices.len());
|
||||||
|
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
|
self.renderer.as_mut().expect("Renderer initialized").update_mesh(&vertices, &indices).expect("Failed to upload terrain to GPU");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
|
fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
|
||||||
|
|
|
||||||
90
crates/client/src/meshing.rs
Normal file
90
crates/client/src/meshing.rs
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
use shared::world::{BlockId, CHUNK_SIZE, Chunk};
|
||||||
|
use renderer::mesh::Vertex;
|
||||||
|
|
||||||
|
#[allow(clippy::cast_precision_loss, clippy::cast_possible_truncation)]
|
||||||
|
pub fn generate_mesh(chunk: &Chunk) -> (Vec<Vertex>, Vec<u32>) {
|
||||||
|
let mut vertices = Vec::new();
|
||||||
|
let mut indices = Vec::new();
|
||||||
|
|
||||||
|
for x in 0..CHUNK_SIZE {
|
||||||
|
for y in 0..CHUNK_SIZE {
|
||||||
|
for z in 0..CHUNK_SIZE {
|
||||||
|
let block = chunk.get(x, y, z);
|
||||||
|
|
||||||
|
if block == BlockId::AIR {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let fx = x as f32;
|
||||||
|
let fy = y as f32;
|
||||||
|
let fz = z as f32;
|
||||||
|
|
||||||
|
if y == CHUNK_SIZE - 1 || chunk.get(x, y + 1, z) == BlockId::AIR {
|
||||||
|
let base_idx = vertices.len() as u32;
|
||||||
|
|
||||||
|
vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz + 0.5], color: [0.2, 0.8, 0.2] });
|
||||||
|
vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz + 0.5], color: [0.2, 0.8, 0.2] });
|
||||||
|
vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz - 0.5], color: [0.2, 0.8, 0.2] });
|
||||||
|
vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz - 0.5], color: [0.2, 0.8, 0.2] });
|
||||||
|
|
||||||
|
indices.extend_from_slice(&[
|
||||||
|
base_idx, base_idx + 1, base_idx + 2,
|
||||||
|
base_idx + 2, base_idx + 3, base_idx,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if y == 0 || chunk.get(x, y - 1, z) == BlockId::AIR {
|
||||||
|
let base_idx = vertices.len() as u32;
|
||||||
|
|
||||||
|
vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz - 0.5], color: [0.1, 0.4, 0.1] });
|
||||||
|
vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz - 0.5], color: [0.1, 0.4, 0.1] });
|
||||||
|
vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz + 0.5], color: [0.1, 0.4, 0.1] });
|
||||||
|
vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz + 0.5], color: [0.1, 0.4, 0.1] });
|
||||||
|
indices.extend_from_slice(&[base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if x == CHUNK_SIZE - 1 || chunk.get(x + 1, y, z) == BlockId::AIR {
|
||||||
|
let base_idx = vertices.len() as u32;
|
||||||
|
|
||||||
|
vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz + 0.5], color: [0.15, 0.6, 0.15] });
|
||||||
|
vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz - 0.5], color: [0.15, 0.6, 0.15] });
|
||||||
|
vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz - 0.5], color: [0.15, 0.6, 0.15] });
|
||||||
|
vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz + 0.5], color: [0.15, 0.6, 0.15] });
|
||||||
|
indices.extend_from_slice(&[base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if x == 0 || chunk.get(x - 1, y, z) == BlockId::AIR {
|
||||||
|
let base_idx = vertices.len() as u32;
|
||||||
|
|
||||||
|
vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz - 0.5], color: [0.15, 0.6, 0.15] });
|
||||||
|
vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz + 0.5], color: [0.15, 0.6, 0.15] });
|
||||||
|
vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz + 0.5], color: [0.15, 0.6, 0.15] });
|
||||||
|
vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz - 0.5], color: [0.15, 0.6, 0.15] });
|
||||||
|
indices.extend_from_slice(&[base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if z == CHUNK_SIZE - 1 || chunk.get(x, y, z + 1) == BlockId::AIR {
|
||||||
|
let base_idx = vertices.len() as u32;
|
||||||
|
|
||||||
|
vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz + 0.5], color: [0.18, 0.7, 0.18] });
|
||||||
|
vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz + 0.5], color: [0.18, 0.7, 0.18] });
|
||||||
|
vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz + 0.5], color: [0.18, 0.7, 0.18] });
|
||||||
|
vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz + 0.5], color: [0.18, 0.7, 0.18] });
|
||||||
|
indices.extend_from_slice(&[base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if z == 0 || chunk.get(x, y, z - 1) == BlockId::AIR {
|
||||||
|
let base_idx = vertices.len() as u32;
|
||||||
|
|
||||||
|
vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz - 0.5], color: [0.18, 0.7, 0.18] });
|
||||||
|
vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz - 0.5], color: [0.18, 0.7, 0.18] });
|
||||||
|
vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz - 0.5], color: [0.18, 0.7, 0.18] });
|
||||||
|
vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz - 0.5], color: [0.18, 0.7, 0.18] });
|
||||||
|
indices.extend_from_slice(&[base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(vertices, indices)
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue