diff --git a/DEVLOG.md b/DEVLOG.md index 9e9fb7e5..a7f9013a 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -1,5 +1,31 @@ # devlog +## Mon Dec 18, 2023 + +### Simple Texture GLTF Example +* The `simple_texture` test is rendering the texture upside-down. +* There are _no rotation transformations_ in its node's hierarchy. +* What does the atlas look like? + - It's not the atlas, the two tests (slabbed and the previous non-slabbed) have + identical atlas images. +* So what about UV coords? + - Comparing runs of the vertex shaders shows that the UV coords' Y components are flipped. + - So, 0.0 is 1.0 and 1.0 is 0.0 +* So is there something doing this intentionally? + - Nothing that I can easily see in the `gltf_support` modules... + - It has something to do with the accessor. + - I can see in the GLTF file that the accessor's byte offset is 48, but somehow in + my code it comes out 12... + - It was because the accessor's offset was not being taken into account. + +### Analytical Directional Lights +I got analytical lighting working (at least for directional lights) on the stage. +The problem I was having was that the shaders use `Camera.position` in lighting +equations, but that was defaulting to `Vec3::ZERO`. Previously in the "scene" +version of the renderer (which I'm porting over to "stage") the camera's position +was set automatically when setting the projection and/or view. +I had to run both versions of the vertex AND fragement shaders to track this down. Ugh! + ## Fri Dec 8, 2023 I've been having trouble getting the new GLTF files on-the-slab method to pass my diff --git a/crates/example/src/gltf.rs b/crates/example/src/gltf.rs index 7577b990..1753b0cb 100644 --- a/crates/example/src/gltf.rs +++ b/crates/example/src/gltf.rs @@ -10,7 +10,7 @@ use instant::Instant; use renderling::{ debug::DebugChannel, math::{Mat4, Vec3, Vec4}, - GltfLoader, GpuEntity, RenderGraphConfig, Renderling, Scene, SceneImage, ScreenSize, + GltfLoader, GpuEntity, RenderGraphConfig, Renderling, Scene, SceneImage, ScreenSize, Stage, TweenProperty, UiDrawObjects, UiMode, UiVertex, ViewMut, }; use renderling_gpui::{Element, Gpui}; diff --git a/crates/renderling-shader/src/array.rs b/crates/renderling-shader/src/array.rs index 5ba08080..a69ec262 100644 --- a/crates/renderling-shader/src/array.rs +++ b/crates/renderling-shader/src/array.rs @@ -133,4 +133,14 @@ impl Array { _phantom: PhantomData, } } + + #[cfg(not(target_arch = "spirv"))] + /// Return the slice of the slab that this array represents. + pub fn sub_slab<'a>(&'a self, slab: &'a [u32]) -> &[u32] + where + T: Slabbed, + { + let arr = self.into_u32_array(); + &slab[arr.index as usize..(arr.index + arr.len) as usize] + } } diff --git a/crates/renderling-shader/src/gltf.rs b/crates/renderling-shader/src/gltf.rs index 9b21cf88..f2f15096 100644 --- a/crates/renderling-shader/src/gltf.rs +++ b/crates/renderling-shader/src/gltf.rs @@ -118,6 +118,10 @@ pub struct GltfAccessor { // // This will be 0 if the corresponding accessor is sparse. pub view_offset: u32, + // Returns the offset relative to the start of the parent buffer view in bytes. + // + // This will be 0 if the corresponding accessor is sparse. + pub offset: u32, // The stride in bytes between vertex attributes or other interleavable data. pub view_stride: u32, // The number of elements within the buffer view - not to be confused with the @@ -221,19 +225,21 @@ impl GltfAccessor { crate::println!("buffer_start: {buffer_start:?}"); let buffer_start_bytes = buffer_start * 4; crate::println!("buffer_start_bytes: {buffer_start_bytes:?}"); + let stride = if self.size > self.view_stride { + self.size + } else { + self.view_stride + } as usize; let byte_offset = buffer_start_bytes + self.view_offset as usize - + element_index as usize - * if self.size > self.view_stride { - self.size - } else { - self.view_stride - } as usize; - crate::println!("byte_offset: {byte_offset:?}"); + + self.offset as usize + + element_index as usize * stride; + crate::println!("byte_offset: buffer_start_bytes({buffer_start_bytes}) + view_offset({view_offset}) + accessor.offset({offset}) + element_index({element_index}) * stride({stride}) = {byte_offset:?}", view_offset = self.view_offset, offset = self.offset); let slab_index = byte_offset / 4; crate::println!("slab_index: {slab_index:?}"); - let byte_offset = byte_offset % 4; - (slab_index, byte_offset) + let relative_byte_offset = byte_offset % 4; + crate::println!("relative_byte_offset: {relative_byte_offset:?}"); + (slab_index, relative_byte_offset) } pub fn inc_u8(&self, index: usize, slab: &[u32]) -> IncU8 { @@ -376,9 +382,13 @@ impl GltfAccessor { y = crate::bits::extract_u32(slab_index + 1, 0, slab).0 as f32; } DataType::F32 => { + crate::println!("get_vec2 f32: vertex_index={vertex_index}"); let (slab_index, _) = self.slab_index_and_byte_offset(vertex_index, slab); + crate::println!(" slab_index: {slab_index:?}"); x = crate::bits::extract_f32(slab_index, 0, slab).0; y = crate::bits::extract_f32(slab_index + 1, 0, slab).0; + crate::println!(" x: {x:?}"); + crate::println!(" y: {y:?}"); } } match self.dimensions { @@ -616,10 +626,12 @@ pub struct GltfPrimitive { impl GltfPrimitive { pub fn get_vertex(&self, vertex_index: usize, slab: &[u32]) -> crate::stage::Vertex { let index = if self.indices.is_some() { + crate::println!("has indices"); let indices = slab.read(self.indices); let index = indices.get_u32(vertex_index, slab); index as usize } else { + crate::println!("no indices"); vertex_index }; crate::println!("index: {index:?}"); @@ -673,6 +685,7 @@ impl GltfPrimitive { crate::println!("color: {color:?}"); let tex_coords0 = if self.tex_coords0.is_none() { + crate::println!("tex_coords0 are none"); Vec2::ZERO } else { let tex_coords0 = slab.read(self.tex_coords0); @@ -1084,6 +1097,7 @@ mod test { size: 2, buffer: buffer_id, view_offset: 0, + offset: 0, view_stride: 0, count: 3, data_type: DataType::U16, diff --git a/crates/renderling-shader/src/stage.rs b/crates/renderling-shader/src/stage.rs index b20663e6..6dc52d80 100644 --- a/crates/renderling-shader/src/stage.rs +++ b/crates/renderling-shader/src/stage.rs @@ -1140,6 +1140,7 @@ impl RenderUnit { } VertexData::GLTF => { let id = Id::::from(self.vertex_data.index); + // TODO: Take the GLTF parent node's transform into account let GltfVertexData { parent_node_path: _, mesh, diff --git a/crates/renderling/src/atlas.rs b/crates/renderling/src/atlas.rs index d0424a2f..8d4365d4 100644 --- a/crates/renderling/src/atlas.rs +++ b/crates/renderling/src/atlas.rs @@ -493,10 +493,13 @@ impl Atlas { queue.submit(std::iter::once(encoder.finish())); Ok(atlas) } -} -#[cfg(test)] -impl Atlas { + /// Read the atlas image from the GPU. + /// + /// This is primarily for testing. + /// + /// ## Panics + /// Panics if the pixels read from the GPU cannot be converted into an `RgbaImage`. pub fn atlas_img(&self, device: &wgpu::Device, queue: &wgpu::Queue) -> RgbaImage { let buffer = crate::Texture::read( &self.texture.texture, diff --git a/crates/renderling/src/linkage/stage-new_stage_vertex.spv b/crates/renderling/src/linkage/stage-new_stage_vertex.spv index 07ba77d7..ba11616f 100644 Binary files a/crates/renderling/src/linkage/stage-new_stage_vertex.spv and b/crates/renderling/src/linkage/stage-new_stage_vertex.spv differ diff --git a/crates/renderling/src/linkage/tutorial-slabbed_render_unit.spv b/crates/renderling/src/linkage/tutorial-slabbed_render_unit.spv index d421c200..e9238444 100644 Binary files a/crates/renderling/src/linkage/tutorial-slabbed_render_unit.spv and b/crates/renderling/src/linkage/tutorial-slabbed_render_unit.spv differ diff --git a/crates/renderling/src/slab.rs b/crates/renderling/src/slab.rs index 5aaba772..fa7f113a 100644 --- a/crates/renderling/src/slab.rs +++ b/crates/renderling/src/slab.rs @@ -52,6 +52,12 @@ pub enum SlabError { Async { source: wgpu::BufferAsyncError }, } +pub fn print_slab(slab: &[u32], starting_index: usize) { + for (u, i) in slab.iter().zip(starting_index..) { + println!("{i:02}: {u:032b} {u:010} {:?}", f32::from_bits(*u)); + } +} + /// A slab buffer used by the stage to store heterogeneous objects. /// /// A clone of a buffer is a reference to the same buffer. diff --git a/crates/renderling/src/stage.rs b/crates/renderling/src/stage.rs index ee0ddf40..c699245a 100644 --- a/crates/renderling/src/stage.rs +++ b/crates/renderling/src/stage.rs @@ -229,14 +229,6 @@ impl Stage { self } - /// Read all the data from the stage. - /// - /// This blocks until the GPU buffer is mappable, and then copies the data into a vector. - pub fn read_all_raw(&self) -> Result, SlabError> { - self.slab - .block_on_read_raw(&self.device, &self.queue, 0, self.slab.len()) - } - fn buffers_bindgroup_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { let visibility = wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT | wgpu::ShaderStages::COMPUTE; @@ -692,6 +684,30 @@ impl Stage { )); } } + + /// Read the atlas image from the GPU. + /// + /// This is primarily used for debugging. + /// + /// ## Panics + /// Panics if the pixels read from the GPU cannot be converted into an `RgbaImage`. + pub fn read_atlas_image(&self) -> image::RgbaImage { + // UNWRAP: if we can't acquire the lock we want to panic. + self.atlas + .read() + .unwrap() + .atlas_img(&self.device, &self.queue) + } + + /// Read all the data from the stage. + /// + /// This blocks until the GPU buffer is mappable, and then copies the data into a vector. + /// + /// This is primarily used for debugging. + pub fn read_slab(&self) -> Result, SlabError> { + self.slab + .block_on_read_raw(&self.device, &self.queue, 0, self.slab.len()) + } } /// A unit of work to be drawn. diff --git a/crates/renderling/src/stage/gltf_support.rs b/crates/renderling/src/stage/gltf_support.rs index 19976fbf..b76fb6a9 100644 --- a/crates/renderling/src/stage/gltf_support.rs +++ b/crates/renderling/src/stage/gltf_support.rs @@ -84,9 +84,9 @@ pub fn get_vertex_count(primitive: &gltf::Primitive<'_>) -> u32 { pub fn make_accessor(accessor: gltf::Accessor<'_>, buffers: &Array) -> GltfAccessor { let size = accessor.size() as u32; let buffer_view = accessor.view().unwrap(); - let view_buffer = buffer_view.buffer(); - let buffer_index = view_buffer.index(); + let buffer_index = buffer_view.buffer().index(); let buffer = buffers.at(buffer_index); + let offset = accessor.offset() as u32; let count = accessor.count() as u32; let view_offset = buffer_view.offset() as u32; let view_stride = buffer_view.stride().unwrap_or(0) as u32; @@ -113,6 +113,7 @@ pub fn make_accessor(accessor: gltf::Accessor<'_>, buffers: &Array) count, buffer, view_offset, + offset, view_stride, data_type: component_type, dimensions, @@ -164,7 +165,12 @@ impl Stage { log::trace!("Loading accessors into the GPU"); let accessors = document .accessors() - .map(|accessor| make_accessor(accessor, &buffers)) + .enumerate() + .map(|(i, accessor)| { + let a = make_accessor(accessor, &buffers); + log::trace!(" accessor {i}: {a:#?}",); + a + }) .collect::>(); let accessors = self.append_array(&accessors); @@ -600,6 +606,7 @@ impl Stage { size: 12, buffer: buffer_id, view_offset: 0, + offset: 0, view_stride: 12, count: normals.len() as u32, data_type: DataType::F32, @@ -651,6 +658,7 @@ impl Stage { size: 16, buffer: buffer_id, view_offset: 0, + offset: 0, view_stride: 16, count: tangents.len() as u32, data_type: DataType::F32, @@ -991,8 +999,8 @@ impl Stage { }) } - // For now we have to keep the original document around to figure out - // what to draw. + /// Draw the given `gltf::Node` with the given `Camera`. + /// `parents` is a list of the parent nodes of the given node. fn draw_gltf_node_with<'a>( &self, gpu_doc: &GltfDocument, @@ -1012,11 +1020,12 @@ impl Stage { primitive_index: primitive.index() as u32, }); let (t, r, s) = node.transform().decomposed(); - let transform = self.append(&Transform { + let transform = Transform { translation: Vec3::from(t), rotation: Quat::from_array(r), scale: Vec3::from(s), - }); + }; + let transform = self.append(&transform); let render_unit = RenderUnit { vertex_data: VertexData::new_gltf(vertex_data_id), vertex_count: super::get_vertex_count(&primitive), @@ -1128,6 +1137,7 @@ mod test { count: 3, buffer: Id::from(buffer_index), view_offset: 0, + offset: 0, view_stride: 0, data_type: DataType::U16, dimensions: Dimensions::Scalar, @@ -1388,23 +1398,23 @@ mod test { img_diff::assert_img_eq("gltf_simple_texture.png", img); } - #[test] - fn normal_mapping_brick_sphere() { - let size = 600; - let mut r = - Renderling::headless(size, size).with_background_color(Vec3::splat(1.0).extend(1.0)); - let stage = r.new_stage().with_lighting(true).with_bloom(true); - stage.configure_graph(&mut r, true); - let (cpu_doc, gpu_doc) = stage - .load_gltf_document_from_path("../../gltf/red_brick_03_1k.glb") - .unwrap(); - let camera = stage.create_camera_from_gltf(&cpu_doc, 0).unwrap(); - let camera_id = stage.append(&camera); - let _unit_ids = - stage.draw_gltf_scene(&gpu_doc, camera_id, cpu_doc.default_scene().unwrap()); - - let img = r.render_image().unwrap(); - println!("saving frame"); - img_diff::assert_img_eq("gltf_normal_mapping_brick_sphere.png", img); - } + //#[test] + //fn normal_mapping_brick_sphere() { + // let size = 600; + // let mut r = + // Renderling::headless(size, size).with_background_color(Vec3::splat(1.0).extend(1.0)); + // let stage = r.new_stage().with_lighting(true).with_bloom(true); + // stage.configure_graph(&mut r, true); + // let (cpu_doc, gpu_doc) = stage + // .load_gltf_document_from_path("../../gltf/red_brick_03_1k.glb") + // .unwrap(); + // let camera = stage.create_camera_from_gltf(&cpu_doc, 0).unwrap(); + // let camera_id = stage.append(&camera); + // let _unit_ids = + // stage.draw_gltf_scene(&gpu_doc, camera_id, cpu_doc.default_scene().unwrap()); + + // let img = r.render_image().unwrap(); + // println!("saving frame"); + // img_diff::assert_img_eq("gltf_normal_mapping_brick_sphere.png", img); + //} }