Begin using basic brickmap. Doesn't include shading table
This commit is contained in:
parent
5914efaea8
commit
6be2dd8054
|
@ -1,7 +1,12 @@
|
||||||
@group(0) @binding(0) var output: texture_storage_2d<rgba8unorm, write>;
|
@group(0) @binding(0) var output: texture_storage_2d<rgba8unorm, write>;
|
||||||
@group(0) @binding(1) var<uniform> camera: Camera;
|
@group(0) @binding(1) var<storage, read> brickmap: Brickmap;
|
||||||
@group(1) @binding(0) var voxels_t: texture_3d<f32>;
|
@group(0) @binding(2) var<uniform> camera: Camera;
|
||||||
@group(1) @binding(1) var voxels_s: sampler;
|
|
||||||
|
struct Brickmap {
|
||||||
|
bitmask: array<u32, 16>,
|
||||||
|
shading_table_offset: u32,
|
||||||
|
lod_color: u32,
|
||||||
|
}
|
||||||
|
|
||||||
struct Camera {
|
struct Camera {
|
||||||
projection: mat4x4<f32>,
|
projection: mat4x4<f32>,
|
||||||
|
@ -24,7 +29,7 @@ struct AabbHitInfo {
|
||||||
fn ray_intersect_aabb(ray_pos: vec3<f32>, ray_dir: vec3<f32>) -> AabbHitInfo {
|
fn ray_intersect_aabb(ray_pos: vec3<f32>, ray_dir: vec3<f32>) -> AabbHitInfo {
|
||||||
let ray_dir_inv = 1.0 / ray_dir;
|
let ray_dir_inv = 1.0 / ray_dir;
|
||||||
let t1 = (vec3<f32>(0.0) - ray_pos) * ray_dir_inv;
|
let t1 = (vec3<f32>(0.0) - ray_pos) * ray_dir_inv;
|
||||||
let t2 = (vec3<f32>(textureDimensions(voxels_t)) - ray_pos) * ray_dir_inv;
|
let t2 = (vec3<f32>(8.0) - ray_pos) * ray_dir_inv;
|
||||||
let t_min = min(t1, t2);
|
let t_min = min(t1, t2);
|
||||||
let t_max = max(t1, t2);
|
let t_max = max(t1, t2);
|
||||||
let tmin = max(max(t_min.x, 0.0), max(t_min.y, t_min.z));
|
let tmin = max(max(t_min.x, 0.0), max(t_min.y, t_min.z));
|
||||||
|
@ -33,13 +38,13 @@ fn ray_intersect_aabb(ray_pos: vec3<f32>, ray_dir: vec3<f32>) -> AabbHitInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn point_inside_aabb(p: vec3<i32>) -> bool {
|
fn point_inside_aabb(p: vec3<i32>) -> bool {
|
||||||
let clamped = clamp(p, vec3<i32>(0), textureDimensions(voxels_t) - vec3<i32>(1));
|
let clamped = clamp(p, vec3<i32>(0), vec3<i32>(8) - vec3<i32>(1));
|
||||||
return clamped.x == p.x && clamped.y == p.y && clamped.z == p.z;
|
return clamped.x == p.x && clamped.y == p.y && clamped.z == p.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn voxel_hit(p: vec3<i32>) -> bool {
|
fn voxel_hit(p: vec3<i32>) -> bool {
|
||||||
let v = textureLoad(voxels_t, p, 0);
|
let local_index = u32(p.x + p.y * 8 + p.z * 64);
|
||||||
return length(v) != 0.0;
|
return (brickmap.bitmask[local_index / 32u] >> (local_index % 32u) & 1u) != 0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cast_ray(orig_ray_pos: vec3<f32>, ray_dir: vec3<f32>) -> HitInfo {
|
fn cast_ray(orig_ray_pos: vec3<f32>, ray_dir: vec3<f32>) -> HitInfo {
|
||||||
|
@ -125,19 +130,19 @@ fn compute(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
||||||
var hit_info = cast_ray(ray_pos, ray_dir);
|
var hit_info = cast_ray(ray_pos, ray_dir);
|
||||||
var color = vec4<f32>(0.0, 0.0, 0.0, 1.0);
|
var color = vec4<f32>(0.0, 0.0, 0.0, 1.0);
|
||||||
if (hit_info.hit){
|
if (hit_info.hit){
|
||||||
// if (hit_info.mask.x) {
|
if (hit_info.mask.x) {
|
||||||
// color.x = 1.0;
|
color.x = 1.0;
|
||||||
// }
|
}
|
||||||
// else if (hit_info.mask.y) {
|
else if (hit_info.mask.y) {
|
||||||
// color.y = 1.0;
|
color.y = 1.0;
|
||||||
// }
|
}
|
||||||
// else if (hit_info.mask.z) {
|
else if (hit_info.mask.z) {
|
||||||
// color.z = 1.0;
|
color.z = 1.0;
|
||||||
// }
|
}
|
||||||
// else {
|
else {
|
||||||
// color = vec4<f32>(1.0);
|
color = vec4<f32>(1.0);
|
||||||
// }
|
}
|
||||||
color = textureLoad(voxels_t, hit_info.hit_pos, 0);
|
// color = textureLoad(voxels_t, hit_info.hit_pos, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
textureStore(output, img_coord, color);
|
textureStore(output, img_coord, color);
|
||||||
|
|
|
@ -4,6 +4,7 @@ use winit::event::{ElementState, KeyboardInput, VirtualKeyCode, WindowEvent};
|
||||||
|
|
||||||
use crate::render::Context;
|
use crate::render::Context;
|
||||||
|
|
||||||
|
// TODO: Implement Default rather than using new()
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
pub struct CameraUniform {
|
pub struct CameraUniform {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod brickmap;
|
||||||
mod voxel_renderer;
|
mod voxel_renderer;
|
||||||
|
|
||||||
pub use voxel_renderer::*;
|
pub use voxel_renderer::*;
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
|
use crate::render;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
|
pub struct BrickmapUniform {
|
||||||
|
pub bitmask: [u32; 16],
|
||||||
|
pub shading_table_offset: u32,
|
||||||
|
pub lod_color: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BrickmapUniform {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
bitmask: [0; 16],
|
||||||
|
shading_table_offset: 0,
|
||||||
|
lod_color: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BrickmapManager {
|
||||||
|
uniform: BrickmapUniform,
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
|
||||||
|
Self { uniform, buffer }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_data(&mut self, data: &[u32; 16]) {
|
||||||
|
self.uniform.bitmask = *data;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_buffer(&self, context: &render::Context) {
|
||||||
|
context
|
||||||
|
.queue
|
||||||
|
.write_buffer(&self.buffer, 0, bytemuck::cast_slice(&[self.uniform]));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_buffer(&self) -> &wgpu::Buffer {
|
||||||
|
&self.buffer
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ pub struct VoxelRenderer {
|
||||||
clear_color: wgpu::Color,
|
clear_color: wgpu::Color,
|
||||||
render_texture: render::Texture,
|
render_texture: render::Texture,
|
||||||
render_pipeline: wgpu::RenderPipeline,
|
render_pipeline: wgpu::RenderPipeline,
|
||||||
voxel_texture: render::Texture,
|
brickmap_manager: super::brickmap::BrickmapManager,
|
||||||
compute_pipeline: wgpu::ComputePipeline,
|
compute_pipeline: wgpu::ComputePipeline,
|
||||||
compute_bind_group: wgpu::BindGroup,
|
compute_bind_group: wgpu::BindGroup,
|
||||||
}
|
}
|
||||||
|
@ -59,40 +59,25 @@ impl VoxelRenderer {
|
||||||
multiview: None,
|
multiview: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
log::info!("Creating voxel volume texture...");
|
log::info!("Creating brickmap manager...");
|
||||||
let voxel_texture = render::TextureBuilder::new()
|
let mut brickmap_manager = super::brickmap::BrickmapManager::new(context);
|
||||||
.with_size(8, 8, 8)
|
let mut data = [0xFFFFFFFF as u32; 16];
|
||||||
.with_dimension(wgpu::TextureDimension::D3)
|
|
||||||
.with_format(wgpu::TextureFormat::Rgba8Unorm)
|
|
||||||
.with_usage(
|
|
||||||
wgpu::TextureUsages::TEXTURE_BINDING
|
|
||||||
| wgpu::TextureUsages::COPY_DST
|
|
||||||
| wgpu::TextureUsages::STORAGE_BINDING,
|
|
||||||
)
|
|
||||||
.with_shader_visibility(wgpu::ShaderStages::COMPUTE)
|
|
||||||
.build(&context);
|
|
||||||
|
|
||||||
let data_len = 8 * 8 * 8 * 4;
|
|
||||||
let mut data: Vec<u8> = Vec::with_capacity(data_len.try_into().unwrap());
|
|
||||||
for z in 0..8 {
|
for z in 0..8 {
|
||||||
|
let mut entry = 0u64;
|
||||||
for y in 0..8 {
|
for y in 0..8 {
|
||||||
for x 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);
|
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) {
|
if pos.length_squared() <= (u32::pow(4, 2) as f32) {
|
||||||
data.push(((x + 1) * 32 - 1) as u8);
|
entry += 1 << idx;
|
||||||
data.push(((y + 1) * 32 - 1) as u8);
|
|
||||||
data.push(((z + 1) * 32 - 1) as u8);
|
|
||||||
data.push(255u8);
|
|
||||||
} else {
|
|
||||||
data.push(0u8);
|
|
||||||
data.push(0u8);
|
|
||||||
data.push(0u8);
|
|
||||||
data.push(0u8);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
data[2 * z] = (entry & 0xFFFFFFFF).try_into().unwrap();
|
||||||
|
data[2 * z + 1] = ((entry >> 32) & 0xFFFFFFFF).try_into().unwrap();
|
||||||
}
|
}
|
||||||
voxel_texture.update(&context, &data);
|
brickmap_manager.set_data(&data);
|
||||||
|
brickmap_manager.update_buffer(context);
|
||||||
|
|
||||||
log::info!("Creating compute pipeline...");
|
log::info!("Creating compute pipeline...");
|
||||||
let cs_descriptor = wgpu::include_wgsl!("../../assets/shaders/voxel_volume.wgsl");
|
let cs_descriptor = wgpu::include_wgsl!("../../assets/shaders/voxel_volume.wgsl");
|
||||||
|
@ -107,6 +92,15 @@ impl VoxelRenderer {
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
.with_entry(
|
||||||
|
wgpu::ShaderStages::COMPUTE,
|
||||||
|
wgpu::BindingType::Buffer {
|
||||||
|
ty: wgpu::BufferBindingType::Storage { read_only: true },
|
||||||
|
has_dynamic_offset: false,
|
||||||
|
min_binding_size: None,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
.with_entry(
|
.with_entry(
|
||||||
wgpu::ShaderStages::COMPUTE,
|
wgpu::ShaderStages::COMPUTE,
|
||||||
wgpu::BindingType::Buffer {
|
wgpu::BindingType::Buffer {
|
||||||
|
@ -120,6 +114,7 @@ impl VoxelRenderer {
|
||||||
let compute_bind_group = render::BindGroupBuilder::new()
|
let compute_bind_group = render::BindGroupBuilder::new()
|
||||||
.with_layout(&compute_layout)
|
.with_layout(&compute_layout)
|
||||||
.with_entry(wgpu::BindingResource::TextureView(&render_texture.view))
|
.with_entry(wgpu::BindingResource::TextureView(&render_texture.view))
|
||||||
|
.with_entry(brickmap_manager.get_buffer().as_entire_binding())
|
||||||
.with_entry(camera_controller.get_buffer().as_entire_binding())
|
.with_entry(camera_controller.get_buffer().as_entire_binding())
|
||||||
.build(context);
|
.build(context);
|
||||||
let compute_pipeline =
|
let compute_pipeline =
|
||||||
|
@ -130,10 +125,7 @@ impl VoxelRenderer {
|
||||||
layout: Some(&context.device.create_pipeline_layout(
|
layout: Some(&context.device.create_pipeline_layout(
|
||||||
&wgpu::PipelineLayoutDescriptor {
|
&wgpu::PipelineLayoutDescriptor {
|
||||||
label: Some("compute"),
|
label: Some("compute"),
|
||||||
bind_group_layouts: &[
|
bind_group_layouts: &[&compute_layout],
|
||||||
&compute_layout,
|
|
||||||
&voxel_texture.bind_group_layout,
|
|
||||||
],
|
|
||||||
push_constant_ranges: &[],
|
push_constant_ranges: &[],
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
|
@ -145,7 +137,7 @@ impl VoxelRenderer {
|
||||||
clear_color: wgpu::Color::BLACK,
|
clear_color: wgpu::Color::BLACK,
|
||||||
render_texture,
|
render_texture,
|
||||||
render_pipeline,
|
render_pipeline,
|
||||||
voxel_texture,
|
brickmap_manager,
|
||||||
compute_pipeline,
|
compute_pipeline,
|
||||||
compute_bind_group,
|
compute_bind_group,
|
||||||
}
|
}
|
||||||
|
@ -167,7 +159,6 @@ impl render::Renderer for VoxelRenderer {
|
||||||
let mut compute_pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor::default());
|
let mut compute_pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor::default());
|
||||||
compute_pass.set_pipeline(&self.compute_pipeline);
|
compute_pass.set_pipeline(&self.compute_pipeline);
|
||||||
compute_pass.set_bind_group(0, &self.compute_bind_group, &[]);
|
compute_pass.set_bind_group(0, &self.compute_bind_group, &[]);
|
||||||
compute_pass.set_bind_group(1, &self.voxel_texture.bind_group, &[]);
|
|
||||||
compute_pass.dispatch_workgroups(size.width / 8, size.height / 8, 1);
|
compute_pass.dispatch_workgroups(size.width / 8, size.height / 8, 1);
|
||||||
drop(compute_pass);
|
drop(compute_pass);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue