1use crabslab::{Id, Slab};
2use glam::{Vec2, Vec4, Vec4Swizzles};
3use spirv_std::{image::Image2d, spirv, Sampler};
4
5#[spirv(vertex)]
9pub fn bloom_vertex(
10 #[spirv(vertex_index)] vertex_index: u32,
11 #[spirv(instance_index)] in_id: u32,
12 out_uv: &mut Vec2,
13 #[spirv(flat)] out_id: &mut u32,
14 #[spirv(position)] out_clip_pos: &mut Vec4,
15) {
16 let i = (vertex_index % 6) as usize;
17 *out_uv = crate::math::UV_COORD_QUAD_CCW[i];
18 *out_clip_pos = crate::math::CLIP_SPACE_COORD_QUAD_CCW[i];
19 *out_id = in_id;
20}
21
22#[spirv(fragment)]
31pub fn bloom_downsample_fragment(
32 #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32],
33 #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d,
37 #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler,
38 in_uv: Vec2,
39 #[spirv(flat)] in_pixel_size_id: Id<Vec2>,
40 downsample: &mut Vec4,
42) {
43 use glam::Vec3;
44
45 let Vec2 { x, y } = slab.read(in_pixel_size_id);
46
47 let a = texture.sample(*sampler, Vec2::new(in_uv.x - 2.0 * x, in_uv.y + 2.0 * y));
55 let b = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y + 2.0 * y));
56 let c = texture.sample(*sampler, Vec2::new(in_uv.x + 2.0 * x, in_uv.y + 2.0 * y));
57
58 let d = texture.sample(*sampler, Vec2::new(in_uv.x - 2.0 * x, in_uv.y));
59 let e = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y));
60 let f = texture.sample(*sampler, Vec2::new(in_uv.x + 2.0 * x, in_uv.y));
61
62 let g = texture.sample(*sampler, Vec2::new(in_uv.x - 2.0 * x, in_uv.y - 2.0 * y));
63 let h = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y - 2.0 * y));
64 let i = texture.sample(*sampler, Vec2::new(in_uv.x + 2.0 * x, in_uv.y - 2.0 * y));
65
66 let j = texture.sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y + y));
67 let k = texture.sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y + y));
68 let l = texture.sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y - y));
69 let m = texture.sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y - y));
70
71 let f1 = 0.125;
85 let f2 = 0.0625;
86 let f3 = 0.03125;
87 let center = e * f1;
88 let inner = (j + k + l + m) * f1;
89 let outer = (b + d + h + f) * f2;
90 let furthest = (a + c + g + i) * f3;
91 let min = Vec3::splat(f32::EPSILON).extend(1.0);
92 *downsample = (center + inner + outer + furthest).max(min);
93}
94
95#[spirv(fragment)]
101pub fn bloom_upsample_fragment(
102 #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32],
103 #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d,
107 #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler,
108 in_uv: Vec2,
109 #[spirv(flat)] filter_radius_id: Id<Vec2>,
110 upsample: &mut Vec4,
112) {
113 let Vec2 { x, y } = slab.read(filter_radius_id);
116
117 let a = texture
123 .sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y + y))
124 .xyz();
125 let b = texture
126 .sample(*sampler, Vec2::new(in_uv.x, in_uv.y + y))
127 .xyz();
128 let c = texture
129 .sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y + y))
130 .xyz();
131
132 let d = texture
133 .sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y))
134 .xyz();
135 let e = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y)).xyz();
136 let f = texture
137 .sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y))
138 .xyz();
139
140 let g = texture
141 .sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y - y))
142 .xyz();
143 let h = texture
144 .sample(*sampler, Vec2::new(in_uv.x, in_uv.y - y))
145 .xyz();
146 let i = texture
147 .sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y - y))
148 .xyz();
149
150 let mut sample = e * 4.0;
155 sample += (b + d + f + h) * 2.0;
156 sample += a + c + g + i;
157 sample *= 1.0 / 16.0;
158 *upsample = sample.extend(0.5);
159}
160
161#[spirv(fragment)]
162#[allow(clippy::too_many_arguments)]
163pub fn bloom_mix_fragment(
168 #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32],
169 #[spirv(descriptor_set = 0, binding = 1)] hdr_texture: &Image2d,
170 #[spirv(descriptor_set = 0, binding = 2)] hdr_sampler: &Sampler,
171 #[spirv(descriptor_set = 0, binding = 3)] bloom_texture: &Image2d,
172 #[spirv(descriptor_set = 0, binding = 4)] bloom_sampler: &Sampler,
173 in_uv: Vec2,
174 #[spirv(flat)] in_bloom_strength_id: Id<f32>,
175 frag_color: &mut Vec4,
176) {
177 let bloom_strength = slab.read(in_bloom_strength_id);
178 let hdr = hdr_texture.sample(*hdr_sampler, in_uv).xyz();
179 let bloom = bloom_texture.sample(*bloom_sampler, in_uv).xyz();
180 let color = hdr.lerp(bloom, bloom_strength);
181 *frag_color = color.extend(1.0)
182}