diff --git a/src/client/render/renderer.rs b/src/client/render/renderer.rs index 6a12c2f..fbb419c 100644 --- a/src/client/render/renderer.rs +++ b/src/client/render/renderer.rs @@ -144,7 +144,6 @@ impl<'a> Renderer<'a> { &self.device, &mut encoder, &mut self.staging_belt, - &mut self.queue, &RenderUpdateData { state, size: &self.size, diff --git a/src/client/render/voxel/group.rs b/src/client/render/voxel/group.rs new file mode 100644 index 0000000..c4a5b41 --- /dev/null +++ b/src/client/render/voxel/group.rs @@ -0,0 +1,10 @@ +use nalgebra::{Transform3, Vector3}; + +#[repr(C, align(16))] +#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Zeroable)] +pub struct VoxelGroup { + pub transform: Transform3, + pub dimensions: Vector3, +} + +unsafe impl bytemuck::Pod for VoxelGroup {} diff --git a/src/client/render/voxel/mod.rs b/src/client/render/voxel/mod.rs index 0d46023..ca7ecb4 100644 --- a/src/client/render/voxel/mod.rs +++ b/src/client/render/voxel/mod.rs @@ -2,5 +2,6 @@ mod grid; mod view; mod pipeline; mod color; +mod group; pub use pipeline::*; diff --git a/src/client/render/voxel/pipeline.rs b/src/client/render/voxel/pipeline.rs index bc2e20d..8ca660b 100644 --- a/src/client/render/voxel/pipeline.rs +++ b/src/client/render/voxel/pipeline.rs @@ -1,4 +1,6 @@ -use super::{color::VoxelColor, view::View}; +use nalgebra::{Rotation3, Transform3, Translation3, Vector3}; + +use super::{color::VoxelColor, group::VoxelGroup, view::View}; use crate::client::render::{ buf::ArrBufUpdate, storage::Storage, uniform::Uniform, RenderUpdateData, }; @@ -8,7 +10,7 @@ pub struct VoxelPipeline { view: Uniform, bind_group_layout: wgpu::BindGroupLayout, bind_group: wgpu::BindGroup, - texture: wgpu::Texture, + voxel_groups: Storage, voxels: Storage, arst: bool, } @@ -24,56 +26,16 @@ impl VoxelPipeline { source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()), }); - let view = Uniform::::init(device, "View", 0); - let texture_size = wgpu::Extent3d { - width: WIDTH, - height: HEIGHT, - depth_or_array_layers: 1, - }; - let texture = device.create_texture(&wgpu::TextureDescriptor { - size: texture_size, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, - usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, - label: Some("diffuse_texture"), - view_formats: &[], - }); - let voxels = Storage::init(device, "voxels", 3); - - let diffuse_texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default()); - let diffuse_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::Linear, - min_filter: wgpu::FilterMode::Nearest, - mipmap_filter: wgpu::FilterMode::Nearest, - ..Default::default() - }); + let view = Uniform::::init(device, "view", 0); + let voxels = Storage::init(device, "voxels", 1); + let voxel_groups = Storage::init(device, "voxel groups", 2); // bind groups let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { entries: &[ view.bind_group_layout_entry(), - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - multisampled: false, - view_dimension: wgpu::TextureViewDimension::D2, - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, voxels.bind_group_layout_entry(), + voxel_groups.bind_group_layout_entry(), ], label: Some("tile_bind_group_layout"), }); @@ -82,15 +44,8 @@ impl VoxelPipeline { layout: &bind_group_layout, entries: &[ view.bind_group_entry(), - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::TextureView(&diffuse_texture_view), - }, - wgpu::BindGroupEntry { - binding: 2, - resource: wgpu::BindingResource::Sampler(&diffuse_sampler), - }, voxels.bind_group_entry(), + voxel_groups.bind_group_entry(), ], label: Some("tile_bind_group"), }); @@ -145,8 +100,8 @@ impl VoxelPipeline { view, bind_group, bind_group_layout, - texture, voxels, + voxel_groups, arst: false, } } @@ -156,38 +111,37 @@ impl VoxelPipeline { device: &wgpu::Device, encoder: &mut wgpu::CommandEncoder, belt: &mut wgpu::util::StagingBelt, - queue: &mut wgpu::Queue, update_data: &RenderUpdateData, ) { - let texture_size = wgpu::Extent3d { - width: WIDTH, - height: HEIGHT, - depth_or_array_layers: 1, - }; if !self.arst { - queue.write_texture( - // Tells wgpu where to copy the pixel data - wgpu::ImageCopyTexture { - texture: &self.texture, - mip_level: 0, - origin: wgpu::Origin3d::ZERO, - aspect: wgpu::TextureAspect::All, - }, - // The actual pixel data - &[0xff, 0x00, 0xff, 0xff].repeat((WIDTH * HEIGHT) as usize), - // The layout of the texture - wgpu::ImageDataLayout { - offset: 0, - bytes_per_row: Some(4 * WIDTH), - rows_per_image: Some(HEIGHT), - }, - texture_size, - ); - let l = 10; - let size = l * l * l; - let mut data: Vec<_> = vec![VoxelColor::none(); size]; - data[0] = VoxelColor::white(); - data[size - 1] = VoxelColor::white(); + let lx = 15; + let ly = 10; + let lz = 10; + let size = lx * ly * lz; + let mut data = vec![VoxelColor::none(); size]; + for x in 0..lx { + for y in 0..ly { + data[x + y * lx] = VoxelColor { + r: (x as f32 / lx as f32 * 255.0) as u8, + g: (y as f32 / ly as f32 * 255.0) as u8, + b: 0, + a: 20, + }; + } + } + for x in 0..lx { + for y in 0..ly { + data[x + y * lx + 3 * lx * ly] = VoxelColor { + r: (x as f32 / lx as f32 * 255.0) as u8, + g: (y as f32 / ly as f32 * 255.0) as u8, + b: 100, + a: 255, + }; + } + } + for i in 0..lx.min(ly.min(lz)) { + data[i + i * lx + i * lx * ly] = VoxelColor::white(); + } self.voxels.update( device, encoder, @@ -195,6 +149,32 @@ impl VoxelPipeline { data.len(), &[ArrBufUpdate { offset: 0, data }], ); + let group = VoxelGroup { + transform: Transform3::identity() + * (Translation3::new(-5.0, -5.0, 20.0) + * Rotation3::from_axis_angle(&Vector3::y_axis(), 0.5)).inverse(), + dimensions: Vector3::new(lx as u32, ly as u32, lz as u32), + }; + self.voxel_groups.update( + device, + encoder, + belt, + 1, + &[ArrBufUpdate { + offset: 0, + data: vec![group], + }], + ); + self.bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &self.bind_group_layout, + entries: &[ + self.view.bind_group_entry(), + self.voxels.bind_group_entry(), + self.voxel_groups.bind_group_entry(), + ], + label: Some("tile_bind_group"), + }); + self.arst = true; } self.view.update(device, encoder, belt, update_data); diff --git a/src/client/render/voxel/shader.wgsl b/src/client/render/voxel/shader.wgsl index 34dcd56..8ebbf97 100644 --- a/src/client/render/voxel/shader.wgsl +++ b/src/client/render/voxel/shader.wgsl @@ -13,14 +13,17 @@ struct View { transform: mat4x4, }; +struct VoxelGroup { + transform: mat4x4, + dimensions: vec3, +}; + @group(0) @binding(0) var view: View; @group(0) @binding(1) -var t_diffuse: texture_2d; -@group(0) @binding(2) -var s_diffuse: sampler; -@group(0) @binding(3) var voxels: array; +@group(0) @binding(2) +var voxel_groups: array; @vertex fn vs_main( @@ -52,30 +55,34 @@ fn fs_main( pixel_pos.y *= 2.0; pixel_pos.y *= aspect; - pixel_pos = (view.transform * vec4(pixel_pos, 1.0)).xyz; - let origin = (view.transform * vec4(0.0, 0.0, 0.0, 1.0)).xyz; + let group = voxel_groups[0]; + let dim_f = vec3(group.dimensions); + + // this should definitely be done per pixel trust me guys + let transform = group.transform * view.transform; + pixel_pos = (transform * vec4(pixel_pos, 1.0)).xyz; + let origin = (transform * vec4(0.0, 0.0, 0.0, 1.0)).xyz; let dir = normalize(pixel_pos - origin); - let voxel_pos = vec3(-5.0, -5.0, 30.0); var t = 0; + var color = vec4(0.0, 0.0, 0.0, 0.0); for(t = 0; t < 1000; t += 1) { - let pos = pixel_pos + f32(t) * 0.1 * dir - voxel_pos; - let rel_coords = vec3(pos.xyz); - if rel_coords.x < 0 || rel_coords.y < 0 || rel_coords.z < 0 || rel_coords.x > 10 || rel_coords.y > 10 || rel_coords.z > 10 { + let pos = pixel_pos + f32(t) * 0.1 * dir; + if pos.x < 0.0 || pos.y < 0.0 || pos.z < 0.0 || pos.x > dim_f.x || pos.y > dim_f.y || pos.z > dim_f.z { continue; } else { - let i = rel_coords.x + rel_coords.y * 10 + rel_coords.z * 100; - let color = unpack4x8unorm(voxels[i]); - if voxels[i] != 0 { - return vec4(1.0); - } else { - let pos = vec3(rel_coords); - return vec4(pos.x / 10.0, pos.y / 10.0, pos.z / 10.0, 1.0); + let rel_coords = vec3(pos.xyz); + let i = u32(rel_coords.x + rel_coords.y * group.dimensions.x + rel_coords.z * group.dimensions.x * group.dimensions.y); + let vcolor = unpack4x8unorm(voxels[i]); + // now I understand premultiplied alpha lmao + color += vec4(vcolor.xyz * vcolor.a * (1.0 - color.a), (1.0 - color.a) * vcolor.a); + if color.a == 1.0 { + break; } } } - return vec4(0.0, 0.0, 0.0, 1.0); + return color; }