materials, brick and nodes structure, preparing for world generation
This commit is contained in:
@@ -1,42 +1,22 @@
|
||||
use wgpu::util::DeviceExt;
|
||||
use std::convert::TryInto;
|
||||
use rand::prelude::*;
|
||||
|
||||
const BRICK_SIZE : usize = 32; // 32x32x32 brick size
|
||||
const BRICK_NUM : usize = 10000; // x bricks in texture
|
||||
|
||||
const BRICK_LEN : usize = BRICK_SIZE*BRICK_SIZE*BRICK_SIZE;
|
||||
use crate::renderer::buffers::{BRICK_SIZE, BRICK_NUM, BRICK_LEN};
|
||||
const DATA_LEN : usize = BRICK_LEN * BRICK_NUM;
|
||||
|
||||
struct BrickData {
|
||||
pub data: Box<[u8]>
|
||||
}
|
||||
|
||||
impl BrickData {
|
||||
|
||||
pub fn new() -> Self {
|
||||
let data = vec![0_u8; DATA_LEN].into_boxed_slice();
|
||||
Self { data }
|
||||
}
|
||||
|
||||
pub fn set(&mut self, brick: usize, x: usize, y: usize, z: usize, value: u8)
|
||||
{
|
||||
let local_idx = x + BRICK_SIZE * (y + BRICK_SIZE * z);
|
||||
let offset = brick * BRICK_LEN;
|
||||
self.data[offset + local_idx] = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct BrickBuffer {
|
||||
bricks: BrickData,
|
||||
pub bricks: Box<[u8]>,
|
||||
pub free_brick: usize,
|
||||
texture: wgpu::Texture,
|
||||
size: wgpu::Extent3d,
|
||||
pub bind_layout: wgpu::BindGroupLayout,
|
||||
pub bind_group: wgpu::BindGroup
|
||||
}
|
||||
|
||||
impl BrickBuffer {
|
||||
|
||||
/*
|
||||
* Create buffer in memory and gpu
|
||||
*/
|
||||
pub fn new(device: &wgpu::Device) -> Self {
|
||||
|
||||
// Create texture
|
||||
@@ -93,36 +73,24 @@ impl BrickBuffer {
|
||||
);
|
||||
|
||||
// Data
|
||||
let mut bricks = BrickData::new();
|
||||
let mut bricks = vec![0_u8; DATA_LEN].into_boxed_slice();
|
||||
bricks[0] = 1;
|
||||
println!("Brick buffer size: {} MB", DATA_LEN as f32 / 1024.0 / 1024.0);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
for x in 0..32 {
|
||||
for y in 0..32 {
|
||||
for z in 0..32 {
|
||||
let value = if rng.gen::<f32>()> 0.99 { 1 } else { 0 };
|
||||
bricks.set(0, x, y, z, value);
|
||||
bricks.set(1, x, 0, z, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
bricks.set(1, 20, 5, 16, 1);
|
||||
|
||||
// Done
|
||||
Self { bricks, texture, size, bind_layout, bind_group }
|
||||
Self { bricks, texture, bind_layout, bind_group, free_brick: 0 }
|
||||
}
|
||||
|
||||
/*
|
||||
Write brick data to gpu, should be called to apply changes
|
||||
offset: Brick index to copy
|
||||
*/
|
||||
pub fn write(&mut self, queue: &wgpu::Queue, offset: usize)
|
||||
{
|
||||
pub fn write(&mut self, queue: &wgpu::Queue, brick: usize) {
|
||||
// Get first brick
|
||||
let brick_offset = offset*BRICK_LEN;
|
||||
let brick_bytes : [u8;BRICK_LEN] = self.bricks.data[brick_offset..brick_offset+BRICK_LEN].try_into().unwrap();
|
||||
let brick_offset = brick*BRICK_LEN;
|
||||
let brick_bytes : [u8;BRICK_LEN] = self.bricks[brick_offset..brick_offset+BRICK_LEN].try_into().unwrap();
|
||||
let brick_size = wgpu::Extent3d{ width: BRICK_SIZE as u32, height: BRICK_SIZE as u32, depth: BRICK_SIZE as u32 };
|
||||
let brick_origin = wgpu::Origin3d{ x:0, y:0, z: (offset*BRICK_SIZE) as u32 };
|
||||
let brick_origin = wgpu::Origin3d{ x:0, y:0, z: (brick*BRICK_SIZE) as u32 };
|
||||
|
||||
// Write
|
||||
queue.write_texture(
|
||||
@@ -132,4 +100,13 @@ impl BrickBuffer {
|
||||
brick_size
|
||||
);
|
||||
}
|
||||
|
||||
pub fn next_brick(&mut self) -> usize {
|
||||
if self.free_brick >= self.bricks.len() {
|
||||
panic!("No more free bricks! we should consider reusing bricks...");
|
||||
}
|
||||
|
||||
self.free_brick += 1;
|
||||
self.free_brick
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Default, Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
struct Material {
|
||||
pub albedo: [f32; 4],
|
||||
}
|
||||
|
||||
impl Material {
|
||||
pub fn set_albedo(&mut self, r: f32, g: f32, b:f32)
|
||||
{
|
||||
self.albedo[0] = r;
|
||||
self.albedo[1] = g;
|
||||
self.albedo[2] = b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct MaterialBuffer {
|
||||
materials: [Material; 256],
|
||||
pub buffer: wgpu::Buffer,
|
||||
pub bind_layout: wgpu::BindGroupLayout,
|
||||
pub bind_group: wgpu::BindGroup
|
||||
}
|
||||
|
||||
impl MaterialBuffer {
|
||||
|
||||
pub fn new(device: &wgpu::Device) -> Self {
|
||||
// Create values
|
||||
let mut materials: [Material; 256] = [Default::default(); 256];
|
||||
materials[0].set_albedo(0.41,0.33,0.20);
|
||||
materials[1].set_albedo(0.49,0.74,0.00);
|
||||
|
||||
// Create buffer
|
||||
let buffer = device.create_buffer_init(
|
||||
&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Materials buffer"),
|
||||
contents: bytemuck::cast_slice(&materials),
|
||||
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
}
|
||||
);
|
||||
|
||||
// Create bind group
|
||||
let bind_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
}
|
||||
],
|
||||
label: Some("Materials buffer layout"),
|
||||
});
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: buffer.as_entire_binding(),
|
||||
}
|
||||
],
|
||||
label: Some("Materials buffer group"),
|
||||
});
|
||||
|
||||
// Done
|
||||
MaterialBuffer { buffer, materials, bind_layout, bind_group }
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,20 @@
|
||||
|
||||
// Consts
|
||||
|
||||
pub const WORLD_SIZE: usize = 32;
|
||||
pub const NUM_NODES: usize = (WORLD_SIZE*WORLD_SIZE*WORLD_SIZE) as usize;
|
||||
|
||||
pub const BRICK_SIZE : usize = 32; // 32x32x32 brick size
|
||||
pub const BRICK_NUM : usize = 32768; // max bricks in texture
|
||||
pub const BRICK_LEN : usize = BRICK_SIZE*BRICK_SIZE*BRICK_SIZE;
|
||||
|
||||
// Import names
|
||||
|
||||
mod node_buffer;
|
||||
pub use node_buffer::NodeBuffer;
|
||||
|
||||
mod brick_buffer;
|
||||
pub use brick_buffer::BrickBuffer;
|
||||
pub use brick_buffer::{BrickBuffer};
|
||||
|
||||
mod uniform_buffer;
|
||||
pub use uniform_buffer::UniformBuffer;
|
||||
@@ -11,4 +22,7 @@ pub use uniform_buffer::UniformValues;
|
||||
|
||||
mod raster_buffer;
|
||||
pub use raster_buffer::RasterBuffer;
|
||||
pub use raster_buffer::Vertex;
|
||||
pub use raster_buffer::Vertex;
|
||||
|
||||
mod material_buffer;
|
||||
pub use material_buffer::MaterialBuffer;
|
||||
@@ -1,31 +1,10 @@
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use rand::prelude::*;
|
||||
|
||||
// 4x4x4 nodes
|
||||
const WORLD_SIZE: usize = 32;
|
||||
const NUM_NODES: usize = (WORLD_SIZE*WORLD_SIZE*WORLD_SIZE) as usize;
|
||||
|
||||
struct NodeData {
|
||||
pub data: Box<[u32]>
|
||||
}
|
||||
|
||||
impl NodeData {
|
||||
|
||||
pub fn new() -> Self {
|
||||
let data = vec![0_u32; NUM_NODES].into_boxed_slice();
|
||||
Self { data }
|
||||
}
|
||||
|
||||
pub fn set(&mut self, x: usize, y: usize, z: usize, value: u32)
|
||||
{
|
||||
let idx = x + WORLD_SIZE * (y + WORLD_SIZE * z);
|
||||
self.data[idx] = value;
|
||||
}
|
||||
}
|
||||
|
||||
use crate::renderer::buffers::{WORLD_SIZE, NUM_NODES};
|
||||
|
||||
pub struct NodeBuffer {
|
||||
nodes: NodeData,
|
||||
pub nodes: Box<[u32]>,
|
||||
texture: wgpu::Texture,
|
||||
size: wgpu::Extent3d,
|
||||
pub bind_layout: wgpu::BindGroupLayout,
|
||||
@@ -90,23 +69,8 @@ impl NodeBuffer {
|
||||
);
|
||||
|
||||
// Data
|
||||
let mut nodes = NodeData::new();
|
||||
|
||||
// let mut rng = rand::thread_rng();
|
||||
// for x in 0..WORLD_SIZE {
|
||||
// for y in 0..WORLD_SIZE {
|
||||
// for z in 0..WORLD_SIZE {
|
||||
// let value = if rng.gen::<f32>()> 0.5 { 1 } else { 0 };
|
||||
// nodes.set(x, y, z, value);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
for i in 0..WORLD_SIZE {
|
||||
nodes.set(i, 0, 0, 1);
|
||||
nodes.set(0, i, 0, 1);
|
||||
nodes.set(0, 0, i, 1);
|
||||
}
|
||||
nodes.set(0, 0, 0, 2);
|
||||
let nodes = vec![0_u32; NUM_NODES].into_boxed_slice();
|
||||
println!("Node buffer size: {} MB", nodes.len() as f32 * 4.0 / 1024.0 / 1024.0);
|
||||
|
||||
// Done
|
||||
Self { nodes, texture, size, bind_layout, bind_group }
|
||||
@@ -115,7 +79,7 @@ impl NodeBuffer {
|
||||
pub fn write(&mut self, queue: &wgpu::Queue) {
|
||||
// Convert 32 bit values to 8 bit
|
||||
let mut bytes = [0_u8; NUM_NODES*4];
|
||||
LittleEndian::write_u32_into(&self.nodes.data, &mut bytes);
|
||||
LittleEndian::write_u32_into(&self.nodes, &mut bytes);
|
||||
|
||||
// Write
|
||||
queue.write_texture(
|
||||
|
||||
Reference in New Issue
Block a user