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 chromatic aberration postprocessing effect.
2//
3// This makes edges of objects turn into multicolored streaks.
5#define_import_path bevy_core_pipeline::post_processing::chromatic_aberration
7// See `bevy_core_pipeline::post_process::ChromaticAberration` for more
8// information on these fields.
9struct ChromaticAberrationSettings {
10 intensity: f32,
11 max_samples: u32,
12 unused_a: u32,
13 unused_b: u32,
16// The source framebuffer texture.
17@group(0) @binding(0) var chromatic_aberration_source_texture: texture_2d<f32>;
18// The sampler used to sample the source framebuffer texture.
19@group(0) @binding(1) var chromatic_aberration_source_sampler: sampler;
20// The 1D lookup table for chromatic aberration.
21@group(0) @binding(2) var chromatic_aberration_lut_texture: texture_2d<f32>;
22// The sampler used to sample that lookup table.
23@group(0) @binding(3) var chromatic_aberration_lut_sampler: sampler;
24// The settings supplied by the developer.
25@group(0) @binding(4) var<uniform> chromatic_aberration_settings: ChromaticAberrationSettings;
27fn chromatic_aberration(start_pos: vec2<f32>) -> vec3<f32> {
28 // Radial chromatic aberration implemented using the *Inside* technique:
29 //
30 // <https://github.com/playdeadgames/publications/blob/master/INSIDE/rendering_inside_gdc2016.pdf>
32 let end_pos = mix(start_pos, vec2(0.5), chromatic_aberration_settings.intensity);
34 // Determine the number of samples. We aim for one sample per texel, unless
35 // that's higher than the developer-specified maximum number of samples, in
36 // which case we choose the maximum number of samples.
37 let texel_length = length((end_pos - start_pos) *
38 vec2<f32>(textureDimensions(chromatic_aberration_source_texture)));
39 let sample_count = min(u32(ceil(texel_length)), chromatic_aberration_settings.max_samples);
41 var color: vec3<f32>;
42 if (sample_count > 1u) {
43 // The LUT texture is in clamp-to-edge mode, so we start at 0.5 texels
44 // from the sides so that we have a nice gradient over the entire LUT
45 // range.
46 let lut_u_offset = 0.5 / f32(textureDimensions(chromatic_aberration_lut_texture).x);
48 var sample_sum = vec3(0.0);
49 var modulate_sum = vec3(0.0);
51 // Start accumulating samples.
52 for (var sample_index = 0u; sample_index < sample_count; sample_index += 1u) {
53 let t = (f32(sample_index) + 0.5) / f32(sample_count);
55 // Sample the framebuffer.
56 let sample_uv = mix(start_pos, end_pos, t);
57 let sample = textureSampleLevel(
58 chromatic_aberration_source_texture,
59 chromatic_aberration_source_sampler,
60 sample_uv,
61 0.0,
62 ).rgb;
64 // Sample the LUT.
65 let lut_u = mix(lut_u_offset, 1.0 - lut_u_offset, t);
66 let modulate = textureSampleLevel(
67 chromatic_aberration_lut_texture,
68 chromatic_aberration_lut_sampler,
69 vec2(lut_u, 0.5),
70 0.0,
71 ).rgb;
73 // Modulate the sample by the LUT value.
74 sample_sum += sample * modulate;
75 modulate_sum += modulate;
76 }
78 color = sample_sum / modulate_sum;
79 } else {
80 // If there's only one sample, don't do anything. If we don't do this,
81 // then this shader will apply whatever tint is in the center of the LUT
82 // texture to such pixels, which is wrong.
83 color = textureSampleLevel(
84 chromatic_aberration_source_texture,
85 chromatic_aberration_source_sampler,
86 start_pos,
87 0.0,
88 ).rgb;
89 }
91 return color;
Contents