initial (bad) voxel renderer

This commit is contained in:
2024-06-04 12:11:28 -04:00
commit 7ae6a01949
31 changed files with 4268 additions and 0 deletions

View File

@@ -0,0 +1,208 @@
use super::{color::VoxelColor, view::View};
use crate::client::render::{
buf::ArrBufUpdate, storage::Storage, uniform::Uniform, RenderUpdateData,
};
pub struct VoxelPipeline {
pipeline: wgpu::RenderPipeline,
view: Uniform<View>,
bind_group_layout: wgpu::BindGroupLayout,
bind_group: wgpu::BindGroup,
texture: wgpu::Texture,
voxels: Storage<VoxelColor>,
arst: bool,
}
const WIDTH: u32 = 300;
const HEIGHT: u32 = 300;
impl VoxelPipeline {
pub fn new(device: &wgpu::Device, format: &wgpu::TextureFormat) -> Self {
// shaders
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("Tile Shader"),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
let view = Uniform::<View>::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()
});
// 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(),
],
label: Some("tile_bind_group_layout"),
});
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
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(),
],
label: Some("tile_bind_group"),
});
// pipeline
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Tile Pipeline Layout"),
bind_group_layouts: &[&bind_group_layout],
push_constant_ranges: &[],
});
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("Voxel Pipeline"),
layout: Some(&render_pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
buffers: &[],
compilation_options: wgpu::PipelineCompilationOptions::default(),
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
targets: &[Some(wgpu::ColorTargetState {
format: *format,
blend: Some(wgpu::BlendState::REPLACE),
write_mask: wgpu::ColorWrites::ALL,
})],
compilation_options: wgpu::PipelineCompilationOptions::default(),
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleStrip,
strip_index_format: None,
front_face: wgpu::FrontFace::Ccw,
cull_mode: None,
polygon_mode: wgpu::PolygonMode::Fill,
unclipped_depth: false,
conservative: false,
},
depth_stencil: None,
multisample: wgpu::MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: true,
},
multiview: None,
});
Self {
pipeline: render_pipeline,
view,
bind_group,
bind_group_layout,
texture,
voxels,
arst: false,
}
}
pub fn update(
&mut self,
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();
self.voxels.update(
device,
encoder,
belt,
data.len(),
&[ArrBufUpdate { offset: 0, data }],
);
self.arst = true;
}
self.view.update(device, encoder, belt, update_data);
}
pub fn draw<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) {
render_pass.set_pipeline(&self.pipeline);
render_pass.set_bind_group(0, &self.bind_group, &[]);
render_pass.draw(0..4, 0..1);
}
}