Skip to content

Commit

Permalink
fixed accessors, they now take their own offset into account
Browse files Browse the repository at this point in the history
  • Loading branch information
schell committed Dec 18, 2023
1 parent 2293435 commit 9182647
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 47 deletions.
26 changes: 26 additions & 0 deletions DEVLOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion crates/example/src/gltf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
10 changes: 10 additions & 0 deletions crates/renderling-shader/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,14 @@ impl<T> Array<T> {
_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]
}
}
32 changes: 23 additions & 9 deletions crates/renderling-shader/src/gltf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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:?}");
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions crates/renderling-shader/src/stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,7 @@ impl RenderUnit {
}
VertexData::GLTF => {
let id = Id::<GltfVertexData>::from(self.vertex_data.index);
// TODO: Take the GLTF parent node's transform into account
let GltfVertexData {
parent_node_path: _,
mesh,
Expand Down
9 changes: 6 additions & 3 deletions crates/renderling/src/atlas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Binary file modified crates/renderling/src/linkage/stage-new_stage_vertex.spv
Binary file not shown.
Binary file modified crates/renderling/src/linkage/tutorial-slabbed_render_unit.spv
Binary file not shown.
6 changes: 6 additions & 0 deletions crates/renderling/src/slab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
32 changes: 24 additions & 8 deletions crates/renderling/src/stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Vec<u32>, 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;
Expand Down Expand Up @@ -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<Vec<u32>, SlabError> {
self.slab
.block_on_read_raw(&self.device, &self.queue, 0, self.slab.len())
}
}

/// A unit of work to be drawn.
Expand Down
62 changes: 36 additions & 26 deletions crates/renderling/src/stage/gltf_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ pub fn get_vertex_count(primitive: &gltf::Primitive<'_>) -> u32 {
pub fn make_accessor(accessor: gltf::Accessor<'_>, buffers: &Array<GltfBuffer>) -> 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;
Expand All @@ -113,6 +113,7 @@ pub fn make_accessor(accessor: gltf::Accessor<'_>, buffers: &Array<GltfBuffer>)
count,
buffer,
view_offset,
offset,
view_stride,
data_type: component_type,
dimensions,
Expand Down Expand Up @@ -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::<Vec<_>>();
let accessors = self.append_array(&accessors);

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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),
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
//}
}

0 comments on commit 9182647

Please sign in to comment.