renderling/
tutorial.rs

1//! Shaders used in the contributor intro tutorial and in WASM tests.
2
3use crabslab::{Array, Id, Slab, SlabItem};
4use glam::{Vec3, Vec3Swizzles, Vec4};
5use spirv_std::spirv;
6
7use crate::{
8    geometry::{shader::GeometryDescriptor, Vertex},
9    primitive::shader::{PrimitiveDescriptor, VertexInfo},
10};
11
12/// Simple fragment shader that writes the input color to the output color.
13// Inline pragma needed so this shader doesn't get optimized away:
14// See <https://github.com/Rust-GPU/rust-gpu/issues/185#issuecomment-2661663722>
15#[inline(never)]
16#[spirv(fragment)]
17pub fn passthru_fragment(in_color: Vec4, output: &mut Vec4) {
18    *output = in_color;
19}
20
21/// Simple vertex shader with an implicit isosceles triangle.
22///
23/// This shader gets run with three indices and draws a triangle without
24/// using any other data from the CPU.
25#[spirv(vertex)]
26pub fn implicit_isosceles_vertex(
27    // Which vertex within the render unit are we rendering
28    #[spirv(vertex_index)] vertex_index: u32,
29
30    out_color: &mut Vec4,
31    #[spirv(position)] clip_pos: &mut Vec4,
32) {
33    let pos = {
34        let x = (1 - vertex_index as i32) as f32 * 0.5;
35        let y = (((vertex_index & 1) as f32 * 2.0) - 1.0) * 0.5;
36        Vec4::new(x, y, 0.0, 1.0)
37    };
38    *out_color = Vec4::new(1.0, 0.0, 0.0, 1.0);
39    *clip_pos = pos;
40}
41
42/// This shader uses the vertex index as a slab [`Id`]. The [`Id`] is used to
43/// read the vertex from the slab. The vertex's position and color are written
44/// to the output.
45#[spirv(vertex)]
46pub fn slabbed_vertices_no_instance(
47    // Which vertex within the render unit are we rendering
48    #[spirv(vertex_index)] vertex_index: u32,
49
50    #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32],
51
52    out_color: &mut Vec4,
53    #[spirv(position)] clip_pos: &mut Vec4,
54) {
55    let vertex_id = Id::<Vertex>::from(vertex_index as usize * Vertex::SLAB_SIZE);
56    let vertex = slab.read(vertex_id);
57    *clip_pos = vertex.position.extend(1.0);
58    *out_color = vertex.color;
59}
60
61/// This shader uses the `instance_index` as a slab [`Id`].
62/// The `instance_index` is the [`Id`] of an [`Array`] of [`Vertex`]s. The
63/// `vertex_index` is the index of a [`Vertex`] within the [`Array`].
64#[spirv(vertex)]
65pub fn slabbed_vertices(
66    // Id of the array of vertices we are rendering
67    #[spirv(instance_index)] array_id: Id<Array<(Vec3, Vec4)>>,
68    // Which vertex within the render unit are we rendering
69    #[spirv(vertex_index)] vertex_index: u32,
70
71    #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32],
72
73    out_color: &mut Vec4,
74    #[spirv(position)] clip_pos: &mut Vec4,
75) {
76    let array = slab.read(array_id);
77    let vertex_id = array.at(vertex_index as usize);
78    let (position, color) = slab.read(vertex_id);
79    *clip_pos = position.extend(1.0);
80    *out_color = color;
81}
82
83/// This shader uses the `instance_index` as a slab id.
84/// The `instance_index` is the `id` of a [`PrimitiveDescriptor`].
85/// The [`PrimitiveDescriptor`] contains an [`Array`] of [`Vertex`]s
86/// as its mesh, the [`Id`]s of a
87/// [`MaterialDescriptor`](crate::material::shader::MaterialDescriptor) and
88///[`CameraDescriptor`](crate::camera::shader::CameraDescriptor),
89/// and TRS transforms.
90/// The `vertex_index` is the index of a [`Vertex`] within the
91/// [`PrimitiveDescriptor`]'s `vertices` [`Array`].
92#[spirv(vertex)]
93pub fn slabbed_renderlet(
94    // Id of the array of vertices we are rendering
95    #[spirv(instance_index)] primitive_id: Id<PrimitiveDescriptor>,
96    // Which vertex within the render unit are we rendering
97    #[spirv(vertex_index)] vertex_index: u32,
98
99    #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32],
100
101    out_color: &mut Vec4,
102    #[spirv(position)] clip_pos: &mut Vec4,
103) {
104    let prim = slab.read(primitive_id);
105    let VertexInfo {
106        vertex,
107        model_matrix,
108        ..
109    } = prim.get_vertex_info(vertex_index, slab);
110    let camera_id =
111        slab.read_unchecked(prim.geometry_descriptor_id + GeometryDescriptor::OFFSET_OF_CAMERA_ID);
112    let camera = slab.read(camera_id);
113    *clip_pos = camera.view_projection() * model_matrix * vertex.position.xyz().extend(1.0);
114    *out_color = vertex.color;
115}