diff --git a/src/app/world_gen.rs b/src/app/world_gen.rs index e681d44..e315980 100644 --- a/src/app/world_gen.rs +++ b/src/app/world_gen.rs @@ -1,10 +1,12 @@ use cgmath::{Point3, InnerSpace}; use noise::{Perlin, NoiseFn}; -use rand::Rng; +use rand::{Rng, prelude::ThreadRng}; use crate::renderer::Level; use crate::renderer::buffers::{BLOCK_SIZE, NODE_TEX_SIZE, Block}; +const SCALE: f64 = 150.0; + pub struct WorldGen { @@ -16,85 +18,63 @@ impl WorldGen { Self{} } + /* + * Generate height map for given block position + */ + fn gen_height_map(x: usize, z: usize, rand: &mut ThreadRng, noise: &Perlin) -> ([[usize;BLOCK_SIZE]; BLOCK_SIZE], usize) { + let x = x * BLOCK_SIZE; + let z = z * BLOCK_SIZE; + + // Generate map + let mut max: usize = 0; + let mut map = [[0_usize; BLOCK_SIZE]; BLOCK_SIZE]; + for lx in 0..BLOCK_SIZE { + for lz in 0..BLOCK_SIZE { + let value = (noise.get([(x + lx) as f64 / SCALE, (z + lz) as f64 /SCALE]) + 1.0) / 2.0; + let mut h = (value * 30.0) as usize + 1; + h += (rand.gen::() * 2.0) as usize; + if h > max { max = h; } + map[lx][lz] = h; + } + } + (map, max) + } /* * Generate world */ pub fn generate(&mut self, level: &mut dyn Level, noise: &Perlin) { - - const SCALE: f64 = 150.0; let mut rng = rand::thread_rng(); + let mut dirty: Vec = Vec::new(); - - for bx in 0..16 { - for bz in 0..16 { - - for x in 0..BLOCK_SIZE { - for z in 0..BLOCK_SIZE { - // world x,z - let wx = bx * BLOCK_SIZE + x; - let wz = bz * BLOCK_SIZE + z; - // world h - let value1 = (noise.get([wx as f64 /SCALE*2.0, wz as f64 /SCALE*2.0]) + 1.0) / 1.5 - 0.6; - let value2 = (noise.get([wx as f64 /SCALE, wz as f64 /SCALE]) + 1.0) / 2.0; - let value = if value1 > value2 { value1 } else {value2}; - - let mut wh = (value * 40.0) as usize + 1; - wh += (rng.gen::() * 2.0) as usize; - - // fill column - for wy in 0..wh { - let y = wy % BLOCK_SIZE; - let by = wy / BLOCK_SIZE; - let val = if wy == wh-1 { 2 } else { 1 }; - - level.block_get(Point3{x:bx, y:by, z:bz}).set(Point3{x, y, z}, val); + for bx in 0..48 { + for bz in 0..48 { + // Generate height map + let (map, max) = WorldGen::gen_height_map(bx, bz, &mut rng, noise); + let bh = max % BLOCK_SIZE; + // Generate blocks + for by in 0..bh { + // Get + let b = level.block_get(Point3{x:bx, y:by, z:bz}); + dirty.push(b.id); + // Fill + for x in 0..BLOCK_SIZE { + for z in 0..BLOCK_SIZE { + // TODO + let h = map[x][z]; + for y in 0..h { + let val = if y+1 == h { 2 } else { 1 }; + b.set(Point3{x, y, z}, val); + } } } } + } } - - // let mut rng = rand::thread_rng(); - // let mut apply = false; - - - // let voxel_pos = pos * BLOCK_SIZE; - - // // Genereate grass - // if pos.y < 1 { - // for x in 0..32 { - // for z in 0..32 { - // let wx = voxel_pos.x + x; - // let wz = voxel_pos.z + z; - - // let value = (noise.get([wx as f64 * 0.0123, wz as f64 * 0.0123]) + 1.0) / 2.0; - // let h = (value * 30.0) as usize + 1; - - // for y in 0..h { - // renderer.block_set_voxel(block_id, x, y, z, 2); - // } - // } - // } - // apply = true; - // } - - // // Generate wall - // if pos.x == 8 && pos.y < 3 && pos.z < 8 && pos.z > 4 { - // for z in 0..32 { - // for y in 0..32 { - // renderer.block_set_voxel(block_id, 16, y, z, 3); - // } - // } - // apply = true; - // } - - // // Apply - // if apply { - // if block_id != renderer.block_get_id(pos, true) { - // panic!("Block already consumed?"); - // } - // } + for id in dirty { + level.block_dirty(id); + } } } \ No newline at end of file diff --git a/src/renderer/buffers/blocks.rs b/src/renderer/buffers/blocks.rs index 5a6cbe2..1e3ed60 100644 --- a/src/renderer/buffers/blocks.rs +++ b/src/renderer/buffers/blocks.rs @@ -99,7 +99,9 @@ impl Blocks { } pub fn write_id(&mut self, queue: &wgpu::Queue, block_id: usize) { - let block = self.get(block_id).unwrap(); + + // Get block from id + let block = &self.blocks[block_id]; // Calculate block position in texture let y = (block.id%BLOCK_TEX_SIZE * BLOCK_SIZE) as u32; @@ -117,6 +119,10 @@ impl Blocks { ); } + pub fn get(&mut self, block_id: usize) -> &mut Block { + &mut self.blocks[block_id] + } + // /* // Write block data to gpu, should be called to apply changes // */ @@ -147,16 +153,4 @@ impl Blocks { self.free_block += 1; &mut self.blocks[self.free_block - 1] } - - /* - * Gets block with id - */ - pub fn get(&mut self, id: usize) -> Option<&mut Block> { - for b in self.blocks.iter_mut() { - if b.id == id { - return Some(b); - } - } - None - } } \ No newline at end of file diff --git a/src/renderer/buffers/mod.rs b/src/renderer/buffers/mod.rs index 67716a9..115566f 100644 --- a/src/renderer/buffers/mod.rs +++ b/src/renderer/buffers/mod.rs @@ -8,7 +8,7 @@ pub const NODE_TEX_SIZE: usize = 48; // 32x32x32 nodes in texture pub const NODE_TEX_LEN: usize = NODE_TEX_SIZE*NODE_TEX_SIZE*NODE_TEX_SIZE; // Number of u32 in node texture pub const BLOCK_LEN : usize = BLOCK_SIZE*BLOCK_SIZE*BLOCK_SIZE; // Number of u8 in one block -pub const BLOCK_ARR_LEN: usize = BLOCK_TEX_SIZE*BLOCK_TEX_SIZE; // Number of blocks in texture +pub const BLOCK_ARR_LEN: usize = NODE_TEX_SIZE*NODE_TEX_SIZE; // Number of blocks in texture pub const BLOCK_TEX_LEN: usize = BLOCK_TEX_SIZE*BLOCK_TEX_SIZE * BLOCK_LEN; // Number of u8 in block texture diff --git a/src/renderer/level.rs b/src/renderer/level.rs index 82225ce..9629f8f 100644 --- a/src/renderer/level.rs +++ b/src/renderer/level.rs @@ -4,7 +4,7 @@ use crate::renderer::{Renderer, buffers}; pub trait Level { fn block_get(&mut self, block_pos: Point3) -> &mut buffers::Block; - fn block_dirty(&mut self, block: &buffers::Block); + fn block_dirty(&mut self, id: usize); } impl Level for Renderer { @@ -17,15 +17,17 @@ impl Level for Renderer { // Allocate new block if node_value == 0 { let block = self.buffers.brick_buffer.alloc(); - self.buffers.node_buffer.nodes[node_idx] = block.id as u32; + self.buffers.node_buffer.nodes[node_idx] = (block.id+1) as u32; return block; } // Return existing block - self.buffers.brick_buffer.get(node_idx).unwrap() + self.buffers.brick_buffer.get((node_value-1) as usize) } - fn block_dirty(&mut self, block: &buffers::Block) { - self.changed_bricks.push(block.id); + fn block_dirty(&mut self, id: usize) { + if !self.changed_bricks.contains(&id) { + self.changed_bricks.push(id); + } } } \ No newline at end of file diff --git a/src/shaders/raytrace/.bin/main.frag.spv b/src/shaders/raytrace/.bin/main.frag.spv index 35ac2de..412d9d8 100644 Binary files a/src/shaders/raytrace/.bin/main.frag.spv and b/src/shaders/raytrace/.bin/main.frag.spv differ diff --git a/src/shaders/raytrace/main.frag b/src/shaders/raytrace/main.frag index a296136..007b93e 100644 --- a/src/shaders/raytrace/main.frag +++ b/src/shaders/raytrace/main.frag @@ -62,7 +62,7 @@ vec3 solve() // Calculate ray direction vec3 view_dir = (_ProjMatrixInv * vec4(_InUV, 0, 1)).xyz; vec3 rayDir = normalize(_ViewMatrix * vec4(view_dir,0)).xyz; - Ray primaryRay = Ray(_CamPos / SCALE, rayDir); + Ray primaryRay = Ray((_CamPos + vec3(16, 0, 16)) / SCALE, rayDir); // Raycast HitResult primary = castNodes(primaryRay, 100);