diff options
Diffstat (limited to 'client/src/scene_prepare.rs')
-rw-r--r-- | client/src/scene_prepare.rs | 191 |
1 files changed, 133 insertions, 58 deletions
diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs index 5c5102d..8941fa7 100644 --- a/client/src/scene_prepare.rs +++ b/client/src/scene_prepare.rs @@ -14,12 +14,13 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ -use crate::download::Downloader; +use crate::{download::Downloader, meshops::generate_tangents}; use anyhow::Result; use egui::{Grid, Widget}; +use glam::{Vec2, Vec3, Vec3A}; use humansize::DECIMAL; use image::ImageReader; -use log::debug; +use log::{debug, trace}; use std::{ collections::{HashMap, HashSet}, hash::Hash, @@ -85,10 +86,12 @@ pub struct ScenePreparer { texture_bgl: BindGroupLayout, textures: DemandMap<Resource<Image<'static>>, (Arc<Texture>, Arc<BindGroup>)>, - placeholder_textures: DemandMap<bool, (Arc<Texture>, Arc<BindGroup>)>, + placeholder_textures: DemandMap<TextureIdentityKind, (Arc<Texture>, Arc<BindGroup>)>, index_buffers: DemandMap<Resource<Vec<[u32; 3]>>, (Arc<Buffer>, u32)>, - vertex_buffers: DemandMap<Resource<Vec<f32>>, (Arc<Buffer>, u32)>, - placeholder_vertex_buffers: DemandMap<(u32, bool), Arc<Buffer>>, + vertex_buffers: DemandMap<Resource<Vec<f32>>, Arc<Buffer>>, + generated_tangent_buffers: DemandMap<TangentBufferSpec, Arc<Buffer>>, + generated_normal_buffers: DemandMap<NormalBufferSpec, Arc<Buffer>>, + generated_texcoord_buffers: DemandMap<TexcoordBufferSpec, Arc<Buffer>>, mesh_parts: DemandMap<Resource<MeshPart>, Arc<RMeshPart>>, pub prefabs: DemandMap<Resource<Prefab>, Arc<RPrefab>>, } @@ -99,12 +102,37 @@ pub struct RMeshPart { pub index: Arc<Buffer>, pub va_position: Arc<Buffer>, pub va_normal: Arc<Buffer>, + pub va_tangent: Arc<Buffer>, pub va_texcoord: Arc<Buffer>, pub tex_albedo: Arc<BindGroup>, pub tex_normal: Arc<BindGroup>, pub double_sided: bool, } +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +struct TangentBufferSpec { + index: Resource<Vec<[u32; 3]>>, + position: Resource<Vec<Vec3>>, + texcoord: Resource<Vec<Vec2>>, +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +struct NormalBufferSpec { + index: Resource<Vec<[u32; 3]>>, + position: Resource<Vec<Vec3A>>, +} +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +struct TexcoordBufferSpec { + index: Resource<Vec<[u32; 3]>>, + position: Resource<Vec<Vec3A>>, +} + +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +enum TextureIdentityKind { + Normal, + Multiply, +} + impl ScenePreparer { pub fn new(device: Arc<Device>, queue: Arc<Queue>, texture_bgl: BindGroupLayout) -> Self { Self { @@ -114,8 +142,10 @@ impl ScenePreparer { mesh_parts: DemandMap::new(), prefabs: DemandMap::new(), textures: DemandMap::new(), - placeholder_vertex_buffers: DemandMap::new(), placeholder_textures: DemandMap::new(), + generated_tangent_buffers: DemandMap::new(), + generated_normal_buffers: DemandMap::new(), + generated_texcoord_buffers: DemandMap::new(), device, queue, } @@ -140,19 +170,14 @@ impl ScenePreparer { for pres in self.index_buffers.needed() { let start = Instant::now(); if let Some(buf) = dls.try_get(pres.clone())? { - let buf = buf - .into_iter() - .flatten() - .flat_map(u32::to_le_bytes) - .collect::<Vec<_>>(); let buffer = self.device.create_buffer_init(&BufferInitDescriptor { - contents: &buf, + contents: bytemuck::cast_slice(buf.as_slice()), label: None, usage: BufferUsages::INDEX | BufferUsages::COPY_DST, }); self.index_buffers.insert( pres.clone(), - (Arc::new(buffer), (buf.len() / size_of::<u32>()) as u32), + (Arc::new(buffer), (buf.len() * 3) as u32), buf.len(), ); debug!( @@ -166,20 +191,13 @@ impl ScenePreparer { for pres in self.vertex_buffers.needed() { let start = Instant::now(); if let Some(buf) = dls.try_get(pres.clone())? { - let buf = buf - .into_iter() - .flat_map(f32::to_le_bytes) - .collect::<Vec<_>>(); let buffer = self.device.create_buffer_init(&BufferInitDescriptor { - contents: &buf, + contents: bytemuck::cast_slice(buf.as_slice()), label: None, usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, }); - self.vertex_buffers.insert( - pres.clone(), - (Arc::new(buffer), (buf.len() / size_of::<f32>()) as u32), - buf.len(), - ); + self.vertex_buffers + .insert(pres.clone(), Arc::new(buffer), buf.len()); debug!( "vertex attribute buffer created (len={}, took {:?}) {pres}", buf.len() / size_of::<f32>(), @@ -214,47 +232,62 @@ impl ScenePreparer { num_done += 1; } } - for variant in self.placeholder_textures.needed() { - let v = if variant { 255 } else { 0 }; - let tex_bg = create_texture( - &self.device, - &self.queue, - &self.texture_bgl, - &[v, v, v, 255], - 1, - 1, - ); - self.placeholder_textures.insert(variant, tex_bg, 4); + for kind in self.placeholder_textures.needed() { + let color = match kind { + TextureIdentityKind::Normal => [128, 128, 255, 255], + TextureIdentityKind::Multiply => [255, 255, 255, 255], + }; + let tex_bg = create_texture(&self.device, &self.queue, &self.texture_bgl, &color, 1, 1); + self.placeholder_textures.insert(kind, tex_bg, 4); num_done += 1; } + for spec in self.generated_tangent_buffers.needed() { + if let (Some(index), Some(position), Some(texcoord)) = ( + dls.try_get(spec.index.clone())?, + dls.try_get(spec.position.clone())?, + dls.try_get(spec.texcoord.clone())?, + ) { + let tangents = generate_tangents(&index, &position, &texcoord); + let buffer = self.device.create_buffer_init(&BufferInitDescriptor { + label: None, + usage: BufferUsages::COPY_DST | BufferUsages::VERTEX, + contents: bytemuck::cast_slice(tangents.as_slice()), + }); + self.generated_tangent_buffers.insert( + spec, + Arc::new(buffer), + size_of::<f32>() * tangents.len() * 3, + ); + } + } for pres in self.mesh_parts.needed() { let start = Instant::now(); if let Some(part) = dls.try_get(pres.clone())? { if let (Some(indexres), Some(positionres)) = (part.index, part.va_position) { - let index = self.index_buffers.try_get(indexres); + let index = self.index_buffers.try_get(indexres.clone()); let position = self .vertex_buffers .try_get(Resource(positionres.0, PhantomData)); - let vertex_count = position.as_ref().map(|(_, c)| *c / 3); - let normal = if let Some(res) = part.va_normal { - self.vertex_buffers - .try_get(Resource(res.0, PhantomData)) - .map(|e| e.0) + let normal = if let Some(res) = part.va_normal.clone() { + self.vertex_buffers.try_get(Resource(res.0, PhantomData)) } else { - vertex_count - .map(|vc| self.placeholder_vertex_buffers.try_get((vc * 4, false))) - .flatten() + todo!() }; - let texcoord = if let Some(res) = part.va_texcoord { - self.vertex_buffers - .try_get(Resource(res.0, PhantomData)) - .map(|e| e.0) + let texcoord = if let Some(res) = part.va_texcoord.clone() { + self.vertex_buffers.try_get(Resource(res.0, PhantomData)) } else { - vertex_count - .map(|vc| self.placeholder_vertex_buffers.try_get((vc * 2, false))) - .flatten() + todo!() + }; + let tangent = if let Some(res) = part.va_tangent.clone() { + self.vertex_buffers.try_get(Resource(res.0, PhantomData)) + } else { + self.generated_tangent_buffers.try_get(TangentBufferSpec { + index: indexres, + position: Resource(positionres.0, PhantomData), + texcoord: part.va_texcoord.expect("TODO"), + }) }; let mut tex_albedo = None; @@ -263,7 +296,10 @@ impl ScenePreparer { tex_albedo = Some(bg) } } else { - if let Some((_tex, bg)) = self.placeholder_textures.try_get(true) { + if let Some((_tex, bg)) = self + .placeholder_textures + .try_get(TextureIdentityKind::Multiply) + { tex_albedo = Some(bg) } } @@ -273,20 +309,25 @@ impl ScenePreparer { tex_normal = Some(bg) } } else { - if let Some((_tex, bg)) = self.placeholder_textures.try_get(false) { + if let Some((_tex, bg)) = self + .placeholder_textures + .try_get(TextureIdentityKind::Normal) + { tex_normal = Some(bg) } } if let ( - Some(va_normal), Some((index, index_count)), + Some(va_normal), + Some(va_tangent), Some(va_texcoord), - Some((va_position, _)), + Some(va_position), Some(tex_normal), Some(tex_albedo), - ) = (normal, index, texcoord, position, tex_normal, tex_albedo) - { + ) = ( + index, normal, tangent, texcoord, position, tex_normal, tex_albedo, + ) { debug!("part created (took {:?}) {pres}", start.elapsed()); self.mesh_parts.insert( pres, @@ -294,6 +335,7 @@ impl ScenePreparer { index_count, index, va_normal, + va_tangent, va_position, va_texcoord, tex_albedo, @@ -307,6 +349,7 @@ impl ScenePreparer { } } } + self.print_missing(); Ok(num_done) } } @@ -373,6 +416,34 @@ impl<K, V> Widget for &DemandMap<K, V> { ui.response() } } +impl ScenePreparer { + pub fn print_missing(&self) { + fn visit<K, V>(name: &str, m: &DemandMap<K, V>) + where + K: Clone, + K: Hash, + K: std::cmp::Eq, + V: Clone, + { + let nl = m.needed().len(); + if nl > 0 { + trace!("{name}: need {nl}") + } + } + visit("prefabs", &self.prefabs); + visit("mesh_parts", &self.mesh_parts); + visit("vertex_buffers", &self.vertex_buffers); + visit("index_buffers", &self.index_buffers); + visit("placeholder_textures", &self.placeholder_textures); + visit("generated_tangent_buffers", &self.generated_tangent_buffers); + visit("generated_normal_buffers", &self.generated_normal_buffers); + visit( + "generated_texcoord_buffers", + &self.generated_texcoord_buffers, + ); + visit("textures", &self.textures); + } +} impl Widget for &ScenePreparer { fn ui(self, ui: &mut egui::Ui) -> egui::Response { @@ -389,8 +460,12 @@ impl Widget for &ScenePreparer { self.index_buffers.ui(ui); ui.label("placeholder_textures"); self.placeholder_textures.ui(ui); - ui.label("placeholder_vertex_buffers"); - self.placeholder_vertex_buffers.ui(ui); + ui.label("generated_tangent_buffers"); + self.generated_tangent_buffers.ui(ui); + ui.label("generated_normal_buffers"); + self.generated_normal_buffers.ui(ui); + ui.label("generated_texcoord_buffers"); + self.generated_texcoord_buffers.ui(ui); ui.label("textures"); self.textures.ui(ui); }) |