Skip to content

Commit 0663cd9

Browse files
committed
WIP GLTF is the only internal representation
1 parent 5566425 commit 0663cd9

15 files changed

+344
-332
lines changed

DEVLOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# devlog
22

3+
## Wed Dec 20, 2023
4+
5+
I think I'm going to keep going with this idea of making GLTF the internal representation of the
6+
renderer.
7+
38
## Tue Dec 19, 2023
49

510
### Thoughts on GLTF

crates/renderling-shader/src/array.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,26 @@ use core::marker::PhantomData;
44
use crate::id::Id;
55
use crate::slab::Slabbed;
66

7+
#[derive(Clone, Copy)]
8+
pub struct ArrayIter<T> {
9+
array: Array<T>,
10+
index: usize,
11+
}
12+
13+
impl<T: Slabbed> Iterator for ArrayIter<T> {
14+
type Item = Id<T>;
15+
16+
fn next(&mut self) -> Option<Self::Item> {
17+
if self.index >= self.array.len() {
18+
None
19+
} else {
20+
let id = self.array.at(self.index);
21+
self.index += 1;
22+
Some(id)
23+
}
24+
}
25+
}
26+
727
#[repr(C)]
828
pub struct Array<T> {
929
// u32 offset in the slab
@@ -25,6 +45,17 @@ impl<T> Clone for Array<T> {
2545

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

48+
/// An `Id<T>` is an `Array<T>` with a length of 1.
49+
impl<T> From<Id<T>> for Array<T> {
50+
fn from(id: Id<T>) -> Self {
51+
Self {
52+
index: id.inner(),
53+
len: 1,
54+
_phantom: PhantomData,
55+
}
56+
}
57+
}
58+
2859
impl<T> core::fmt::Debug for Array<T> {
2960
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3061
if self.is_null() {
@@ -122,6 +153,13 @@ impl<T> Array<T> {
122153
self.index as usize
123154
}
124155

156+
pub fn iter(&self) -> ArrayIter<T> {
157+
ArrayIter {
158+
array: *self,
159+
index: 0,
160+
}
161+
}
162+
125163
/// Convert this array into a `u32` array.
126164
pub fn into_u32_array(self) -> Array<u32>
127165
where

crates/renderling-shader/src/gltf.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ pub struct GltfAccessor {
132132
//
133133
/// This may be Id::NONE if the corresponding accessor is sparse.
134134
pub view: Id<GltfBufferView>,
135-
// The offset relative to the start of the parent buffer view in bytes.
135+
// The offset relative to the start of the parent **buffer view** in bytes.
136136
//
137137
// This will be 0 if the corresponding accessor is sparse.
138138
pub offset: u32,

crates/renderling-shader/src/stage.rs

Lines changed: 39 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,18 +1010,6 @@ impl Default for StageLegend {
10101010
}
10111011
}
10121012

1013-
#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
1014-
#[repr(C)]
1015-
#[derive(Default, Clone, Copy, PartialEq, Slabbed)]
1016-
pub struct NativeVertexData {
1017-
// Points to an array of `Vertex` in the stage's slab.
1018-
pub vertices: Array<Vertex>,
1019-
// Points to an array of `Indices` in the stage's slab.
1020-
pub indices: Array<u32>,
1021-
// Points to a `PbrMaterial` in the stage's slab.
1022-
pub material: Id<PbrMaterial>,
1023-
}
1024-
10251013
#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
10261014
#[repr(C)]
10271015
#[derive(Default, Clone, Copy, PartialEq, Slabbed)]
@@ -1034,53 +1022,6 @@ pub struct GltfVertexData {
10341022
pub primitive_index: u32,
10351023
}
10361024

1037-
#[repr(C)]
1038-
#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
1039-
#[derive(Clone, Copy, PartialEq, Slabbed)]
1040-
pub struct VertexData {
1041-
// The hash of the vertex data. This is used to determine how to read
1042-
// the vertex data from the slab.
1043-
pub hash: u32,
1044-
// The first index of the vertex data in the slab.
1045-
pub index: u32,
1046-
}
1047-
1048-
impl Default for VertexData {
1049-
fn default() -> Self {
1050-
VertexData {
1051-
hash: 0,
1052-
index: u32::MAX,
1053-
}
1054-
}
1055-
}
1056-
1057-
impl VertexData {
1058-
pub const NATIVE: u32 = 0;
1059-
pub const GLTF: u32 = 1;
1060-
1061-
pub fn new_native(id: Id<NativeVertexData>) -> Self {
1062-
Self {
1063-
hash: Self::NATIVE,
1064-
index: id.into(),
1065-
}
1066-
}
1067-
1068-
pub fn new_gltf(id: Id<GltfVertexData>) -> Self {
1069-
Self {
1070-
hash: Self::GLTF,
1071-
index: id.into(),
1072-
}
1073-
}
1074-
1075-
pub fn is_native(&self) -> bool {
1076-
self.hash == Self::NATIVE
1077-
}
1078-
1079-
pub fn is_gltf(&self) -> bool {
1080-
self.hash == Self::GLTF
1081-
}
1082-
}
1083-
10841025
#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
10851026
#[repr(C)]
10861027
#[derive(Clone, Copy, PartialEq, Slabbed)]
@@ -1100,18 +1041,27 @@ impl Default for Transform {
11001041
}
11011042
}
11021043

1103-
/// A fully-computed unit of rendering, roughly meaning a mesh with model matrix
1104-
/// transformations.
1044+
/// A rendering "command" that draws a single mesh from a top-level node.
11051045
#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
11061046
#[repr(C)]
11071047
#[derive(Default, Clone, Copy, PartialEq, Slabbed)]
11081048
pub struct RenderUnit {
1109-
pub vertex_data: VertexData,
1049+
// Which node are we rendering, and what is the path through its
1050+
// ancestors to get to it.
1051+
pub node_path: Array<Id<GltfNode>>,
1052+
// Index of the mesh within the child node that we're rendering.
1053+
pub mesh_index: u32,
1054+
// Index of the primitive within the mesh that we're rendering.
1055+
pub primitive_index: u32,
11101056
// Points to a `Camera` in the stage's slab.
11111057
pub camera: Id<Camera>,
1112-
// Points to a `Transform` in the stage's slab.
1058+
// Points to a top-level `Transform` in the stage's slab.
1059+
//
1060+
// This is used to transform your GLTF models.
11131061
pub transform: Id<Transform>,
11141062
// Number of vertices to draw for this unit.
1063+
//
1064+
// This is a cache for convenience on CPU.
11151065
pub vertex_count: u32,
11161066
}
11171067

@@ -1121,45 +1071,34 @@ impl RenderUnit {
11211071
vertex_index: u32,
11221072
slab: &[u32],
11231073
) -> (Vertex, Transform, Id<PbrMaterial>) {
1124-
let transform = slab.read(self.transform);
1125-
match self.vertex_data.hash {
1126-
VertexData::NATIVE => {
1127-
let id = Id::<NativeVertexData>::from(self.vertex_data.index);
1128-
let NativeVertexData {
1129-
vertices,
1130-
indices,
1131-
material,
1132-
} = slab.read(id);
1133-
let index = if indices.is_empty() {
1134-
vertex_index
1135-
} else {
1136-
slab.read(indices.at(vertex_index as usize))
1137-
};
1138-
let vertex = slab.read(vertices.at(index as usize));
1139-
(vertex, transform, material)
1140-
}
1141-
VertexData::GLTF => {
1142-
let id = Id::<GltfVertexData>::from(self.vertex_data.index);
1143-
// TODO: Take the GLTF parent node's transform into account
1144-
let GltfVertexData {
1145-
parent_node_path: _,
1146-
mesh,
1147-
primitive_index,
1148-
} = slab.read(id);
1149-
// TODO: check nodes for skinning
1150-
let mesh = slab.read(mesh);
1151-
let primitive = slab.read(mesh.primitives.at(primitive_index as usize));
1152-
let material = primitive.material;
1153-
let vertex = primitive.get_vertex(vertex_index as usize, slab);
1154-
(vertex, transform, material)
1155-
}
1156-
_ => Default::default(),
1074+
let t = slab.read(self.transform);
1075+
let mut model = Mat4::from_scale_rotation_translation(t.scale, t.rotation, t.translation);
1076+
let mut node = GltfNode::default();
1077+
for id_id in self.node_path.iter() {
1078+
let node_id = slab.read(id_id);
1079+
node = slab.read(node_id);
1080+
let node_transform =
1081+
Mat4::from_scale_rotation_translation(node.scale, node.rotation, node.translation);
1082+
model = model * node_transform;
11571083
}
1084+
// TODO: check nodes for skinning
1085+
let mesh = slab.read(node.mesh);
1086+
let primitive_id = mesh.primitives.at(self.primitive_index as usize);
1087+
let primitive = slab.read(primitive_id);
1088+
let material = primitive.material;
1089+
let vertex = primitive.get_vertex(vertex_index as usize, slab);
1090+
let (s, r, t) = model.to_scale_rotation_translation_or_id();
1091+
let transform = Transform {
1092+
translation: t,
1093+
rotation: r,
1094+
scale: s,
1095+
};
1096+
(vertex, transform, material)
11581097
}
11591098
}
11601099

11611100
#[spirv(vertex)]
1162-
pub fn new_stage_vertex(
1101+
pub fn gltf_vertex(
11631102
// Which render unit are we rendering
11641103
#[spirv(instance_index)] instance_index: u32,
11651104
// Which vertex within the render unit are we rendering
@@ -1234,7 +1173,7 @@ pub fn get_material(material_index: u32, has_lighting: bool, slab: &[u32]) -> pb
12341173
#[allow(clippy::too_many_arguments)]
12351174
#[spirv(fragment)]
12361175
/// Scene fragment shader.
1237-
pub fn stage_fragment(
1176+
pub fn gltf_fragment(
12381177
#[spirv(descriptor_set = 1, binding = 0)] atlas: &Image2d,
12391178
#[spirv(descriptor_set = 1, binding = 1)] atlas_sampler: &Sampler,
12401179

@@ -1262,7 +1201,7 @@ pub fn stage_fragment(
12621201
output: &mut Vec4,
12631202
brigtness: &mut Vec4,
12641203
) {
1265-
stage_fragment_impl(
1204+
gltf_fragment_impl(
12661205
atlas,
12671206
atlas_sampler,
12681207
irradiance,
@@ -1288,7 +1227,7 @@ pub fn stage_fragment(
12881227

12891228
#[allow(clippy::too_many_arguments)]
12901229
/// Scene fragment shader.
1291-
pub fn stage_fragment_impl<T, C, S>(
1230+
pub fn gltf_fragment_impl<T, C, S>(
12921231
atlas: &T,
12931232
atlas_sampler: &S,
12941233
irradiance: &C,

crates/renderling/src/lib.rs

Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ mod state;
6262
#[cfg(feature = "text")]
6363
mod text;
6464
mod texture;
65-
mod tutorial;
65+
//mod tutorial;
6666
mod ui;
6767
mod uniform;
6868

@@ -254,14 +254,13 @@ fn init_logging() {
254254
.try_init();
255255
}
256256

257-
#[cfg(test)]
257+
#[cfg(all(feature = "blah", test))]
258258
mod test {
259259
use super::*;
260260
use glam::{Mat3, Mat4, Quat, UVec2, Vec2, Vec3, Vec4, Vec4Swizzles};
261261
use pretty_assertions::assert_eq;
262262
use renderling_shader::stage::{
263-
light::*, new_stage_vertex, Camera, GpuEntity, NativeVertexData, RenderUnit, Transform,
264-
Vertex, VertexData,
263+
gltf_vertex, light::*, Camera, GpuEntity, RenderUnit, Transform, Vertex,
265264
};
266265

267266
#[test]
@@ -610,59 +609,6 @@ mod test {
610609
]
611610
}
612611

613-
/// A helper struct that contains all outputs of the vertex shader.
614-
#[allow(unused)]
615-
#[derive(Clone, Debug, Default, PartialEq)]
616-
pub struct VertexInvocation {
617-
pub instance_index: u32,
618-
pub vertex_index: u32,
619-
pub render_unit_id: Id<RenderUnit>,
620-
pub render_unit: RenderUnit,
621-
pub out_camera: u32,
622-
pub out_material: u32,
623-
pub out_color: Vec4,
624-
pub out_uv0: Vec2,
625-
pub out_uv1: Vec2,
626-
pub out_norm: Vec3,
627-
pub out_tangent: Vec3,
628-
pub out_bitangent: Vec3,
629-
pub out_pos: Vec3,
630-
// output clip coordinates
631-
pub clip_pos: Vec4,
632-
// output normalized device coordinates
633-
pub ndc_pos: Vec3,
634-
}
635-
636-
impl VertexInvocation {
637-
#[allow(dead_code)]
638-
pub fn invoke(instance_index: u32, vertex_index: u32, slab: &[u32]) -> Self {
639-
let mut v = Self {
640-
instance_index,
641-
vertex_index,
642-
..Default::default()
643-
};
644-
v.render_unit_id = Id::from(v.instance_index);
645-
v.render_unit = slab.read(v.render_unit_id);
646-
new_stage_vertex(
647-
v.instance_index,
648-
v.vertex_index,
649-
slab,
650-
&mut v.out_camera,
651-
&mut v.out_material,
652-
&mut v.out_color,
653-
&mut v.out_uv0,
654-
&mut v.out_uv1,
655-
&mut v.out_norm,
656-
&mut v.out_tangent,
657-
&mut v.out_bitangent,
658-
&mut v.out_pos,
659-
&mut v.clip_pos,
660-
);
661-
v.ndc_pos = v.clip_pos.xyz() / v.clip_pos.w;
662-
v
663-
}
664-
}
665-
666612
#[test]
667613
// Tests that updating the material actually updates the rendering of an unlit mesh
668614
fn unlit_textured_cube_material() {
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)