|
| 1 | +#![cfg_attr(target_arch = "spirv", no_std)] |
| 2 | +#![feature(asm_experimental_arch)] |
| 3 | +#![allow(clippy::missing_safety_doc)] |
| 4 | + |
| 5 | +use spirv_std::{ |
| 6 | + glam::{vec3, vec4, Mat3, Mat4, Vec3, Vec4}, |
| 7 | + macros::debug_printf, |
| 8 | + num_traits::float::Float, |
| 9 | + spirv, |
| 10 | +}; |
| 11 | + |
| 12 | +#[repr(C)] |
| 13 | +pub struct UBO { |
| 14 | + projection: Mat4, |
| 15 | + model: Mat4, |
| 16 | + light_pos: Vec4, |
| 17 | +} |
| 18 | + |
| 19 | +#[spirv(vertex)] |
| 20 | +pub fn main_vs( |
| 21 | + #[spirv(vertex_index)] _vertex_index: i32, |
| 22 | + in_pos: Vec3, |
| 23 | + in_normal: Vec3, |
| 24 | + in_color: Vec3, |
| 25 | + #[spirv(uniform, descriptor_set = 0, binding = 0)] ubo: &UBO, |
| 26 | + #[spirv(position)] out_position: &mut Vec4, |
| 27 | + out_normal: &mut Vec3, |
| 28 | + out_color: &mut Vec3, |
| 29 | + out_view_vec: &mut Vec3, |
| 30 | + out_light_vec: &mut Vec3, |
| 31 | +) { |
| 32 | + *out_normal = in_normal; |
| 33 | + *out_color = in_color; |
| 34 | + *out_position = ubo.projection * ubo.model * vec4(in_pos.x, in_pos.y, in_pos.z, 1.0); |
| 35 | + |
| 36 | + let pos = ubo.model * vec4(in_pos.x, in_pos.y, in_pos.z, 1.0); |
| 37 | + |
| 38 | + // Output the vertex position using debug printf |
| 39 | + unsafe { |
| 40 | + debug_printf!("Position = %v4f", pos); |
| 41 | + } |
| 42 | + |
| 43 | + let model_mat3 = Mat3::from_cols( |
| 44 | + ubo.model.x_axis.truncate(), |
| 45 | + ubo.model.y_axis.truncate(), |
| 46 | + ubo.model.z_axis.truncate(), |
| 47 | + ); |
| 48 | + |
| 49 | + *out_normal = model_mat3 * in_normal; |
| 50 | + let l_pos = model_mat3 * ubo.light_pos.truncate(); |
| 51 | + *out_light_vec = l_pos - pos.truncate(); |
| 52 | + *out_view_vec = -pos.truncate(); |
| 53 | +} |
| 54 | + |
| 55 | +#[spirv(fragment)] |
| 56 | +pub fn main_fs( |
| 57 | + in_normal: Vec3, |
| 58 | + in_color: Vec3, |
| 59 | + in_view_vec: Vec3, |
| 60 | + in_light_vec: Vec3, |
| 61 | + #[spirv(descriptor_set = 0, binding = 1)] _sampler_color_map: &spirv_std::Image!(2D, type=f32, sampled), |
| 62 | + out_frag_color: &mut Vec4, |
| 63 | +) { |
| 64 | + // Desaturate color |
| 65 | + let gray = in_color.x * 0.2126 + in_color.y * 0.7152 + in_color.z * 0.0722; |
| 66 | + let desaturated = vec3(gray, gray, gray); |
| 67 | + let color = in_color.lerp(desaturated, 0.65); |
| 68 | + |
| 69 | + // High ambient colors because mesh materials are pretty dark |
| 70 | + let ambient = color; |
| 71 | + let n = in_normal.normalize(); |
| 72 | + let l = in_light_vec.normalize(); |
| 73 | + let v = in_view_vec.normalize(); |
| 74 | + let r = (-l).reflect(n); |
| 75 | + |
| 76 | + let diffuse = n.dot(l).max(0.0) * color; |
| 77 | + let specular = r.dot(v).max(0.0).powf(16.0) * vec3(0.75, 0.75, 0.75); |
| 78 | + |
| 79 | + let base_color = ambient + diffuse * 1.75 + specular; |
| 80 | + *out_frag_color = vec4(base_color.x, base_color.y, base_color.z, 1.0); |
| 81 | + |
| 82 | + // Toon shading |
| 83 | + let intensity = n.dot(l); |
| 84 | + let mut shade = 1.0; |
| 85 | + if intensity < 0.5 { |
| 86 | + shade = 0.75; |
| 87 | + } |
| 88 | + if intensity < 0.35 { |
| 89 | + shade = 0.6; |
| 90 | + } |
| 91 | + if intensity < 0.25 { |
| 92 | + shade = 0.5; |
| 93 | + } |
| 94 | + if intensity < 0.1 { |
| 95 | + shade = 0.25; |
| 96 | + } |
| 97 | + |
| 98 | + let final_color = in_color * 3.0 * shade; |
| 99 | + *out_frag_color = vec4(final_color.x, final_color.y, final_color.z, 1.0); |
| 100 | +} |
0 commit comments