From 5ef0fc14d1d12cc5e7cc6a1fb896953d6d668891 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Sun, 19 Jan 2025 20:36:21 +0100 Subject: client: send material data to shader --- client/src/scene_prepare.rs | 71 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 4 deletions(-) (limited to 'client/src/scene_prepare.rs') diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs index 97ab166..0e65e72 100644 --- a/client/src/scene_prepare.rs +++ b/client/src/scene_prepare.rs @@ -19,8 +19,9 @@ use crate::{ meshops::{generate_normals, generate_tangents, generate_texcoords}, }; use anyhow::Result; +use bytemuck::{Pod, Zeroable}; use egui::{Grid, Widget}; -use glam::{Vec2, Vec3}; +use glam::{UVec3, UVec4, Vec2, Vec3, Vec3A, uvec3, uvec4}; use humansize::DECIMAL; use image::ImageReader; use log::{debug, trace}; @@ -87,6 +88,7 @@ pub struct ScenePreparer { device: Arc, queue: Arc, texture_bgl: BindGroupLayout, + material_bgl: BindGroupLayout, textures: DemandMap<(Resource>, bool), (Arc, Arc)>, placeholder_textures: DemandMap, Arc)>, @@ -96,6 +98,7 @@ pub struct ScenePreparer { generated_normal_buffers: DemandMap>, generated_texcoord_buffers: DemandMap>, mesh_parts: DemandMap, Arc>, + materials: DemandMap>, pub prefabs: DemandMap, Arc>, } @@ -109,6 +112,7 @@ pub struct RMeshPart { pub va_texcoord: Arc, pub tex_albedo: Arc, pub tex_normal: Arc, + pub material: Arc, pub double_sided: bool, } @@ -136,10 +140,29 @@ enum TextureIdentityKind { Multiply, } +#[derive(Debug, Clone, Copy, Pod, Zeroable, Hash, PartialEq, Eq)] +#[repr(C)] +struct Material { + roughness: u32, + metallic: u32, + _pad1: [u32; 2], + albedo_alpha: UVec4, + emission: UVec3, + _pad2: u32, +} + impl ScenePreparer { - pub fn new(device: Arc, queue: Arc, texture_bgl: BindGroupLayout) -> Self { + pub fn new( + device: Arc, + queue: Arc, + texture_bgl: BindGroupLayout, + material_bgl: BindGroupLayout, + ) -> Self { Self { + device, + queue, texture_bgl, + material_bgl, index_buffers: DemandMap::new(), vertex_buffers: DemandMap::new(), mesh_parts: DemandMap::new(), @@ -149,8 +172,7 @@ impl ScenePreparer { generated_tangent_buffers: DemandMap::new(), generated_normal_buffers: DemandMap::new(), generated_texcoord_buffers: DemandMap::new(), - device, - queue, + materials: DemandMap::new(), } } pub fn update(&self, dls: &Downloader) -> Result { @@ -312,6 +334,22 @@ impl ScenePreparer { ); } } + for spec in self.materials.needed() { + let buffer = self.device.create_buffer_init(&BufferInitDescriptor { + label: Some("material props"), + usage: BufferUsages::COPY_DST | BufferUsages::UNIFORM, + contents: bytemuck::cast_slice(&[spec]), + }); + let bind_group = self.device.create_bind_group(&BindGroupDescriptor { + label: Some("material"), + layout: &self.material_bgl, + entries: &[BindGroupEntry { + binding: 0, + resource: buffer.as_entire_binding(), + }], + }); + self.materials.insert(spec, Arc::new(bind_group), 0); + } for pres in self.mesh_parts.needed() { let start = Instant::now(); if let Some(part) = dls.try_get(pres.clone())? { @@ -375,6 +413,28 @@ impl ScenePreparer { } } + let material = self.materials.try_get({ + let albedo = part.g_albedo.unwrap_or(Vec3A::ONE); + let emission = part.g_emission.unwrap_or(Vec3A::ONE); + Material { + roughness: part.g_roughness.unwrap_or(1.).to_bits(), + metallic: part.g_metallic.unwrap_or(0.).to_bits(), + _pad1: [0, 0], + albedo_alpha: uvec4( + albedo.x.to_bits(), + albedo.y.to_bits(), + albedo.z.to_bits(), + part.g_alpha.unwrap_or(1.).to_bits(), + ), + emission: uvec3( + emission.x.to_bits(), + emission.y.to_bits(), + emission.z.to_bits(), + ), + _pad2: 0, + } + }); + if let ( Some((index, index_count)), Some(va_normal), @@ -383,8 +443,10 @@ impl ScenePreparer { Some(va_position), Some(tex_normal), Some(tex_albedo), + Some(material), ) = ( index, normal, tangent, texcoord, position, tex_normal, tex_albedo, + material, ) { debug!("part created (took {:?}) {pres}", start.elapsed()); self.mesh_parts.insert( @@ -398,6 +460,7 @@ impl ScenePreparer { va_texcoord, tex_albedo, tex_normal, + material, double_sided: part.g_double_sided.is_some(), }), 0, -- cgit v1.2.3-70-g09d2