Skip to main content

bevy_post_process/
lib.rs

1#![expect(missing_docs, reason = "Not all docs are written yet, see #3492.")]
2#![forbid(unsafe_code)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![doc(
5    html_logo_url = "https://bevy.org/assets/icon.png",
6    html_favicon_url = "https://bevy.org/assets/icon.png"
7)]
8
9pub mod auto_exposure;
10pub mod bloom;
11pub mod dof;
12pub mod effect_stack;
13pub mod motion_blur;
14pub mod msaa_writeback;
15
16use crate::{
17    bloom::BloomPlugin, dof::DepthOfFieldPlugin, effect_stack::EffectStackPlugin,
18    motion_blur::MotionBlurPlugin, msaa_writeback::MsaaWritebackPlugin,
19};
20use bevy_app::{App, Plugin};
21use bevy_shader::load_shader_library;
22
23/// Adds bloom, motion blur, depth of field, and chromatic aberration support.
24#[derive(#[automatically_derived]
impl ::core::default::Default for PostProcessPlugin {
    #[inline]
    fn default() -> PostProcessPlugin { PostProcessPlugin {} }
}Default)]
25pub struct PostProcessPlugin;
26
27impl Plugin for PostProcessPlugin {
28    fn build(&self, app: &mut App) {
29        {
    {
        let mut embedded =
            app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
        let path =
            {
                let crate_name =
                    "bevy_post_process".split(':').next().unwrap();
                ::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
                    "src".as_ref(), "src/lib.rs".as_ref(),
                    "gaussian_blur.wgsl".as_ref())
            };
        let watched_path =
            ::bevy_asset::io::embedded::watched_path("src/lib.rs",
                "gaussian_blur.wgsl");
        embedded.insert_asset(watched_path, &path,
            b"// A library containing a 1D Gaussian blur kernel.\n//\n// This is used by depth of field, but you can also use it in custom\n// postprocessing passes.\n\n#define_import_path bevy_post_process::gaussian_blur\n\n// Performs a single direction of the separable Gaussian blur kernel.\n//\n// * `color_texture` is the texture to blur.\n//\n// * `color_texture_sampler` is a sampler to sample the texture. It must have\n//   linear filtering for both minification and magnification.\n//\n// * `frag_coord` is the screen-space pixel coordinate of the fragment (i.e. the\n//   `position` input to the fragment).\n//\n// * `coc` is the diameter (not the radius) of the circle of confusion for this\n//   fragment.\n//\n// * `frag_offset` is the vector, in screen-space units, from one sample to the\n//   next. For a horizontal blur this will be `vec2(1.0, 0.0)`; for a vertical\n//   blur this will be `vec2(0.0, 1.0)`.\n//\n// Returns the resulting color of the fragment.\nfn gaussian_blur(color_texture: texture_2d<f32>, color_texture_sampler: sampler, frag_coord: vec4<f32>, coc: f32, frag_offset: vec2<f32>) -> vec4<f32> {\n    // Usually \xcf\x83 (the standard deviation) is half the radius, and the radius is\n    // half the CoC. So we multiply by 0.25.\n    let sigma = coc * 0.25;\n\n    // 1.5\xcf\x83 is a good, somewhat aggressive default for support\xe2\x80\x94the number of\n    // texels on each side of the center that we process.\n    let support = i32(ceil(sigma * 1.5));\n    let uv = frag_coord.xy / vec2<f32>(textureDimensions(color_texture));\n    let offset = frag_offset / vec2<f32>(textureDimensions(color_texture));\n\n    // The probability density function of the Gaussian blur is (up to constant factors) `exp(-1 / 2\xcf\x83\xc2\xb2 *\n    // x\xc2\xb2). We precalculate the constant factor here to avoid having to\n    // calculate it in the inner loop.\n    let exp_factor = -1.0 / (2.0 * sigma * sigma);\n\n    // Accumulate samples on both sides of the current texel. Go two at a time,\n    // taking advantage of bilinear filtering.\n    var sum = textureSampleLevel(color_texture, color_texture_sampler, uv, 0.0).rgb;\n    var weight_sum = 1.0;\n    for (var i = 1; i <= support; i += 2) {\n        // This is a well-known trick to reduce the number of needed texture\n        // samples by a factor of two. We seek to accumulate two adjacent\n        // samples c\xe2\x82\x80 and c\xe2\x82\x81 with weights w\xe2\x82\x80 and w\xe2\x82\x81 respectively, with a single\n        // texture sample at a carefully chosen location. Observe that:\n        //\n        //     k \xe2\x8b\x85 lerp(c\xe2\x82\x80, c\xe2\x82\x81, t) = w\xe2\x82\x80\xe2\x8b\x85c\xe2\x82\x80 + w\xe2\x82\x81\xe2\x8b\x85c\xe2\x82\x81\n        //\n        //                              w\xe2\x82\x81\n        //     if k = w\xe2\x82\x80 + w\xe2\x82\x81 and t = \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n        //                            w\xe2\x82\x80 + w\xe2\x82\x81\n        //\n        // Therefore, if we sample at a distance of t = w\xe2\x82\x81 / (w\xe2\x82\x80 + w\xe2\x82\x81) texels in\n        // between the two texel centers and scale by k = w\xe2\x82\x80 + w\xe2\x82\x81 afterward, we\n        // effectively evaluate w\xe2\x82\x80\xe2\x8b\x85c\xe2\x82\x80 + w\xe2\x82\x81\xe2\x8b\x85c\xe2\x82\x81 with a single texture lookup.\n        let w0 = exp(exp_factor * f32(i) * f32(i));\n        let w1 = exp(exp_factor * f32(i + 1) * f32(i + 1));\n        let uv_offset = offset * (f32(i) + w1 / (w0 + w1));\n        let weight = w0 + w1;\n\n        sum += (\n            textureSampleLevel(color_texture, color_texture_sampler, uv + uv_offset, 0.0).rgb +\n            textureSampleLevel(color_texture, color_texture_sampler, uv - uv_offset, 0.0).rgb\n        ) * weight;\n        weight_sum += weight * 2.0;\n    }\n\n    return vec4(sum / weight_sum, 1.0);\n}\n\n");
    }
};
let handle:
        ::bevy_shader::_macro::bevy_asset::prelude::Handle<::bevy_shader::prelude::Shader> =
    {
        let (path, asset_server) =
            {
                let path =
                    {
                        {
                            let crate_name =
                                "bevy_post_process".split(':').next().unwrap();
                            ::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
                                "src".as_ref(), "src/lib.rs".as_ref(),
                                "gaussian_blur.wgsl".as_ref())
                        }
                    };
                let path =
                    ::bevy_asset::AssetPath::from_path_buf(path).with_source("embedded");
                let asset_server =
                    ::bevy_asset::io::embedded::GetAssetServer::get_asset_server(app);
                (path, asset_server)
            };
        asset_server.load(path)
    };
core::mem::forget(handle);load_shader_library!(app, "gaussian_blur.wgsl");
30
31        app.add_plugins((
32            MsaaWritebackPlugin,
33            BloomPlugin,
34            MotionBlurPlugin,
35            DepthOfFieldPlugin,
36            EffectStackPlugin,
37        ));
38    }
39}