Add initial multi-brickmap support
This commit is contained in:
parent
1d126eba10
commit
1823d8b52c
|
@ -1,7 +1,8 @@
|
|||
@group(0) @binding(0) var output: texture_storage_2d<rgba8unorm, write>;
|
||||
@group(0) @binding(1) var<storage, read> brickmap: Brickmap;
|
||||
@group(0) @binding(2) var<storage, read> shading_table: array<ShadingElement>;
|
||||
@group(0) @binding(3) var<uniform> camera: Camera;
|
||||
@group(0) @binding(1) var<uniform> world_state: WorldState;
|
||||
@group(0) @binding(2) var<storage, read> brickmap_cache: array<Brickmap>;
|
||||
@group(0) @binding(3) var<storage, read> shading_table: array<ShadingElement>;
|
||||
@group(0) @binding(4) var<uniform> camera: Camera;
|
||||
|
||||
struct ShadingElement {
|
||||
albedo: u32,
|
||||
|
@ -20,6 +21,11 @@ struct Camera {
|
|||
_pad: f32,
|
||||
};
|
||||
|
||||
struct WorldState {
|
||||
brickmap_cache_dims: vec3<u32>,
|
||||
_pad: u32,
|
||||
};
|
||||
|
||||
struct HitInfo {
|
||||
hit: bool,
|
||||
hit_pos: vec3<i32>,
|
||||
|
@ -32,21 +38,37 @@ struct AabbHitInfo {
|
|||
};
|
||||
|
||||
fn get_shading_offset(p: vec3<i32>) -> u32 {
|
||||
let local_index = u32(p.x + p.y * 8 + p.z * 64);
|
||||
// return 0u;
|
||||
|
||||
// What brickmap are we in?
|
||||
let brickmap_index = (p.x / 8) + (p.y / 8) * 32 + (p.z / 8) * 1024;
|
||||
let local_index = u32((p.x % 8) + (p.y % 8) * 8 + (p.z % 8) * 64);
|
||||
let brickmap = &brickmap_cache[brickmap_index];
|
||||
let bitmask_index = local_index / 32u;
|
||||
var map_voxel_idx = 0u;
|
||||
for (var i: i32 = 0; i < i32(bitmask_index); i++) {
|
||||
map_voxel_idx += countOneBits(brickmap.bitmask[i]);
|
||||
map_voxel_idx += countOneBits((*brickmap).bitmask[i]);
|
||||
}
|
||||
let extracted_bits = extractBits(brickmap.bitmask[bitmask_index], 0u, (local_index % 32u));
|
||||
let extracted_bits = extractBits((*brickmap).bitmask[bitmask_index], 0u, (local_index % 32u));
|
||||
map_voxel_idx += countOneBits(extracted_bits);
|
||||
return brickmap.shading_table_offset + map_voxel_idx;
|
||||
return (*brickmap).shading_table_offset + map_voxel_idx;
|
||||
|
||||
|
||||
// let local_index = u32(p.x + p.y * 8 + p.z * 64);
|
||||
// let bitmask_index = local_index / 32u;
|
||||
// var map_voxel_idx = 0u;
|
||||
// for (var i: i32 = 0; i < i32(bitmask_index); i++) {
|
||||
// map_voxel_idx += countOneBits(brickmap.bitmask[i]);
|
||||
// }
|
||||
// let extracted_bits = extractBits(brickmap.bitmask[bitmask_index], 0u, (local_index % 32u));
|
||||
// map_voxel_idx += countOneBits(extracted_bits);
|
||||
// return brickmap.shading_table_offset + map_voxel_idx;
|
||||
}
|
||||
|
||||
fn ray_intersect_aabb(ray_pos: vec3<f32>, ray_dir: vec3<f32>) -> AabbHitInfo {
|
||||
let ray_dir_inv = 1.0 / ray_dir;
|
||||
let t1 = (vec3<f32>(0.0) - ray_pos) * ray_dir_inv;
|
||||
let t2 = (vec3<f32>(8.0) - ray_pos) * ray_dir_inv;
|
||||
let t2 = ((vec3<f32>(8.0) * vec3<f32>(world_state.brickmap_cache_dims)) - ray_pos) * ray_dir_inv;
|
||||
let t_min = min(t1, t2);
|
||||
let t_max = max(t1, t2);
|
||||
let tmin = max(max(t_min.x, 0.0), max(t_min.y, t_min.z));
|
||||
|
@ -55,13 +77,15 @@ fn ray_intersect_aabb(ray_pos: vec3<f32>, ray_dir: vec3<f32>) -> AabbHitInfo {
|
|||
}
|
||||
|
||||
fn point_inside_aabb(p: vec3<i32>) -> bool {
|
||||
let clamped = clamp(p, vec3<i32>(0), vec3<i32>(8) - vec3<i32>(1));
|
||||
let max = vec3<i32>(world_state.brickmap_cache_dims) * 8;
|
||||
let clamped = clamp(p, vec3<i32>(0), max - vec3<i32>(1));
|
||||
return clamped.x == p.x && clamped.y == p.y && clamped.z == p.z;
|
||||
}
|
||||
|
||||
fn voxel_hit(p: vec3<i32>) -> bool {
|
||||
let local_index = u32(p.x + p.y * 8 + p.z * 64);
|
||||
return (brickmap.bitmask[local_index / 32u] >> (local_index % 32u) & 1u) != 0u;
|
||||
let brickmap_index = (p.x / 8) + (p.y / 8) * 32 + (p.z / 8) * 1024;
|
||||
let local_index = u32((p.x % 8) + (p.y % 8) * 8 + (p.z % 8) * 64);
|
||||
return (brickmap_cache[brickmap_index].bitmask[local_index / 32u] >> (local_index % 32u) & 1u) != 0u;
|
||||
}
|
||||
|
||||
fn cast_ray(orig_ray_pos: vec3<f32>, ray_dir: vec3<f32>) -> HitInfo {
|
||||
|
@ -84,7 +108,7 @@ fn cast_ray(orig_ray_pos: vec3<f32>, ray_dir: vec3<f32>) -> HitInfo {
|
|||
var side_dist = (sign(ray_dir) * (vec3<f32>(map_pos) - ray_pos) + (sign(ray_dir) * 0.5) + 0.5) * delta_dist;
|
||||
|
||||
// TODO: don't hardcode max ray depth
|
||||
for (var i: i32 = 0; i < 64; i++) {
|
||||
for (var i: i32 = 0; i < 2048; i++) {
|
||||
if (side_dist.x < side_dist.y) {
|
||||
if (side_dist.x < side_dist.z) {
|
||||
side_dist.x += delta_dist.x;
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
use std::mem::size_of;
|
||||
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
use crate::render;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
pub struct BrickmapUniform {
|
||||
#[derive(Debug, Default, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
struct Brickmap {
|
||||
pub bitmask: [u32; 16],
|
||||
pub shading_table_offset: u32,
|
||||
pub lod_color: u32,
|
||||
}
|
||||
|
||||
impl BrickmapUniform {
|
||||
impl Brickmap {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
bitmask: [0; 16],
|
||||
|
@ -22,53 +20,84 @@ impl BrickmapUniform {
|
|||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
struct WorldState {
|
||||
brickmap_cache_dims: [u32; 3],
|
||||
_pad: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BrickmapManager {
|
||||
uniform: BrickmapUniform,
|
||||
buffer: wgpu::Buffer,
|
||||
state_uniform: WorldState,
|
||||
state_buffer: wgpu::Buffer,
|
||||
brickmap_cache: Vec<Brickmap>,
|
||||
brickmap_buffer: wgpu::Buffer,
|
||||
shading_table: Vec<u32>,
|
||||
shading_table_buffer: wgpu::Buffer,
|
||||
}
|
||||
|
||||
impl BrickmapManager {
|
||||
pub fn new(context: &render::Context) -> Self {
|
||||
let uniform = BrickmapUniform::new();
|
||||
let buffer = context
|
||||
.device
|
||||
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: bytemuck::cast_slice(&[uniform]),
|
||||
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
|
||||
});
|
||||
let mut state_uniform = WorldState::default();
|
||||
state_uniform.brickmap_cache_dims = [32, 32, 32];
|
||||
|
||||
let shading_table_buffer =
|
||||
context
|
||||
.device
|
||||
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &[0; 25000000],
|
||||
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
|
||||
});
|
||||
let mut brickmap_cache = Vec::<Brickmap>::with_capacity(32768);
|
||||
brickmap_cache.resize(32768, Brickmap::default());
|
||||
|
||||
let shading_table = Vec::<u32>::new();
|
||||
let device = &context.device;
|
||||
let state_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: bytemuck::cast_slice(&[state_uniform]),
|
||||
usage: wgpu::BufferUsages::UNIFORM,
|
||||
});
|
||||
|
||||
let brickmap_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: bytemuck::cast_slice(&brickmap_cache),
|
||||
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
|
||||
});
|
||||
|
||||
let shading_table_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: bytemuck::cast_slice(&[0u32; 25000000]),
|
||||
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
|
||||
});
|
||||
|
||||
let mut shading_table = Vec::<u32>::with_capacity(25000000);
|
||||
shading_table.resize(shading_table.capacity(), 0);
|
||||
|
||||
Self {
|
||||
uniform,
|
||||
buffer,
|
||||
state_uniform,
|
||||
state_buffer,
|
||||
brickmap_cache,
|
||||
brickmap_buffer,
|
||||
shading_table,
|
||||
shading_table_buffer,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Ideally this should take a generic voxel format and do the data mapping here
|
||||
pub fn set_data(&mut self, data: &[u32; 16], colours: &[u32]) {
|
||||
self.uniform.bitmask = *data;
|
||||
self.shading_table = colours.to_vec();
|
||||
pub fn set_data(&mut self, chunk_pos: glam::UVec3, data: &[u32; 16], colours: &[u32]) {
|
||||
let idx: usize = (chunk_pos.x + chunk_pos.y * 32 + chunk_pos.z * 1024)
|
||||
.try_into()
|
||||
.unwrap();
|
||||
let shading_idx = idx * 512;
|
||||
self.brickmap_cache[idx].bitmask = *data;
|
||||
self.brickmap_cache[idx].shading_table_offset = shading_idx as u32;
|
||||
self.shading_table.splice(
|
||||
shading_idx..(shading_idx + colours.len()),
|
||||
colours.to_owned(),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn update_buffer(&self, context: &render::Context) {
|
||||
let queue = &context.queue;
|
||||
queue.write_buffer(&self.buffer, 0, bytemuck::cast_slice(&[self.uniform]));
|
||||
queue.write_buffer(
|
||||
&self.brickmap_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&self.brickmap_cache),
|
||||
);
|
||||
queue.write_buffer(
|
||||
&self.shading_table_buffer,
|
||||
0,
|
||||
|
@ -76,8 +105,12 @@ impl BrickmapManager {
|
|||
);
|
||||
}
|
||||
|
||||
pub fn get_buffer(&self) -> &wgpu::Buffer {
|
||||
&self.buffer
|
||||
pub fn get_worldstate_buffer(&self) -> &wgpu::Buffer {
|
||||
&self.state_buffer
|
||||
}
|
||||
|
||||
pub fn get_brickmap_buffer(&self) -> &wgpu::Buffer {
|
||||
&self.brickmap_buffer
|
||||
}
|
||||
|
||||
pub fn get_shading_buffer(&self) -> &wgpu::Buffer {
|
||||
|
|
|
@ -61,29 +61,34 @@ impl VoxelRenderer {
|
|||
|
||||
log::info!("Creating brickmap manager...");
|
||||
let mut brickmap_manager = super::brickmap::BrickmapManager::new(context);
|
||||
let mut bitmask_data = [0xFFFFFFFF as u32; 16];
|
||||
let mut albedo_data = Vec::<u32>::new();
|
||||
for z in 0..8 {
|
||||
let mut entry = 0u64;
|
||||
for y in 0..8 {
|
||||
for x in 0..8 {
|
||||
let idx = x + y * 8;
|
||||
let pos = glam::vec3(x as f32, y as f32, z as f32) - glam::vec3(3.5, 3.5, 3.5);
|
||||
if pos.length_squared() <= (u32::pow(4, 2) as f32) {
|
||||
entry += 1 << idx;
|
||||
let mut albedo = 0u32;
|
||||
albedo += ((x + 1) * 32 - 1) << 24;
|
||||
albedo += ((y + 1) * 32 - 1) << 16;
|
||||
albedo += ((z + 1) * 32 - 1) << 8;
|
||||
albedo += 255;
|
||||
albedo_data.push(albedo);
|
||||
let sphere_center = glam::vec3(3.5, 3.5, 3.5);
|
||||
let sphere_r2 = u32::pow(4, 2) as f32;
|
||||
for chunk_idx in 0..32768 {
|
||||
let chunk_pos = glam::uvec3(chunk_idx % 32, (chunk_idx / 32) % 32, chunk_idx / 1024);
|
||||
let mut bitmask_data = [0xFFFFFFFF as u32; 16];
|
||||
let mut albedo_data = Vec::<u32>::new();
|
||||
for z in 0..8 {
|
||||
let mut entry = 0u64;
|
||||
for y in 0..8 {
|
||||
for x in 0..8 {
|
||||
let idx = x + y * 8;
|
||||
let pos = glam::vec3(x as f32, y as f32, z as f32);
|
||||
if (pos - sphere_center).length_squared() <= sphere_r2 {
|
||||
entry += 1 << idx;
|
||||
let mut albedo = 0u32;
|
||||
albedo += ((chunk_pos.x + 1) * 8 - 1) << 24;
|
||||
albedo += ((chunk_pos.y + 1) * 8 - 1) << 16;
|
||||
albedo += ((chunk_pos.z + 1) * 8 - 1) << 8;
|
||||
albedo += 255;
|
||||
albedo_data.push(albedo);
|
||||
}
|
||||
}
|
||||
}
|
||||
bitmask_data[2 * z as usize] = (entry & 0xFFFFFFFF).try_into().unwrap();
|
||||
bitmask_data[2 * z as usize + 1] = ((entry >> 32) & 0xFFFFFFFF).try_into().unwrap();
|
||||
}
|
||||
bitmask_data[2 * z as usize] = (entry & 0xFFFFFFFF).try_into().unwrap();
|
||||
bitmask_data[2 * z as usize + 1] = ((entry >> 32) & 0xFFFFFFFF).try_into().unwrap();
|
||||
brickmap_manager.set_data(chunk_pos, &bitmask_data, &albedo_data);
|
||||
}
|
||||
brickmap_manager.set_data(&bitmask_data, &albedo_data);
|
||||
brickmap_manager.update_buffer(context);
|
||||
|
||||
log::info!("Creating compute pipeline...");
|
||||
|
@ -99,6 +104,15 @@ impl VoxelRenderer {
|
|||
},
|
||||
None,
|
||||
)
|
||||
.with_entry(
|
||||
wgpu::ShaderStages::COMPUTE,
|
||||
wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
None,
|
||||
)
|
||||
.with_entry(
|
||||
wgpu::ShaderStages::COMPUTE,
|
||||
wgpu::BindingType::Buffer {
|
||||
|
@ -130,7 +144,8 @@ impl VoxelRenderer {
|
|||
let compute_bind_group = render::BindGroupBuilder::new()
|
||||
.with_layout(&compute_layout)
|
||||
.with_entry(wgpu::BindingResource::TextureView(&render_texture.view))
|
||||
.with_entry(brickmap_manager.get_buffer().as_entire_binding())
|
||||
.with_entry(brickmap_manager.get_worldstate_buffer().as_entire_binding())
|
||||
.with_entry(brickmap_manager.get_brickmap_buffer().as_entire_binding())
|
||||
.with_entry(brickmap_manager.get_shading_buffer().as_entire_binding())
|
||||
.with_entry(camera_controller.get_buffer().as_entire_binding())
|
||||
.build(context);
|
||||
|
|
Loading…
Reference in New Issue