Moved node buffer logic to Nodes struct
This commit is contained in:
@@ -104,7 +104,6 @@ impl Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send dirty chunks to renderer
|
// Send dirty chunks to renderer
|
||||||
// TODO: Only send chunks in rendering range
|
|
||||||
// TODO: Unload chunks above certain radius
|
// TODO: Unload chunks above certain radius
|
||||||
self.world.update();
|
self.world.update();
|
||||||
for (pos, chunk) in self.world.all_chunks() {
|
for (pos, chunk) in self.world.all_chunks() {
|
||||||
|
|||||||
@@ -4,17 +4,15 @@ use std::convert::TryInto;
|
|||||||
use cgmath::Vector3;
|
use cgmath::Vector3;
|
||||||
use std::cmp::{min, max};
|
use std::cmp::{min, max};
|
||||||
use crate::game::world::block::WorldBlock;
|
use crate::game::world::block::WorldBlock;
|
||||||
|
use super::nodes::{Nodes, NODE_TEX_SIZE, NODE_TEX_SIZE_QB};
|
||||||
|
|
||||||
//note: remember to update in main.frag
|
//note: remember to update in main.frag
|
||||||
pub const BLOCK_SIZE : usize = 32; // 32x32x32 block size
|
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 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_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_SQ: usize = BLOCK_TEX_SIZE*BLOCK_TEX_SIZE;
|
||||||
const BLOCK_TEX_SIZE_QB: usize = BLOCK_TEX_SIZE*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 struct ContentStats {
|
||||||
pub node_tex_size: f64, // MB
|
pub node_tex_size: f64, // MB
|
||||||
@@ -26,9 +24,8 @@ pub struct ContentStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Content {
|
pub struct Content {
|
||||||
node_buffer: Box<[u32]>,
|
nodes: Nodes,
|
||||||
node_texture: wgpu::Texture,
|
node_texture: wgpu::Texture,
|
||||||
node_dirty: bool,
|
|
||||||
block_freed: Vec<u32>,
|
block_freed: Vec<u32>,
|
||||||
block_freeidx: usize,
|
block_freeidx: usize,
|
||||||
block_texture: wgpu::Texture,
|
block_texture: wgpu::Texture,
|
||||||
@@ -39,9 +36,6 @@ pub struct Content {
|
|||||||
impl Content {
|
impl Content {
|
||||||
|
|
||||||
pub fn new(device: &wgpu::Device) -> Self {
|
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
|
// Create textures
|
||||||
let node_texture = device.create_texture(
|
let node_texture = device.create_texture(
|
||||||
&wgpu::TextureDescriptor {
|
&wgpu::TextureDescriptor {
|
||||||
@@ -87,10 +81,11 @@ impl Content {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
|
let nodes = Nodes::new();
|
||||||
let block_freeidx = 0;
|
let block_freeidx = 0;
|
||||||
let node_dirty = false;
|
let node_dirty = false;
|
||||||
let block_freed = Vec::new();
|
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 {
|
pub fn stats(&self) -> ContentStats {
|
||||||
@@ -115,7 +110,7 @@ impl Content {
|
|||||||
|
|
||||||
// Get node
|
// 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 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
|
// Allocate new block
|
||||||
if value == 0 {
|
if value == 0 {
|
||||||
@@ -127,10 +122,8 @@ impl Content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Assign
|
// Assign
|
||||||
self.node_buffer[index] = value as u32;
|
|
||||||
self.block_freeidx = value;
|
self.block_freeidx = value;
|
||||||
// Mark node buffer as dirty
|
self.nodes.set_node(index, value as u32);
|
||||||
self.node_dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate position in block texture
|
// Calculate position in block texture
|
||||||
@@ -152,54 +145,33 @@ impl Content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn shift(&mut self, offset: &Vector3<i32>) {
|
pub fn shift(&mut self, offset: &Vector3<i32>) {
|
||||||
let timer = Instant::now();
|
// let timer = Instant::now();
|
||||||
let mut result = vec![0_u32; self.node_buffer.len()].into_boxed_slice();
|
// let mut result = vec![0_u32; self.node_buffer.len()].into_boxed_slice();
|
||||||
let (ox, oy, oz) = (offset.x, offset.y, offset.z);
|
// let (ox, oy, oz) = (offset.x, offset.y, offset.z);
|
||||||
let size = NODE_TEX_SIZE as i32;
|
// let size = NODE_TEX_SIZE as i32;
|
||||||
|
|
||||||
let a = max(0, -oz);
|
// let a = max(0, -oz);
|
||||||
let b = min(size-oz, size);
|
// let b = min(size-oz, size);
|
||||||
println!("from {} to {}", a, b);
|
// println!("from {} to {}", a, b);
|
||||||
|
|
||||||
for x in max(0, -ox)..min(size-ox, size) {
|
// for x in max(0, -ox)..min(size-ox, size) {
|
||||||
for y in max(0, -oy)..min(size-oy, size) {
|
// for y in max(0, -oy)..min(size-oy, size) {
|
||||||
for z in max(0, -oz)..min(size-oz, size) {
|
// for z in max(0, -oz)..min(size-oz, size) {
|
||||||
let idx0 = x + size * (y + size * z);
|
// let idx0 = x + size * (y + size * z);
|
||||||
let idx1 = (x+ox) + size * ((y+oy) + size * (z+oz));
|
// let idx1 = (x+ox) + size * ((y+oy) + size * (z+oz));
|
||||||
result[idx1 as usize] = self.node_buffer[idx0 as usize];
|
// 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) {
|
pub fn update(&mut self, queue: &wgpu::Queue) {
|
||||||
if self.node_dirty {
|
self.nodes.update(queue, &self.node_texture);
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ pub mod content;
|
|||||||
pub use content::Content;
|
pub use content::Content;
|
||||||
mod materials;
|
mod materials;
|
||||||
pub use materials::Materials;
|
pub use materials::Materials;
|
||||||
|
pub mod nodes;
|
||||||
|
|
||||||
pub struct Buffers {
|
pub struct Buffers {
|
||||||
pub uniforms: Uniform,
|
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> {
|
pub fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
|
||||||
|
|
||||||
// Update uniform buffer
|
// 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 };
|
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());
|
self.buffers.uniforms.values.update(&self.camera, offset, self.start.elapsed().as_secs_f32());
|
||||||
|
|||||||
Reference in New Issue
Block a user