Search across packages, versions, files, declarations, and comments. Use multiple terms to narrow results (AND), and add @vertex, @fragment, or @compute to filter by shader stage.
1//! The vignette postprocessing effect.
3import package::effect_stack::chromatic_aberration::source_texture;
5/// See `package::effect_stack::Vignette` for more
6/// information on these fields.
7struct VignetteSettings {
8 intensity: f32,
9 radius: f32,
10 smoothness: f32,
11 roundness: f32,
12 center: vec2<f32>,
13 edge_compensation: f32,
14 unused: u32,
15 color: vec4<f32>
18const VISUAL_THRESHOLD: f32 = 1e-4;
20/// The settings supplied by the developer.
21@group(0) @binding(4) var<uniform> vignette_settings: VignetteSettings;
23fn vignette(uv: vec2<f32>, color: vec3<f32>) -> vec3<f32> {
24 let intensity = vignette_settings.intensity;
25 if (intensity < VISUAL_THRESHOLD) {
26 return color;
27 }
28 let radius = vignette_settings.radius;
29 let smoothness = vignette_settings.smoothness;
30 let roundness = vignette_settings.roundness;
31 let edge_comp = vignette_settings.edge_compensation;
33 // Get the screen resolution.
34 let dims = textureDimensions(source_texture);
35 let resolution = vec2<f32>(dims.xy);
36 let screen_aspect = resolution.x / resolution.y;
38 // Calculate the aspect ratio.
39 //
40 // We divide by the smallest dimension to normalize the scale.
41 // This will be used later to force the vignette to be circular, not oval.
42 let aspect_ratio = resolution / min(resolution.x, resolution.y);
44 // Center the UV coordinates at (0,0).
45 let centered_uv = uv - 0.5;
47 // Calculate the normalized offset from the center.
48 //
49 // (vignette_settings.center - 0.5) maps the 0.0-1.0 input to -0.5-0.5.
50 // Multiplying by (1.0, y/x) compensates for the screen's aspect ratio.
51 // This ensures that a movement of 0.1 looks the same distance horizontally and vertically.
52 let offset = (vignette_settings.center - 0.5) * vec2<f32>(1.0, resolution.y / resolution.x);
54 let uv_from_center = centered_uv - offset;
55 var scale_vec = aspect_ratio * vec2<f32>(1.0, 1.0 / roundness);
57 // Apply edge compensation to make the vignette fit the screen better.
58 if (screen_aspect >= 1.0) {
59 let compensation_factor = mix(1.0, 1.0 / screen_aspect, edge_comp);
60 scale_vec.x *= compensation_factor;
61 } else {
62 let compensation_factor = mix(1.0, screen_aspect, edge_comp);
63 scale_vec.y *= compensation_factor;
64 }
66 let final_uv = uv_from_center * scale_vec;
68 // Calculate distance from center.
69 let dist = length(final_uv) * (1.0 / radius);
70 let base_curve = 1.0 - (dist * dist);
71 let clamped_factor = clamp(base_curve, 0.0, 1.0);
72 let factor = pow(clamped_factor, smoothness);
74 // Blend the original color with the vignette color.
75 return mix(color, vignette_settings.color.rgb, (1.0 - factor) * intensity);
Contents