renderling/skybox/
shader.rs1use crabslab::{Id, Slab};
4use glam::{Mat3, Mat4, Vec2, Vec3, Vec4, Vec4Swizzles};
5use spirv_std::{
6 image::{Cubemap, Image2d},
7 spirv, Sampler,
8};
9
10#[allow(unused_imports)]
11use spirv_std::num_traits::Float;
12
13use crate::{
14 camera::shader::CameraDescriptor,
15 math::{self, IsVector},
16};
17
18const INV_ATAN: Vec2 = Vec2::new(0.1591, core::f32::consts::FRAC_1_PI);
19
20pub fn direction_to_equirectangular_uv(dir: Vec3) -> Vec2 {
23 let mut uv = Vec2::new(f32::atan2(dir.z, dir.x), f32::asin(dir.y));
24 uv *= INV_ATAN;
25 uv += 0.5;
26 uv
27}
28
29#[spirv(vertex)]
31pub fn skybox_vertex(
32 #[spirv(instance_index)] camera_index: u32,
33 #[spirv(vertex_index)] vertex_index: u32,
34 #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32],
35 local_pos: &mut Vec3,
36 #[spirv(position)] clip_pos: &mut Vec4,
37) {
38 let camera_id = Id::<CameraDescriptor>::from(camera_index);
39 let camera = slab.read(camera_id);
40 let point = math::CUBE[vertex_index as usize];
41 *local_pos = point;
42 let camera_view_without_translation = Mat3::from_mat4(camera.view());
43 let rot_view = Mat4::from_mat3(camera_view_without_translation);
44 let position = camera.projection() * rot_view * point.extend(1.0);
45 *clip_pos = position.xyww();
46}
47
48#[spirv(fragment)]
50pub fn skybox_cubemap_fragment(
51 #[spirv(descriptor_set = 0, binding = 1)] texture: &Cubemap,
52 #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler,
53 local_pos: Vec3,
54 out_color: &mut Vec4,
55) {
56 let env_color: Vec3 = texture.sample(*sampler, local_pos.alt_norm_or_zero()).xyz();
57 *out_color = env_color.extend(1.0);
58}
59
60#[spirv(vertex)]
67pub fn skybox_cubemap_vertex(
68 #[spirv(instance_index)] camera_id: Id<CameraDescriptor>,
69 #[spirv(vertex_index)] vertex_index: u32,
70 #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32],
71 local_pos: &mut Vec3,
72 #[spirv(position)] gl_pos: &mut Vec4,
73) {
74 let camera = slab.read(camera_id);
75 let pos = crate::math::CUBE[vertex_index as usize];
76 *local_pos = pos;
77 *gl_pos = camera.view_projection() * pos.extend(1.0);
78}
79
80#[spirv(fragment)]
82pub fn skybox_equirectangular_fragment(
83 #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d,
84 #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler,
85 local_pos: Vec3,
86 out_color: &mut Vec4,
87) {
88 let uv = direction_to_equirectangular_uv(local_pos.alt_norm_or_zero());
89 let env_color: Vec3 = texture.sample(*sampler, uv).xyz();
90 *out_color = env_color.extend(1.0);
91}