diff options
author | metamuffin <metamuffin@disroot.org> | 2025-01-06 22:36:03 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-01-06 22:36:03 +0100 |
commit | 45282d3a54cc50306383c41e4c7e3d982cac69d1 (patch) | |
tree | d9b9046dae519f1e48716a7497c1dc8505d5e4d8 /client | |
parent | 44ef37bca0aa633f8c59d849946faf2319c5446b (diff) | |
download | weareserver-45282d3a54cc50306383c41e4c7e3d982cac69d1.tar weareserver-45282d3a54cc50306383c41e4c7e3d982cac69d1.tar.bz2 weareserver-45282d3a54cc50306383c41e4c7e3d982cac69d1.tar.zst |
mesh not visible
Diffstat (limited to 'client')
-rw-r--r-- | client/src/main.rs | 1 | ||||
-rw-r--r-- | client/src/renderer.rs | 28 | ||||
-rw-r--r-- | client/src/scene_prepare.rs | 111 | ||||
-rw-r--r-- | client/src/scene_render.rs | 30 | ||||
-rw-r--r-- | client/src/shader.wgsl | 33 |
5 files changed, 141 insertions, 62 deletions
diff --git a/client/src/main.rs b/client/src/main.rs index cfbd052..1b615d1 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,3 +1,4 @@ +#![feature(iter_array_chunks)] pub mod download; pub mod network; pub mod renderer; diff --git a/client/src/renderer.rs b/client/src/renderer.rs index 7116a20..34450b2 100644 --- a/client/src/renderer.rs +++ b/client/src/renderer.rs @@ -1,7 +1,8 @@ -use crate::{download::Downloader, scene_prepare::ScenePreparer, scene_render::ScenePipeline}; -use anyhow::{Context, Result, anyhow}; +use crate::{scene_prepare::ScenePreparer, scene_render::ScenePipeline}; +use anyhow::{Result, anyhow}; use log::{info, warn}; use pollster::FutureExt; +use std::sync::Arc; use weareshared::tree::SceneTree; use wgpu::{ Backends, CommandEncoderDescriptor, Device, DeviceDescriptor, Features, Instance, @@ -13,10 +14,11 @@ use winit::window::Window; pub struct Renderer<'a> { surface: Surface<'a>, queue: Queue, - device: Device, + device: Arc<Device>, surface_configuration: SurfaceConfiguration, scene_pipeline: ScenePipeline, pub scene_prepare: ScenePreparer, + surface_needs_reconfigure: bool, } impl<'a> Renderer<'a> { pub fn new(window: &'a Window) -> Result<Self> { @@ -39,8 +41,11 @@ impl<'a> Renderer<'a> { let (device, queue) = adapter .request_device( &DeviceDescriptor { - required_features: Features::default(), - required_limits: Limits::downlevel_defaults(), + required_features: Features::PUSH_CONSTANTS, + required_limits: Limits { + max_push_constant_size: 48, + ..Limits::default() + }, ..Default::default() }, None, @@ -53,13 +58,16 @@ impl<'a> Renderer<'a> { surface.configure(&device, &surface_configuration); + let device = Arc::new(device); + Ok(Self { scene_pipeline: ScenePipeline::new(&device, surface_configuration.format), - scene_prepare: ScenePreparer::new(), + scene_prepare: ScenePreparer::new(device.clone()), surface, device, queue, surface_configuration, + surface_needs_reconfigure: false, }) } @@ -71,9 +79,15 @@ impl<'a> Renderer<'a> { } pub fn draw(&mut self, scene: &SceneTree) -> Result<()> { + if self.surface_needs_reconfigure { + self.surface + .configure(&self.device, &self.surface_configuration); + self.surface_needs_reconfigure = false + } let target = self.surface.get_current_texture()?; if target.suboptimal { - warn!("suboptimal swapchain texture") + warn!("suboptimal swapchain texture"); + self.surface_needs_reconfigure = true; } let target_view = target .texture diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs index 8d50fc3..47f168d 100644 --- a/client/src/scene_prepare.rs +++ b/client/src/scene_prepare.rs @@ -1,5 +1,6 @@ use crate::download::Downloader; use anyhow::{Context, Result}; +use log::{debug, info}; use std::{ collections::{HashMap, HashSet}, sync::Arc, @@ -8,8 +9,12 @@ use weareshared::{ Affine3A, packets::{ReadWrite, Resource}, resources::{Attribute, Part, Prefab}, + store::sha256, +}; +use wgpu::{ + Buffer, BufferUsages, Device, + util::{BufferInitDescriptor, DeviceExt}, }; -use wgpu::Buffer; pub struct ScenePreparer { index_buffers: HashMap<Resource, (Arc<Buffer>, u32)>, @@ -20,6 +25,8 @@ pub struct ScenePreparer { parts_needed: HashSet<Resource>, pub prefabs: HashMap<Resource, RPrefab>, pub prefabs_needed: HashSet<Resource>, + + device: Arc<Device>, } pub struct RPrefab(pub Vec<(Affine3A, Arc<RPart>)>); @@ -32,7 +39,7 @@ pub struct RPart { } impl ScenePreparer { - pub fn new() -> Self { + pub fn new(device: Arc<Device>) -> Self { Self { index_buffers: HashMap::new(), vertex_buffers: HashMap::new(), @@ -42,6 +49,7 @@ impl ScenePreparer { prefabs: HashMap::new(), prefabs_needed: HashSet::new(), index_buffers_needed: HashSet::new(), + device, } } pub fn update(&mut self, dls: &mut Downloader) -> Result<()> { @@ -59,12 +67,45 @@ impl ScenePreparer { } if rprefab.0.len() == prefab.0.len() { self.prefabs.insert(*pres, rprefab); + debug!("prefab created ({pres})"); done.push(*pres); } } } for pres in &self.index_buffers_needed { - if let Some(buf) = dls.try_get(*pres)? {} + if let Some(buf) = dls.try_get(*pres)? { + let buffer = self.device.create_buffer_init(&BufferInitDescriptor { + contents: &buf, + label: None, + usage: BufferUsages::INDEX | BufferUsages::COPY_DST, + }); + self.index_buffers + .insert(*pres, (Arc::new(buffer), buf.len() as u32 / 2)); + debug!("index buffer created (len={}) {pres}", buf.len() / 6); + done.push(*pres); + } + } + for pres in &self.vertex_buffers_needed { + if let Some(buf) = dls.try_get(*pres)? { + let buf = buf + .into_iter() + .array_chunks::<4>() + .map(f32::from_be_bytes) + .map(f32::to_le_bytes) + .flatten() + .collect::<Vec<_>>(); + let buffer = self.device.create_buffer_init(&BufferInitDescriptor { + contents: &buf, + label: None, + usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, + }); + self.vertex_buffers.insert(*pres, Arc::new(buffer)); + debug!( + "vertex attribute buffer created (len={}) {pres}", + buf.len() / 4 + ); + done.push(*pres); + } } for pres in &self.parts_needed { if let Some(buf) = dls.try_get(*pres)? { @@ -80,64 +121,72 @@ impl ScenePreparer { self.index_buffers_needed.insert(indexres); continue; }; - let mut positions = Vec::new(); + let mut position = Vec::new(); for vr in positionres { match vr { Attribute::Constant(_) => todo!(), Attribute::Vertex(resource) => { - let Some(vertex) = self.vertex_buffers.get(&resource).cloned() - else { - self.vertex_buffers_needed.insert(indexres); - continue; + if let Some(vertex) = self.vertex_buffers.get(&resource).cloned() { + position.push(vertex); + } else { + self.vertex_buffers_needed.insert(resource); }; - positions.push(vertex); } Attribute::Texture(_resource) => todo!(), } } - let mut normals = Vec::new(); + let mut normal = Vec::new(); for vr in normalres { match vr { Attribute::Constant(_) => todo!(), Attribute::Vertex(resource) => { - let Some(vertex) = self.vertex_buffers.get(&resource).cloned() - else { - self.vertex_buffers_needed.insert(indexres); - continue; + if let Some(vertex) = self.vertex_buffers.get(&resource).cloned() { + normal.push(vertex); + } else { + self.vertex_buffers_needed.insert(resource); }; - normals.push(vertex); } Attribute::Texture(_resource) => todo!(), } } - let mut texcoords = Vec::new(); + let mut texcoord = Vec::new(); for vr in texcoordres { match vr { Attribute::Constant(_) => todo!(), Attribute::Vertex(resource) => { - let Some(vertex) = self.vertex_buffers.get(&resource).cloned() - else { - self.vertex_buffers_needed.insert(indexres); - continue; + if let Some(vertex) = self.vertex_buffers.get(&resource).cloned() { + texcoord.push(vertex); + } else { + self.vertex_buffers_needed.insert(resource); }; - texcoords.push(vertex); } Attribute::Texture(_resource) => todo!(), } } - self.parts.insert( - *pres, - Arc::new(RPart { - index_count, - index, - texcoord: texcoords.try_into().unwrap(), - normal: normals.try_into().unwrap(), - position: positions.try_into().unwrap(), - }), - ); + if texcoord.len() == 2 && normal.len() == 3 && position.len() == 3 { + debug!("part created ({pres})"); + self.parts.insert( + *pres, + Arc::new(RPart { + index_count, + index, + texcoord: texcoord.try_into().unwrap(), + normal: normal.try_into().unwrap(), + position: position.try_into().unwrap(), + }), + ); + done.push(*pres); + } } } } + + for d in done { + self.parts_needed.remove(&d); + self.prefabs_needed.remove(&d); + self.index_buffers_needed.remove(&d); + self.vertex_buffers_needed.remove(&d); + } Ok(()) } } diff --git a/client/src/scene_render.rs b/client/src/scene_render.rs index 366b956..b2cd915 100644 --- a/client/src/scene_render.rs +++ b/client/src/scene_render.rs @@ -4,7 +4,7 @@ use wgpu::{ BindGroup, BindGroupDescriptor, BindGroupLayoutDescriptor, BlendState, Color, ColorTargetState, ColorWrites, CommandEncoder, Device, FragmentState, FrontFace, IndexFormat, LoadOp, MultisampleState, Operations, PipelineCompilationOptions, PipelineLayoutDescriptor, - PolygonMode, PrimitiveState, PrimitiveTopology, RenderPassColorAttachment, + PolygonMode, PrimitiveState, PrimitiveTopology, PushConstantRange, RenderPassColorAttachment, RenderPassDescriptor, RenderPipeline, RenderPipelineDescriptor, ShaderStages, StoreOp, TextureFormat, TextureView, VertexAttribute, VertexBufferLayout, VertexFormat, VertexState, VertexStepMode, include_wgsl, @@ -33,7 +33,10 @@ impl ScenePipeline { let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor { label: None, bind_group_layouts: &[&bind_group_layout], - push_constant_ranges: &[], + push_constant_ranges: &[PushConstantRange { + range: 0..(12 * 4), + stages: ShaderStages::VERTEX, + }], }); let pipeline = device.create_render_pipeline(&RenderPipelineDescriptor { label: None, @@ -53,19 +56,12 @@ impl ScenePipeline { entry_point: Some("vs_main"), buffers: &[VertexBufferLayout { step_mode: VertexStepMode::Vertex, - array_stride: 2 * 4 * 3, - attributes: &[ - VertexAttribute { - format: VertexFormat::Float32x3, - offset: 0, - shader_location: 0, - }, - VertexAttribute { - format: VertexFormat::Float32x3, - offset: 3 * 4, - shader_location: 1, - }, - ], + array_stride: 4, + attributes: &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(|i| VertexAttribute { + format: VertexFormat::Float32, + offset: 0, + shader_location: i, + }), }], compilation_options: PipelineCompilationOptions::default(), }, @@ -111,13 +107,13 @@ impl ScenePipeline { })], ..Default::default() }); - rpass.set_bind_group(0, &self.bind_group, &[]); - rpass.set_pipeline(&self.pipeline); for ob in scene.objects.values() { if let Some(prefab) = prefabs.get(&ob.res) { for (affine, part) in &prefab.0 { let affine = affine.to_cols_array().map(|v| v.to_le_bytes()); + rpass.set_bind_group(0, &self.bind_group, &[]); + rpass.set_pipeline(&self.pipeline); rpass.set_push_constants(ShaderStages::VERTEX, 0, affine.as_flattened()); rpass.set_index_buffer(part.index.slice(..), IndexFormat::Uint16); rpass.set_vertex_buffer(0, part.position[0].slice(..)); diff --git a/client/src/shader.wgsl b/client/src/shader.wgsl index 41c21d9..68bd93d 100644 --- a/client/src/shader.wgsl +++ b/client/src/shader.wgsl @@ -1,11 +1,30 @@ -@vertex -fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> { - let x = f32(i32(in_vertex_index) % 2); - let y = f32(i32(in_vertex_index & 1u) * 2 - 1); - return vec4<f32>(x, y, 0.0, 1.0); + +struct VertexIn { + @location(0) x: f32, + @location(1) y: f32, + @location(2) z: f32, + @location(3) nx: f32, + @location(4) ny: f32, + @location(5) nz: f32, + @location(6) u: f32, + @location(7) v: f32, +} +struct VertexOut { + @builtin(position) clip: vec4<f32>, + @location(0) normal: vec3<f32>, + @location(1) uv: vec2<f32>, } +@vertex +fn vs_main(vi: VertexIn) -> VertexOut { + let vo = VertexOut( + vec4(vi.x * 0.1, vi.y * 0.1, 0., 1.), + vec3(vi.nx, vi.ny, vi.nz), + vec2(vi.u, vi.v), + ); + return vo; +} @fragment -fn fs_main() -> @location(0) vec4<f32> { - return vec4<f32>(1.0, 0.0, 0.0, 1.0); +fn fs_main(vo: VertexOut) -> @location(0) vec4<f32> { + return vec4<f32>(vo.normal, 1.0); } |