|
| 1 | +// The chromatic aberration postprocessing effect. |
| 2 | +// |
| 3 | +// This makes edges of objects turn into multicolored streaks. |
| 4 | + |
| 5 | +#define_import_path bevy_core_pipeline::post_processing::chromatic_aberration |
| 6 | + |
| 7 | +// See `bevy_core_pipeline::post_process::ChromaticAberration` for more |
| 8 | +// information on these fields. |
| 9 | +struct ChromaticAberrationSettings { |
| 10 | + intensity: f32, |
| 11 | + max_samples: u32, |
| 12 | + unused_a: u32, |
| 13 | + unused_b: u32, |
| 14 | +} |
| 15 | + |
| 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; |
| 26 | + |
| 27 | +fn 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> |
| 31 | + |
| 32 | + let end_pos = mix(start_pos, vec2(0.5), chromatic_aberration_settings.intensity); |
| 33 | + |
| 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); |
| 40 | + |
| 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); |
| 47 | + |
| 48 | + var sample_sum = vec3(0.0); |
| 49 | + var modulate_sum = vec3(0.0); |
| 50 | + |
| 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); |
| 54 | + |
| 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; |
| 63 | + |
| 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; |
| 72 | + |
| 73 | + // Modulate the sample by the LUT value. |
| 74 | + sample_sum += sample * modulate; |
| 75 | + modulate_sum += modulate; |
| 76 | + } |
| 77 | + |
| 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 | + } |
| 90 | + |
| 91 | + return color; |
| 92 | +} |
0 commit comments