renderling/atlas/
shader.rs1use crabslab::{Id, Slab, SlabItem};
2use glam::{UVec2, UVec3, Vec2, Vec3, Vec3Swizzles, Vec4, Vec4Swizzles};
3use spirv_std::{image::Image2d, spirv, Sampler};
4
5#[derive(Clone, Copy, core::fmt::Debug, Default, PartialEq, SlabItem)]
7pub struct AtlasDescriptor {
8 pub size: UVec3,
9}
10
11#[derive(Clone, Copy, Default, PartialEq, SlabItem, core::fmt::Debug)]
13pub struct AtlasTextureDescriptor {
14 pub offset_px: UVec2,
16 pub size_px: UVec2,
18 pub layer_index: u32,
21 pub frame_index: u32,
23 pub modes: super::TextureModes,
25}
26
27impl AtlasTextureDescriptor {
28 pub fn uv(&self, mut uv: Vec2, atlas_size: UVec2) -> Vec3 {
31 uv.x = self.modes.s.wrap(uv.x);
32 uv.y = self.modes.t.wrap(uv.y);
33
34 let mut px_index_s = (uv.x * self.size_px.x as f32) as u32;
37 let mut px_index_t = (uv.y * self.size_px.y as f32) as u32;
38
39 px_index_s += self.offset_px.x;
41 px_index_t += self.offset_px.y;
42
43 let sx = atlas_size.x as f32;
44 let sy = atlas_size.y as f32;
45 let uv_s = px_index_s as f32 / sx;
47 let uv_t = px_index_t as f32 / sy;
48
49 Vec2::new(uv_s, uv_t).extend(self.layer_index as f32)
50 }
51
52 pub fn constrain_clip_coords_to_texture_space(
55 &self,
56 clip_pos: Vec2,
57 atlas_size: UVec2,
58 ) -> Vec2 {
59 let input_uv = (clip_pos * Vec2::new(1.0, -1.0) + Vec2::splat(1.0)) * Vec2::splat(0.5);
62 self.uv(input_uv, atlas_size).xy()
63 }
64
65 pub fn constrain_clip_coords(&self, clip_pos: Vec2, atlas_size: UVec2) -> Vec2 {
68 let uv = self.constrain_clip_coords_to_texture_space(clip_pos, atlas_size);
69 (uv * Vec2::new(2.0, 2.0) - Vec2::splat(1.0)) * Vec2::new(1.0, -1.0)
71 }
72
73 #[cfg(cpu)]
74 pub fn origin(&self) -> wgpu::Origin3d {
76 wgpu::Origin3d {
77 x: self.offset_px.x,
78 y: self.offset_px.y,
79 z: self.layer_index,
80 }
81 }
82
83 #[cfg(cpu)]
84 pub fn size_as_extent(&self) -> wgpu::Extent3d {
86 wgpu::Extent3d {
87 width: self.size_px.x,
88 height: self.size_px.y,
89 depth_or_array_layers: 1,
90 }
91 }
92}
93
94#[derive(Clone, Copy, Default, SlabItem, core::fmt::Debug)]
95pub struct AtlasBlittingDescriptor {
96 pub atlas_texture_id: Id<AtlasTextureDescriptor>,
97 pub atlas_desc_id: Id<AtlasDescriptor>,
98}
99
100#[spirv(vertex)]
106pub fn atlas_blit_vertex(
107 #[spirv(vertex_index)] vertex_id: u32,
108 #[spirv(instance_index)] atlas_blitting_desc_id: Id<AtlasBlittingDescriptor>,
109 #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] slab: &[u32],
110 out_uv: &mut Vec2,
111 #[spirv(position)] out_pos: &mut Vec4,
112) {
113 let i = vertex_id as usize;
114 *out_uv = crate::math::UV_COORD_QUAD_CCW[i];
115
116 crate::println!("atlas_blitting_desc_id: {atlas_blitting_desc_id:?}");
117 let atlas_blitting_desc = slab.read_unchecked(atlas_blitting_desc_id);
118 crate::println!("atlas_blitting_desc: {atlas_blitting_desc:?}");
119 let atlas_texture = slab.read_unchecked(atlas_blitting_desc.atlas_texture_id);
120 crate::println!("atlas_texture: {atlas_texture:?}");
121 let atlas_desc = slab.read_unchecked(atlas_blitting_desc.atlas_desc_id);
122 crate::println!("atlas_desc: {atlas_desc:?}");
123 let clip_pos = crate::math::CLIP_SPACE_COORD_QUAD_CCW[i];
124 crate::println!("clip_pos: {clip_pos:?}");
125 *out_pos = atlas_texture
126 .constrain_clip_coords(clip_pos.xy(), atlas_desc.size.xy())
127 .extend(clip_pos.z)
128 .extend(clip_pos.w);
129 crate::println!("out_pos: {out_pos}");
130}
131
132#[spirv(fragment)]
134pub fn atlas_blit_fragment(
135 #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d,
136 #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler,
137 in_uv: Vec2,
138 frag_color: &mut Vec4,
139) {
140 *frag_color = texture.sample(*sampler, in_uv);
141}