Combined node and block buffer into one struct: content.
This commit is contained in:
+3
-3
@@ -1,8 +1,8 @@
|
||||
mod camera_controller;
|
||||
mod world;
|
||||
pub mod world;
|
||||
use cgmath::{SquareMatrix, Point3, InnerSpace};
|
||||
use winit::event::Event;
|
||||
use crate::renderer::{camera::CameraTransform, RenderSpace};
|
||||
use crate::renderer::{camera::CameraTransform};
|
||||
use camera_controller::CameraController;
|
||||
use world::World;
|
||||
|
||||
@@ -17,7 +17,7 @@ pub struct App {
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new(renderer: &mut dyn RenderSpace) -> Self {
|
||||
pub fn new() -> Self {
|
||||
let mut app = Self {
|
||||
camera_controller: CameraController::new(),
|
||||
world: World::new("default".to_string())
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
use cgmath::Point3;
|
||||
|
||||
pub const SIZE: usize = 32;
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WorldBlock {
|
||||
pub materials: [u8;(SIZE*SIZE*SIZE) as usize]
|
||||
|
||||
@@ -19,11 +19,12 @@ impl WorldChunk {
|
||||
|
||||
pub fn get_block(&mut self, block_pos: &Point3<u32>) -> &mut WorldBlock {
|
||||
// Get block index
|
||||
let index = block_pos.x + SIZE * (block_pos.y + SIZE * block_pos.z);
|
||||
let mut value = self.nodes[index as usize];
|
||||
let index = (block_pos.x + SIZE * (block_pos.y + SIZE * block_pos.z)) as usize;
|
||||
let mut value = self.nodes[index];
|
||||
// Allocate new block
|
||||
if value == 0 {
|
||||
value = (self.blocks.len() + 1) as u32;
|
||||
self.nodes[index] = value;
|
||||
self.blocks.push(WorldBlock::new());
|
||||
}
|
||||
// Return block reference
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
mod generator;
|
||||
mod chunk;
|
||||
mod block;
|
||||
pub mod chunk;
|
||||
pub mod block;
|
||||
use cgmath::Point3;
|
||||
use std::collections::HashMap;
|
||||
use generator::WorldGen;
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ fn main() {
|
||||
.expect("Failed to create window");
|
||||
|
||||
let mut renderer = futures::executor::block_on(Renderer::new(&window));
|
||||
let mut app = App::new(&mut renderer);
|
||||
let mut app = App::new();
|
||||
|
||||
// Stats
|
||||
let mut fps_timer = std::time::Instant::now();
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
use std::convert::TryInto;
|
||||
use cgmath::Point3;
|
||||
use crate::renderer::{buffers, buffers::{BLOCK_SIZE, BLOCK_TEX_SIZE, BLOCK_TEX_LEN, BLOCK_LEN, BLOCK_ARR_LEN}};
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RenderBlock {
|
||||
pub id: usize,
|
||||
pub data: [u8;BLOCK_LEN]
|
||||
}
|
||||
|
||||
impl RenderBlock {
|
||||
pub fn new() -> Self {
|
||||
Self { id: 0, data: [0_u8;BLOCK_LEN] }
|
||||
}
|
||||
|
||||
pub fn set(&mut self, voxel_pos: Point3<usize>, value: u8) {
|
||||
self.data[voxel_pos.x + buffers::BLOCK_SIZE * (voxel_pos.y + buffers::BLOCK_SIZE * voxel_pos.z)] = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct Blocks {
|
||||
blocks: Box<[RenderBlock]>,
|
||||
free_block: usize,
|
||||
texture: wgpu::Texture,
|
||||
pub bind_layout: wgpu::BindGroupLayout,
|
||||
pub bind_group: wgpu::BindGroup
|
||||
}
|
||||
|
||||
impl Blocks {
|
||||
|
||||
/*
|
||||
* Create buffer in memory and gpu
|
||||
*/
|
||||
pub fn new(device: &wgpu::Device) -> Self {
|
||||
|
||||
// Create texture
|
||||
let block_tex_dim = BLOCK_TEX_SIZE * BLOCK_SIZE;
|
||||
let size = wgpu::Extent3d { width: BLOCK_SIZE as u32, height: block_tex_dim as u32, depth: block_tex_dim as u32 };
|
||||
let texture = device.create_texture(
|
||||
&wgpu::TextureDescriptor {
|
||||
size: size,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D3,
|
||||
format: wgpu::TextureFormat::R8Uint,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, // STORAGE?
|
||||
label: Some("block texture"),
|
||||
}
|
||||
);
|
||||
|
||||
// Bind layout
|
||||
let bind_layout = device.create_bind_group_layout(
|
||||
&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture { multisampled: false, view_dimension: wgpu::TextureViewDimension::D3, sample_type: wgpu::TextureSampleType::Uint },
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler { comparison: false, filtering: false },
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
label: Some("Node texture layout"),
|
||||
}
|
||||
);
|
||||
|
||||
// Bind group
|
||||
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge, address_mode_v: wgpu::AddressMode::ClampToEdge, address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter: wgpu::FilterMode::Nearest, min_filter: wgpu::FilterMode::Nearest, mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
..Default::default()
|
||||
});
|
||||
let bind_group = device.create_bind_group(
|
||||
&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry { binding: 0, resource: wgpu::BindingResource::TextureView(&view) },
|
||||
wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::Sampler(&sampler) }
|
||||
],
|
||||
label: Some("block texture group"),
|
||||
}
|
||||
);
|
||||
|
||||
// Data
|
||||
let mut blocks = vec![RenderBlock::new(); BLOCK_ARR_LEN].into_boxed_slice();
|
||||
for (i, b) in blocks.iter_mut().enumerate() { b.id = i; }
|
||||
println!("Blocks size: {} MB, max: {}", BLOCK_TEX_LEN as f32 / 1024.0 / 1024.0, BLOCK_ARR_LEN);
|
||||
|
||||
// Done
|
||||
Self { blocks, texture, bind_layout, bind_group, free_block: 0 }
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes block to gpu
|
||||
*/
|
||||
pub fn write(&mut self, queue: &wgpu::Queue, block_id: usize) {
|
||||
|
||||
// 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;
|
||||
let z = (block.id/BLOCK_TEX_SIZE * BLOCK_SIZE) as u32;
|
||||
let block_origin = wgpu::Origin3d{ x:0, y, z };
|
||||
let block_size = wgpu::Extent3d{ width: BLOCK_SIZE as u32, height: BLOCK_SIZE as u32, depth: BLOCK_SIZE as u32 };
|
||||
let block_bytes : [u8;BLOCK_LEN] = block.data.try_into().unwrap();
|
||||
|
||||
// Write to texture
|
||||
queue.write_texture(
|
||||
wgpu::TextureCopyView { texture: &self.texture, mip_level: 0, origin: block_origin },
|
||||
&block_bytes,
|
||||
wgpu::TextureDataLayout { offset: 0, bytes_per_row: block_size.width, rows_per_image: block_size.height },
|
||||
block_size
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get(&mut self, block_id: usize) -> &mut RenderBlock {
|
||||
&mut self.blocks[block_id]
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocates new block
|
||||
*/
|
||||
pub fn alloc(&mut self) -> &mut RenderBlock {
|
||||
// Make sure we still have some free blocks
|
||||
if self.free_block >= BLOCK_ARR_LEN { panic!("No more free blocks! we should consider reusing blocks..."); }
|
||||
|
||||
self.free_block += 1;
|
||||
&mut self.blocks[self.free_block - 1]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use std::convert::TryInto;
|
||||
use cgmath::Point3;
|
||||
use crate::app::world::block::WorldBlock;
|
||||
|
||||
pub const BLOCK_SIZE : usize = 32; // 32x32x32 block size
|
||||
pub const BLOCK_TEX_SIZE : usize = 64; // 64x64 blocks in texture
|
||||
pub const NODE_TEX_SIZE: usize = 48; // 32x32x32 nodes in texture
|
||||
|
||||
|
||||
pub struct Content {
|
||||
node_buffer: Box<[u32]>,
|
||||
node_texture: wgpu::Texture,
|
||||
block_freeidx: usize,
|
||||
block_texture: wgpu::Texture,
|
||||
pub bind_layout: wgpu::BindGroupLayout,
|
||||
pub bind_group: wgpu::BindGroup
|
||||
}
|
||||
|
||||
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 {
|
||||
mip_level_count: 1, sample_count: 1, dimension: wgpu::TextureDimension::D3,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, label: None,
|
||||
size: wgpu::Extent3d{ width: NODE_TEX_SIZE as u32, height: NODE_TEX_SIZE as u32, depth: NODE_TEX_SIZE as u32 },
|
||||
format: wgpu::TextureFormat::R32Uint,
|
||||
}
|
||||
);
|
||||
let block_texture = device.create_texture(
|
||||
&wgpu::TextureDescriptor {
|
||||
mip_level_count: 1, sample_count: 1, dimension: wgpu::TextureDimension::D3,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, label: None,
|
||||
size: wgpu::Extent3d{ width: BLOCK_SIZE as u32, height: (BLOCK_TEX_SIZE * BLOCK_SIZE) as u32, depth: (BLOCK_TEX_SIZE * BLOCK_SIZE) as u32 },
|
||||
format: wgpu::TextureFormat::R8Uint,
|
||||
}
|
||||
);
|
||||
|
||||
// Bind layout
|
||||
let sampler_entry = wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,visibility: wgpu::ShaderStage::FRAGMENT, count: None,
|
||||
ty: wgpu::BindingType::Sampler { comparison: false, filtering: false },
|
||||
};
|
||||
let texture_entry = wgpu::BindGroupLayoutEntry {
|
||||
binding: 0, visibility: wgpu::ShaderStage::FRAGMENT, count: None,
|
||||
ty: wgpu::BindingType::Texture { multisampled: false, view_dimension: wgpu::TextureViewDimension::D3, sample_type: wgpu::TextureSampleType::Uint },
|
||||
};
|
||||
let bind_layout = device.create_bind_group_layout(
|
||||
&wgpu::BindGroupLayoutDescriptor {
|
||||
label: None, entries: &[
|
||||
wgpu::BindGroupLayoutEntry { binding: 0, ..texture_entry },
|
||||
wgpu::BindGroupLayoutEntry { binding: 1, ..texture_entry },
|
||||
wgpu::BindGroupLayoutEntry { binding: 2, ..sampler_entry },
|
||||
wgpu::BindGroupLayoutEntry { binding: 3, ..sampler_entry },
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
// Bind group
|
||||
let bind_group = device.create_bind_group(
|
||||
&wgpu::BindGroupDescriptor {
|
||||
label: None, layout: &bind_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry { binding: 0, resource: wgpu::BindingResource::TextureView(&node_texture.create_view(&wgpu::TextureViewDescriptor::default())) },
|
||||
wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::TextureView(&block_texture.create_view(&wgpu::TextureViewDescriptor::default())) },
|
||||
wgpu::BindGroupEntry { binding: 2, resource: wgpu::BindingResource::Sampler(&device.create_sampler(&Default::default())) },
|
||||
wgpu::BindGroupEntry { binding: 3, resource: wgpu::BindingResource::Sampler(&device.create_sampler(&Default::default())) }
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
// Done
|
||||
let block_freeidx = 0;
|
||||
Self { node_buffer, node_texture, block_freeidx, block_texture, bind_layout, bind_group }
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn write(&mut self, queue: &wgpu::Queue, block_pos: &Point3<u32>, block: &WorldBlock) {
|
||||
|
||||
// Get node
|
||||
let index = (block_pos.x + NODE_TEX_SIZE as u32 * (block_pos.y + NODE_TEX_SIZE as u32 * block_pos.z)) as usize;
|
||||
let mut value = self.node_buffer[index] as usize;
|
||||
|
||||
// Allocate new block
|
||||
if value == 0 {
|
||||
value = self.block_freeidx;
|
||||
self.node_buffer[index] = value as u32;
|
||||
self.block_freeidx += 1;
|
||||
}
|
||||
|
||||
// Calculate position in block texture
|
||||
let y = (value % BLOCK_TEX_SIZE * BLOCK_SIZE) as u32;
|
||||
let z = (value / BLOCK_TEX_SIZE * BLOCK_SIZE) as u32;
|
||||
let block_origin = wgpu::Origin3d{ x:0, y, z };
|
||||
let block_size = wgpu::Extent3d{ width: BLOCK_SIZE as u32, height: BLOCK_SIZE as u32, depth: BLOCK_SIZE as u32 };
|
||||
let block_bytes : [u8;BLOCK_SIZE*BLOCK_SIZE*BLOCK_SIZE] = block.materials.try_into().unwrap();
|
||||
|
||||
// Write block
|
||||
queue.write_texture(
|
||||
wgpu::TextureCopyView { texture: &self.block_texture, mip_level: 0, origin: block_origin }, &block_bytes,
|
||||
wgpu::TextureDataLayout { offset: 0, bytes_per_row: block_size.width, rows_per_image: block_size.height }, block_size
|
||||
);
|
||||
|
||||
// Convert u32 node buffer to u8
|
||||
let node_size = wgpu::Extent3d { width: NODE_TEX_SIZE as u32, height: NODE_TEX_SIZE as u32, depth: NODE_TEX_SIZE as u32 };
|
||||
let mut node_bytes = [0_u8; NODE_TEX_SIZE*NODE_TEX_SIZE*NODE_TEX_SIZE*4];
|
||||
LittleEndian::write_u32_into(&self.node_buffer, &mut node_bytes);
|
||||
|
||||
// Write nodes (TODO: do it max once per frame, and only if smth changed)
|
||||
queue.write_texture(
|
||||
wgpu::TextureCopyView { texture: &self.node_texture, mip_level: 0, origin: wgpu::Origin3d::ZERO }, &node_bytes,
|
||||
wgpu::TextureDataLayout { offset: 0, bytes_per_row: 4*node_size.width, rows_per_image: node_size.height }, node_size
|
||||
);
|
||||
}
|
||||
}
|
||||
+10
-35
@@ -1,50 +1,25 @@
|
||||
|
||||
// Consts
|
||||
|
||||
pub const BLOCK_SIZE : usize = 32; // 32x32x32 block size
|
||||
pub const BLOCK_TEX_SIZE : usize = 64; // 64x64 blocks in texture
|
||||
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_TEX_LEN: usize = BLOCK_TEX_SIZE*BLOCK_TEX_SIZE * BLOCK_LEN; // Number of u8 in block texture
|
||||
|
||||
|
||||
|
||||
// Import names
|
||||
|
||||
mod nodes;
|
||||
pub use nodes::Nodes;
|
||||
|
||||
mod blocks;
|
||||
pub use blocks::Blocks;
|
||||
pub use blocks::RenderBlock;
|
||||
|
||||
mod uniform;
|
||||
pub use uniform::Uniform;
|
||||
pub use uniform::UniformValues;
|
||||
|
||||
mod content;
|
||||
pub use content::Content;
|
||||
mod materials;
|
||||
pub use materials::Materials;
|
||||
|
||||
// Create buffers
|
||||
|
||||
pub struct Buffers {
|
||||
pub uniform_buffer: Uniform,
|
||||
pub node_buffer: Nodes,
|
||||
pub brick_buffer: Blocks,
|
||||
pub material_buffer: Materials
|
||||
pub uniforms: Uniform,
|
||||
pub content: Content,
|
||||
pub materials: Materials
|
||||
}
|
||||
|
||||
impl Buffers {
|
||||
|
||||
pub fn new(device: &wgpu::Device) -> Self {
|
||||
let uniform_buffer = Uniform::new(device);
|
||||
let node_buffer = Nodes::new(device);
|
||||
let brick_buffer = Blocks::new(device);
|
||||
let material_buffer = Materials::new(device);
|
||||
Self { uniform_buffer, node_buffer, brick_buffer, material_buffer }
|
||||
Self {
|
||||
uniforms: Uniform::new(device),
|
||||
content: Content::new(device),
|
||||
materials: Materials::new(device)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
|
||||
use crate::renderer::buffers::{NODE_TEX_SIZE, NODE_TEX_LEN};
|
||||
|
||||
pub struct Nodes {
|
||||
pub nodes: Box<[u32]>,
|
||||
texture: wgpu::Texture,
|
||||
size: wgpu::Extent3d,
|
||||
pub bind_layout: wgpu::BindGroupLayout,
|
||||
pub bind_group: wgpu::BindGroup
|
||||
}
|
||||
|
||||
impl Nodes {
|
||||
|
||||
pub fn new(device: &wgpu::Device) -> Self {
|
||||
|
||||
// Create texture
|
||||
let size = wgpu::Extent3d { width: NODE_TEX_SIZE as u32, height: NODE_TEX_SIZE as u32, depth: NODE_TEX_SIZE as u32 };
|
||||
let texture = device.create_texture(
|
||||
&wgpu::TextureDescriptor {
|
||||
size: size,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D3,
|
||||
format: wgpu::TextureFormat::R32Uint,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, // STORAGE?
|
||||
label: Some("Node texture"),
|
||||
}
|
||||
);
|
||||
|
||||
// Bind layout
|
||||
let bind_layout = device.create_bind_group_layout(
|
||||
&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture { multisampled: false, view_dimension: wgpu::TextureViewDimension::D3, sample_type: wgpu::TextureSampleType::Uint },
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler { comparison: false, filtering: false },
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
label: Some("Node texture layout"),
|
||||
}
|
||||
);
|
||||
|
||||
// Bind group
|
||||
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge, address_mode_v: wgpu::AddressMode::ClampToEdge, address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter: wgpu::FilterMode::Nearest, min_filter: wgpu::FilterMode::Nearest, mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
..Default::default()
|
||||
});
|
||||
let bind_group = device.create_bind_group(
|
||||
&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry { binding: 0, resource: wgpu::BindingResource::TextureView(&view) },
|
||||
wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::Sampler(&sampler) }
|
||||
],
|
||||
label: Some("Node texture group"),
|
||||
}
|
||||
);
|
||||
|
||||
// Data
|
||||
let nodes = vec![0_u32; NODE_TEX_LEN].into_boxed_slice();
|
||||
println!("Nodes size: {} MB", (nodes.len() as f32 * 4.0 / 1024.0 / 1024.0 * 100.0).round() / 100.0);
|
||||
|
||||
// Done
|
||||
Self { nodes, texture, size, bind_layout, bind_group }
|
||||
}
|
||||
|
||||
pub fn write(&mut self, queue: &wgpu::Queue) {
|
||||
// Convert 32 bit values to 8 bit
|
||||
let mut bytes = [0_u8; NODE_TEX_LEN*4];
|
||||
LittleEndian::write_u32_into(&self.nodes, &mut bytes);
|
||||
|
||||
// Write
|
||||
queue.write_texture(
|
||||
wgpu::TextureCopyView { texture: &self.texture, mip_level: 0, origin: wgpu::Origin3d::ZERO },
|
||||
&bytes,
|
||||
wgpu::TextureDataLayout { offset: 0, bytes_per_row: 4*self.size.width, rows_per_image: self.size.height },
|
||||
self.size
|
||||
);
|
||||
}
|
||||
}
|
||||
+3
-26
@@ -1,17 +1,11 @@
|
||||
use winit::{window::Window, dpi::PhysicalSize};
|
||||
|
||||
pub mod buffers;
|
||||
use buffers::Buffers;
|
||||
|
||||
mod passes;
|
||||
use passes::{RaytracePass, PostprocessPass};
|
||||
|
||||
pub mod camera;
|
||||
use camera::Camera;
|
||||
|
||||
pub mod renderspace;
|
||||
pub use renderspace::RenderSpace;
|
||||
|
||||
pub struct Renderer {
|
||||
surface: wgpu::Surface,
|
||||
device: wgpu::Device,
|
||||
@@ -27,7 +21,6 @@ pub struct Renderer {
|
||||
// Other
|
||||
pub camera: Camera,
|
||||
start: std::time::Instant,
|
||||
changed_bricks: Vec<usize>,
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
@@ -84,10 +77,9 @@ impl Renderer {
|
||||
|
||||
// Other
|
||||
let start = std::time::Instant::now();
|
||||
let changed_bricks: Vec<usize> = Vec::new();
|
||||
|
||||
println!("Initialized");
|
||||
Self { surface, device, queue, swapchain_desc, swapchain, texture, raytrace_pass, postprocess_pass, buffers, camera, start, changed_bricks }
|
||||
Self { surface, device, queue, swapchain_desc, swapchain, texture, raytrace_pass, postprocess_pass, buffers, camera, start }
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -113,23 +105,8 @@ impl Renderer {
|
||||
pub fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
|
||||
|
||||
// Update uniform buffer
|
||||
self.buffers.uniform_buffer.values.update(&self.camera, self.start.elapsed().as_secs_f32());
|
||||
self.queue.write_buffer(&self.buffers.uniform_buffer.buffer, 0, bytemuck::cast_slice(&[self.buffers.uniform_buffer.values]));
|
||||
|
||||
// Update changed nodes
|
||||
if self.changed_bricks.len() > 0 {
|
||||
self.buffers.node_buffer.write(&self.queue);
|
||||
for block_id in &self.changed_bricks {
|
||||
self.buffers.brick_buffer.write(&self.queue, *block_id);
|
||||
}
|
||||
|
||||
// let used = self.buffers.brick_buffer.next_block(false);
|
||||
// let total = buffers::BLOCK_TEX_SIZE * buffers::BLOCK_TEX_SIZE;
|
||||
// let changed = self.changed_bricks.len();
|
||||
// println!("Used: {}/{} Changed: {}", used, total, changed);
|
||||
|
||||
self.changed_bricks.clear();
|
||||
}
|
||||
self.buffers.uniforms.values.update(&self.camera, self.start.elapsed().as_secs_f32());
|
||||
self.queue.write_buffer(&self.buffers.uniforms.buffer, 0, bytemuck::cast_slice(&[self.buffers.uniforms.values]));
|
||||
|
||||
// Get next frame to render to
|
||||
let frame = self.swapchain.get_current_frame()?.output;
|
||||
|
||||
@@ -28,10 +28,9 @@ impl RaytracePass {
|
||||
|
||||
// Bind group layouts
|
||||
let bind_group_layouts = [
|
||||
&buffers.uniform_buffer.bind_layout,
|
||||
&buffers.node_buffer.bind_layout,
|
||||
&buffers.brick_buffer.bind_layout,
|
||||
&buffers.material_buffer.bind_layout
|
||||
&buffers.uniforms.bind_layout,
|
||||
&buffers.content.bind_layout,
|
||||
&buffers.materials.bind_layout
|
||||
];
|
||||
|
||||
// Pipeline layout
|
||||
@@ -81,10 +80,9 @@ impl RaytracePass {
|
||||
render_pass.set_pipeline(&self.pipeline);
|
||||
|
||||
// Bind groups
|
||||
render_pass.set_bind_group(0, &buffers.uniform_buffer.bind_group, &[]);
|
||||
render_pass.set_bind_group(1, &buffers.node_buffer.bind_group, &[]);
|
||||
render_pass.set_bind_group(2, &buffers.brick_buffer.bind_group, &[]);
|
||||
render_pass.set_bind_group(3, &buffers.material_buffer.bind_group, &[]);
|
||||
render_pass.set_bind_group(0, &buffers.uniforms.bind_group, &[]);
|
||||
render_pass.set_bind_group(1, &buffers.content.bind_group, &[]);
|
||||
render_pass.set_bind_group(2, &buffers.materials.bind_group, &[]);
|
||||
|
||||
// Draw 2 triangles
|
||||
render_pass.draw(0..6, 0..1);
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
use cgmath::Point3;
|
||||
use crate::renderer::{Renderer, buffers};
|
||||
|
||||
|
||||
pub trait RenderSpace {
|
||||
fn block_get(&mut self, block_pos: Point3<usize>) -> &mut buffers::RenderBlock;
|
||||
fn block_dirty(&mut self, id: usize);
|
||||
}
|
||||
|
||||
impl RenderSpace for Renderer {
|
||||
|
||||
/*
|
||||
* Grabs existing or allocates new block for given position
|
||||
*
|
||||
* block_pos: Position of the block in world, in block space
|
||||
* block_id: Block identifier, equal to Block.id
|
||||
*/
|
||||
fn block_get(&mut self, block_pos: Point3<usize>) -> &mut buffers::RenderBlock {
|
||||
// Get node
|
||||
let node_idx = block_pos.x + buffers::NODE_TEX_SIZE * (block_pos.y + buffers::NODE_TEX_SIZE * block_pos.z);
|
||||
let node_value = self.buffers.node_buffer.nodes[node_idx];
|
||||
|
||||
// Allocate new block
|
||||
if node_value == 0 {
|
||||
let block = self.buffers.brick_buffer.alloc();
|
||||
self.buffers.node_buffer.nodes[node_idx] = (block.id+1) as u32;
|
||||
return block;
|
||||
}
|
||||
|
||||
// Return existing block
|
||||
self.buffers.brick_buffer.get((node_value-1) as usize)
|
||||
}
|
||||
|
||||
/*
|
||||
* Marks block as dirty, will be sent to gpu at the next frame
|
||||
*
|
||||
* block_id: Block identifier, equal to Block.id
|
||||
*/
|
||||
fn block_dirty(&mut self, block_id: usize) {
|
||||
if !self.changed_bricks.contains(&block_id) {
|
||||
self.changed_bricks.push(block_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user