Skip to content

Commit

Permalink
WIP GLTF is the only internal representation
Browse files Browse the repository at this point in the history
  • Loading branch information
schell committed Dec 20, 2023
1 parent 5566425 commit 0663cd9
Show file tree
Hide file tree
Showing 15 changed files with 344 additions and 332 deletions.
5 changes: 5 additions & 0 deletions DEVLOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# devlog

## Wed Dec 20, 2023

I think I'm going to keep going with this idea of making GLTF the internal representation of the
renderer.

## Tue Dec 19, 2023

### Thoughts on GLTF
Expand Down
38 changes: 38 additions & 0 deletions crates/renderling-shader/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@ use core::marker::PhantomData;
use crate::id::Id;
use crate::slab::Slabbed;

#[derive(Clone, Copy)]
pub struct ArrayIter<T> {
array: Array<T>,
index: usize,
}

impl<T: Slabbed> Iterator for ArrayIter<T> {
type Item = Id<T>;

fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.array.len() {
None
} else {
let id = self.array.at(self.index);
self.index += 1;
Some(id)
}
}
}

#[repr(C)]
pub struct Array<T> {
// u32 offset in the slab
Expand All @@ -25,6 +45,17 @@ impl<T> Clone for Array<T> {

impl<T> Copy for Array<T> {}

/// An `Id<T>` is an `Array<T>` with a length of 1.
impl<T> From<Id<T>> for Array<T> {
fn from(id: Id<T>) -> Self {
Self {
index: id.inner(),
len: 1,
_phantom: PhantomData,
}
}
}

impl<T> core::fmt::Debug for Array<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if self.is_null() {
Expand Down Expand Up @@ -122,6 +153,13 @@ impl<T> Array<T> {
self.index as usize
}

pub fn iter(&self) -> ArrayIter<T> {
ArrayIter {
array: *self,
index: 0,
}
}

/// Convert this array into a `u32` array.
pub fn into_u32_array(self) -> Array<u32>
where
Expand Down
2 changes: 1 addition & 1 deletion crates/renderling-shader/src/gltf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ pub struct GltfAccessor {
//
/// This may be Id::NONE if the corresponding accessor is sparse.
pub view: Id<GltfBufferView>,
// The offset relative to the start of the parent buffer view in bytes.
// 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,
Expand Down
139 changes: 39 additions & 100 deletions crates/renderling-shader/src/stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1010,18 +1010,6 @@ impl Default for StageLegend {
}
}

#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
#[repr(C)]
#[derive(Default, Clone, Copy, PartialEq, Slabbed)]
pub struct NativeVertexData {
// Points to an array of `Vertex` in the stage's slab.
pub vertices: Array<Vertex>,
// Points to an array of `Indices` in the stage's slab.
pub indices: Array<u32>,
// Points to a `PbrMaterial` in the stage's slab.
pub material: Id<PbrMaterial>,
}

#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
#[repr(C)]
#[derive(Default, Clone, Copy, PartialEq, Slabbed)]
Expand All @@ -1034,53 +1022,6 @@ pub struct GltfVertexData {
pub primitive_index: u32,
}

#[repr(C)]
#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
#[derive(Clone, Copy, PartialEq, Slabbed)]
pub struct VertexData {
// The hash of the vertex data. This is used to determine how to read
// the vertex data from the slab.
pub hash: u32,
// The first index of the vertex data in the slab.
pub index: u32,
}

impl Default for VertexData {
fn default() -> Self {
VertexData {
hash: 0,
index: u32::MAX,
}
}
}

impl VertexData {
pub const NATIVE: u32 = 0;
pub const GLTF: u32 = 1;

pub fn new_native(id: Id<NativeVertexData>) -> Self {
Self {
hash: Self::NATIVE,
index: id.into(),
}
}

pub fn new_gltf(id: Id<GltfVertexData>) -> Self {
Self {
hash: Self::GLTF,
index: id.into(),
}
}

pub fn is_native(&self) -> bool {
self.hash == Self::NATIVE
}

pub fn is_gltf(&self) -> bool {
self.hash == Self::GLTF
}
}

#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
#[repr(C)]
#[derive(Clone, Copy, PartialEq, Slabbed)]
Expand All @@ -1100,18 +1041,27 @@ impl Default for Transform {
}
}

/// A fully-computed unit of rendering, roughly meaning a mesh with model matrix
/// transformations.
/// A rendering "command" that draws a single mesh from a top-level node.
#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
#[repr(C)]
#[derive(Default, Clone, Copy, PartialEq, Slabbed)]
pub struct RenderUnit {
pub vertex_data: VertexData,
// Which node are we rendering, and what is the path through its
// ancestors to get to it.
pub node_path: Array<Id<GltfNode>>,
// Index of the mesh within the child node that we're rendering.
pub mesh_index: u32,
// Index of the primitive within the mesh that we're rendering.
pub primitive_index: u32,
// Points to a `Camera` in the stage's slab.
pub camera: Id<Camera>,
// Points to a `Transform` in the stage's slab.
// Points to a top-level `Transform` in the stage's slab.
//
// This is used to transform your GLTF models.
pub transform: Id<Transform>,
// Number of vertices to draw for this unit.
//
// This is a cache for convenience on CPU.
pub vertex_count: u32,
}

Expand All @@ -1121,45 +1071,34 @@ impl RenderUnit {
vertex_index: u32,
slab: &[u32],
) -> (Vertex, Transform, Id<PbrMaterial>) {
let transform = slab.read(self.transform);
match self.vertex_data.hash {
VertexData::NATIVE => {
let id = Id::<NativeVertexData>::from(self.vertex_data.index);
let NativeVertexData {
vertices,
indices,
material,
} = slab.read(id);
let index = if indices.is_empty() {
vertex_index
} else {
slab.read(indices.at(vertex_index as usize))
};
let vertex = slab.read(vertices.at(index as usize));
(vertex, transform, material)
}
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,
primitive_index,
} = slab.read(id);
// TODO: check nodes for skinning
let mesh = slab.read(mesh);
let primitive = slab.read(mesh.primitives.at(primitive_index as usize));
let material = primitive.material;
let vertex = primitive.get_vertex(vertex_index as usize, slab);
(vertex, transform, material)
}
_ => Default::default(),
let t = slab.read(self.transform);
let mut model = Mat4::from_scale_rotation_translation(t.scale, t.rotation, t.translation);
let mut node = GltfNode::default();
for id_id in self.node_path.iter() {
let node_id = slab.read(id_id);
node = slab.read(node_id);
let node_transform =
Mat4::from_scale_rotation_translation(node.scale, node.rotation, node.translation);
model = model * node_transform;
}
// TODO: check nodes for skinning
let mesh = slab.read(node.mesh);
let primitive_id = mesh.primitives.at(self.primitive_index as usize);
let primitive = slab.read(primitive_id);
let material = primitive.material;
let vertex = primitive.get_vertex(vertex_index as usize, slab);
let (s, r, t) = model.to_scale_rotation_translation_or_id();
let transform = Transform {
translation: t,
rotation: r,
scale: s,
};
(vertex, transform, material)
}
}

#[spirv(vertex)]
pub fn new_stage_vertex(
pub fn gltf_vertex(
// Which render unit are we rendering
#[spirv(instance_index)] instance_index: u32,
// Which vertex within the render unit are we rendering
Expand Down Expand Up @@ -1234,7 +1173,7 @@ pub fn get_material(material_index: u32, has_lighting: bool, slab: &[u32]) -> pb
#[allow(clippy::too_many_arguments)]
#[spirv(fragment)]
/// Scene fragment shader.
pub fn stage_fragment(
pub fn gltf_fragment(
#[spirv(descriptor_set = 1, binding = 0)] atlas: &Image2d,
#[spirv(descriptor_set = 1, binding = 1)] atlas_sampler: &Sampler,

Expand Down Expand Up @@ -1262,7 +1201,7 @@ pub fn stage_fragment(
output: &mut Vec4,
brigtness: &mut Vec4,
) {
stage_fragment_impl(
gltf_fragment_impl(
atlas,
atlas_sampler,
irradiance,
Expand All @@ -1288,7 +1227,7 @@ pub fn stage_fragment(

#[allow(clippy::too_many_arguments)]
/// Scene fragment shader.
pub fn stage_fragment_impl<T, C, S>(
pub fn gltf_fragment_impl<T, C, S>(
atlas: &T,
atlas_sampler: &S,
irradiance: &C,
Expand Down
60 changes: 3 additions & 57 deletions crates/renderling/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ mod state;
#[cfg(feature = "text")]
mod text;
mod texture;
mod tutorial;
//mod tutorial;
mod ui;
mod uniform;

Expand Down Expand Up @@ -254,14 +254,13 @@ fn init_logging() {
.try_init();
}

#[cfg(test)]
#[cfg(all(feature = "blah", test))]
mod test {
use super::*;
use glam::{Mat3, Mat4, Quat, UVec2, Vec2, Vec3, Vec4, Vec4Swizzles};
use pretty_assertions::assert_eq;
use renderling_shader::stage::{
light::*, new_stage_vertex, Camera, GpuEntity, NativeVertexData, RenderUnit, Transform,
Vertex, VertexData,
gltf_vertex, light::*, Camera, GpuEntity, RenderUnit, Transform, Vertex,
};

#[test]
Expand Down Expand Up @@ -610,59 +609,6 @@ mod test {
]
}

/// A helper struct that contains all outputs of the vertex shader.
#[allow(unused)]
#[derive(Clone, Debug, Default, PartialEq)]
pub struct VertexInvocation {
pub instance_index: u32,
pub vertex_index: u32,
pub render_unit_id: Id<RenderUnit>,
pub render_unit: RenderUnit,
pub out_camera: u32,
pub out_material: u32,
pub out_color: Vec4,
pub out_uv0: Vec2,
pub out_uv1: Vec2,
pub out_norm: Vec3,
pub out_tangent: Vec3,
pub out_bitangent: Vec3,
pub out_pos: Vec3,
// output clip coordinates
pub clip_pos: Vec4,
// output normalized device coordinates
pub ndc_pos: Vec3,
}

impl VertexInvocation {
#[allow(dead_code)]
pub fn invoke(instance_index: u32, vertex_index: u32, slab: &[u32]) -> Self {
let mut v = Self {
instance_index,
vertex_index,
..Default::default()
};
v.render_unit_id = Id::from(v.instance_index);
v.render_unit = slab.read(v.render_unit_id);
new_stage_vertex(
v.instance_index,
v.vertex_index,
slab,
&mut v.out_camera,
&mut v.out_material,
&mut v.out_color,
&mut v.out_uv0,
&mut v.out_uv1,
&mut v.out_norm,
&mut v.out_tangent,
&mut v.out_bitangent,
&mut v.out_pos,
&mut v.clip_pos,
);
v.ndc_pos = v.clip_pos.xyz() / v.clip_pos.w;
v
}
}

#[test]
// Tests that updating the material actually updates the rendering of an unlit mesh
fn unlit_textured_cube_material() {
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified crates/renderling/src/linkage/tutorial-slabbed_render_unit.spv
Binary file not shown.
Binary file modified crates/renderling/src/linkage/tutorial-slabbed_vertices.spv
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit 0663cd9

Please sign in to comment.