Moved node buffer logic to Nodes struct
This commit is contained in:
@@ -104,7 +104,6 @@ impl Game {
|
||||
}
|
||||
|
||||
// Send dirty chunks to renderer
|
||||
// TODO: Only send chunks in rendering range
|
||||
// TODO: Unload chunks above certain radius
|
||||
self.world.update();
|
||||
for (pos, chunk) in self.world.all_chunks() {
|
||||
|
||||
@@ -4,17 +4,15 @@ use std::convert::TryInto;
|
||||
use cgmath::Vector3;
|
||||
use std::cmp::{min, max};
|
||||
use crate::game::world::block::WorldBlock;
|
||||
use super::nodes::{Nodes, NODE_TEX_SIZE, NODE_TEX_SIZE_QB};
|
||||
|
||||
//note: remember to update in main.frag
|
||||
pub const BLOCK_SIZE : usize = 32; // 32x32x32 block size
|
||||
pub const BLOCK_TEX_SIZE : usize = 40; // number of blocks in texture (32^3 = 1GB, 40^3 = 2GB)
|
||||
pub const NODE_TEX_SIZE: usize = 128; // 32x32x32 nodes in texture
|
||||
const BLOCK_SIZE_QB: usize = BLOCK_SIZE*BLOCK_SIZE*BLOCK_SIZE;
|
||||
|
||||
const BLOCK_TEX_SIZE_SQ: usize = BLOCK_TEX_SIZE*BLOCK_TEX_SIZE;
|
||||
const BLOCK_TEX_SIZE_QB: usize = BLOCK_TEX_SIZE*BLOCK_TEX_SIZE*BLOCK_TEX_SIZE;
|
||||
const NODE_TEX_SIZE_SQ: usize = NODE_TEX_SIZE*NODE_TEX_SIZE;
|
||||
const NODE_TEX_SIZE_QB: usize = NODE_TEX_SIZE*NODE_TEX_SIZE*NODE_TEX_SIZE;
|
||||
|
||||
|
||||
pub struct ContentStats {
|
||||
pub node_tex_size: f64, // MB
|
||||
@@ -26,9 +24,8 @@ pub struct ContentStats {
|
||||
}
|
||||
|
||||
pub struct Content {
|
||||
node_buffer: Box<[u32]>,
|
||||
nodes: Nodes,
|
||||
node_texture: wgpu::Texture,
|
||||
node_dirty: bool,
|
||||
block_freed: Vec<u32>,
|
||||
block_freeidx: usize,
|
||||
block_texture: wgpu::Texture,
|
||||
@@ -39,9 +36,6 @@ pub struct Content {
|
||||
impl Content {
|
||||
|
||||
pub fn new(device: &wgpu::Device) -> Self {
|
||||
// Create node buffer
|
||||
let node_buffer = vec![0_u32; (NODE_TEX_SIZE*NODE_TEX_SIZE*NODE_TEX_SIZE) as usize].into_boxed_slice();
|
||||
|
||||
// Create textures
|
||||
let node_texture = device.create_texture(
|
||||
&wgpu::TextureDescriptor {
|
||||
@@ -87,10 +81,11 @@ impl Content {
|
||||
);
|
||||
|
||||
// Done
|
||||
let nodes = Nodes::new();
|
||||
let block_freeidx = 0;
|
||||
let node_dirty = false;
|
||||
let block_freed = Vec::new();
|
||||
Self { node_buffer, node_dirty, block_freed, node_texture, block_freeidx, block_texture, bind_layout, bind_group }
|
||||
Self { nodes, block_freed, node_texture, block_freeidx, block_texture, bind_layout, bind_group }
|
||||
}
|
||||
|
||||
pub fn stats(&self) -> ContentStats {
|
||||
@@ -115,7 +110,7 @@ impl Content {
|
||||
|
||||
// Get node
|
||||
let index = (block_pos.x + NODE_TEX_SIZE as i32 * (block_pos.y + NODE_TEX_SIZE as i32 * block_pos.z)) as usize;
|
||||
let mut value = self.node_buffer[index] as usize;
|
||||
let mut value = self.nodes.get_node(index) as usize;
|
||||
|
||||
// Allocate new block
|
||||
if value == 0 {
|
||||
@@ -127,10 +122,8 @@ impl Content {
|
||||
}
|
||||
|
||||
// Assign
|
||||
self.node_buffer[index] = value as u32;
|
||||
self.block_freeidx = value;
|
||||
// Mark node buffer as dirty
|
||||
self.node_dirty = true;
|
||||
self.nodes.set_node(index, value as u32);
|
||||
}
|
||||
|
||||
// Calculate position in block texture
|
||||
@@ -152,54 +145,33 @@ impl Content {
|
||||
}
|
||||
|
||||
pub fn shift(&mut self, offset: &Vector3<i32>) {
|
||||
let timer = Instant::now();
|
||||
let mut result = vec![0_u32; self.node_buffer.len()].into_boxed_slice();
|
||||
let (ox, oy, oz) = (offset.x, offset.y, offset.z);
|
||||
let size = NODE_TEX_SIZE as i32;
|
||||
// let timer = Instant::now();
|
||||
// let mut result = vec![0_u32; self.node_buffer.len()].into_boxed_slice();
|
||||
// let (ox, oy, oz) = (offset.x, offset.y, offset.z);
|
||||
// let size = NODE_TEX_SIZE as i32;
|
||||
|
||||
let a = max(0, -oz);
|
||||
let b = min(size-oz, size);
|
||||
println!("from {} to {}", a, b);
|
||||
// let a = max(0, -oz);
|
||||
// let b = min(size-oz, size);
|
||||
// println!("from {} to {}", a, b);
|
||||
|
||||
for x in max(0, -ox)..min(size-ox, size) {
|
||||
for y in max(0, -oy)..min(size-oy, size) {
|
||||
for z in max(0, -oz)..min(size-oz, size) {
|
||||
let idx0 = x + size * (y + size * z);
|
||||
let idx1 = (x+ox) + size * ((y+oy) + size * (z+oz));
|
||||
result[idx1 as usize] = self.node_buffer[idx0 as usize];
|
||||
}
|
||||
}
|
||||
}
|
||||
// for x in max(0, -ox)..min(size-ox, size) {
|
||||
// for y in max(0, -oy)..min(size-oy, size) {
|
||||
// for z in max(0, -oz)..min(size-oz, size) {
|
||||
// let idx0 = x + size * (y + size * z);
|
||||
// let idx1 = (x+ox) + size * ((y+oy) + size * (z+oz));
|
||||
// result[idx1 as usize] = self.node_buffer[idx0 as usize];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
self.node_buffer = result;
|
||||
self.node_dirty = true;
|
||||
println!("Shifted node buffer by {:?} in {} ms", offset, timer.elapsed().as_millis());
|
||||
// self.node_buffer = result;
|
||||
// self.node_dirty = true;
|
||||
// println!("Shifted node buffer by {:?} in {} ms", offset, timer.elapsed().as_millis());
|
||||
}
|
||||
|
||||
fn write_nodes(&mut self, queue: &wgpu::Queue, z: usize) {
|
||||
// Convert u32 node buffer to u8
|
||||
let node_origin = wgpu::Origin3d{ x:0, y: 0, z: z as u32 };
|
||||
let node_size = wgpu::Extent3d { width: NODE_TEX_SIZE as u32, height: NODE_TEX_SIZE as u32, depth: 1 };
|
||||
let mut node_bytes = [0_u8; NODE_TEX_SIZE_SQ*4];
|
||||
let offset = NODE_TEX_SIZE_SQ*z;
|
||||
LittleEndian::write_u32_into(&self.node_buffer[offset..offset+NODE_TEX_SIZE_SQ], &mut node_bytes);
|
||||
|
||||
// Write nodes
|
||||
queue.write_texture(
|
||||
wgpu::TextureCopyView { texture: &self.node_texture, mip_level: 0, origin: node_origin }, &node_bytes,
|
||||
wgpu::TextureDataLayout { offset: 0, bytes_per_row: 4*node_size.width, rows_per_image: node_size.height }, node_size
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
pub fn update(&mut self, queue: &wgpu::Queue) {
|
||||
if self.node_dirty {
|
||||
self.node_dirty = false;
|
||||
|
||||
let timer = Instant::now();
|
||||
for z in 0..NODE_TEX_SIZE {
|
||||
self.write_nodes(queue, z);
|
||||
}
|
||||
println!("Write nodes: {}", timer.elapsed().as_secs_f32());
|
||||
}
|
||||
self.nodes.update(queue, &self.node_texture);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ pub mod content;
|
||||
pub use content::Content;
|
||||
mod materials;
|
||||
pub use materials::Materials;
|
||||
|
||||
pub mod nodes;
|
||||
|
||||
pub struct Buffers {
|
||||
pub uniforms: Uniform,
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
use byteorder::{LittleEndian, ByteOrder};
|
||||
|
||||
pub const NODE_TEX_SIZE: usize = 128; // 32x32x32 nodes in texture
|
||||
pub const NODE_TEX_SIZE_SQ: usize = NODE_TEX_SIZE*NODE_TEX_SIZE;
|
||||
pub const NODE_TEX_SIZE_QB: usize = NODE_TEX_SIZE*NODE_TEX_SIZE*NODE_TEX_SIZE;
|
||||
|
||||
|
||||
pub struct Nodes {
|
||||
node_buffer_a: Box<[u32]>,
|
||||
node_buffer_b: Box<[u32]>,
|
||||
active_buffer: u8,
|
||||
modified: bool
|
||||
}
|
||||
|
||||
impl Nodes {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
node_buffer_a: vec![0_u32; NODE_TEX_SIZE_QB].into_boxed_slice(),
|
||||
node_buffer_b: vec![0_u32; NODE_TEX_SIZE_QB].into_boxed_slice(),
|
||||
active_buffer: 0,
|
||||
modified: false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_node(&self, index: usize) -> u32 {
|
||||
if self.active_buffer == 0 { self.node_buffer_a[index] }
|
||||
else { self.node_buffer_b[index] }
|
||||
}
|
||||
|
||||
pub fn set_node(&mut self, index: usize, value: u32) {
|
||||
if self.active_buffer == 0 { self.node_buffer_a[index] = value; }
|
||||
else { self.node_buffer_b[index] = value; }
|
||||
self.modified = true;
|
||||
}
|
||||
|
||||
pub fn update(&mut self, queue: &wgpu::Queue, texture: &wgpu::Texture) {
|
||||
if self.modified {
|
||||
self.modified = false;
|
||||
|
||||
// Select target node buffer
|
||||
let node_buffer;
|
||||
if self.active_buffer == 0 { node_buffer = &self.node_buffer_a; }
|
||||
else { node_buffer = &self.node_buffer_b; }
|
||||
|
||||
// Write all nodes to gpu
|
||||
for z in 0..NODE_TEX_SIZE {
|
||||
|
||||
// Convert u32 node buffer to u8
|
||||
let node_origin = wgpu::Origin3d{ x:0, y: 0, z: z as u32 };
|
||||
let node_size = wgpu::Extent3d { width: NODE_TEX_SIZE as u32, height: NODE_TEX_SIZE as u32, depth: 1 };
|
||||
let mut node_bytes = [0_u8; NODE_TEX_SIZE_SQ*4];
|
||||
let offset = NODE_TEX_SIZE_SQ*z;
|
||||
LittleEndian::write_u32_into(&node_buffer[offset..offset+NODE_TEX_SIZE_SQ], &mut node_bytes);
|
||||
|
||||
// Write nodes
|
||||
queue.write_texture(
|
||||
wgpu::TextureCopyView { texture: texture, mip_level: 0, origin: node_origin }, &node_bytes,
|
||||
wgpu::TextureDataLayout { offset: 0, bytes_per_row: 4*node_size.width, rows_per_image: node_size.height }, node_size
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -117,7 +117,7 @@ impl Renderer {
|
||||
pub fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
|
||||
|
||||
// Update uniform buffer
|
||||
let half = (buffers::content::NODE_TEX_SIZE / 2) as i32;
|
||||
let half = (buffers::nodes::NODE_TEX_SIZE / 2) as i32;
|
||||
let offset = Vector3{x: (self.world_offset.x + half) as f32, y: (self.world_offset.y + half) as f32, z: (self.world_offset.z + half) as f32 };
|
||||
|
||||
self.buffers.uniforms.values.update(&self.camera, offset, self.start.elapsed().as_secs_f32());
|
||||
|
||||
Reference in New Issue
Block a user