1use bevy_app::{App, Plugin};
18use bevy_asset::{embedded_asset, load_embedded_asset, AssetServer, Handle};
19use bevy_camera::{Camera3d, PhysicalCameraParameters, Projection};
20use bevy_derive::{Deref, DerefMut};
21use bevy_ecs::{
22 component::Component,
23 entity::Entity,
24 query::With,
25 reflect::ReflectComponent,
26 resource::Resource,
27 schedule::IntoScheduleConfigs as _,
28 system::{Commands, Query, Res, ResMut},
29};
30use bevy_math::ops;
31use bevy_reflect::{prelude::ReflectDefault, Reflect};
32use bevy_render::{
33 camera::ExtractedCamera,
34 extract_component::{ComponentUniforms, DynamicUniformIndex, UniformComponentPlugin},
35 render_resource::{
36 binding_types::{
37 sampler, texture_2d, texture_depth_2d, texture_depth_2d_multisampled, uniform_buffer,
38 },
39 BindGroup, BindGroupEntries, BindGroupLayoutDescriptor, BindGroupLayoutEntries,
40 CachedRenderPipelineId, ColorTargetState, ColorWrites, FilterMode, FragmentState, LoadOp,
41 Operations, PipelineCache, RenderPassColorAttachment, RenderPassDescriptor,
42 RenderPipelineDescriptor, Sampler, SamplerBindingType, SamplerDescriptor, ShaderStages,
43 ShaderType, SpecializedRenderPipeline, SpecializedRenderPipelines, StoreOp,
44 TextureDescriptor, TextureDimension, TextureFormat, TextureSampleType, TextureUsages,
45 },
46 renderer::{RenderContext, RenderDevice, ViewQuery},
47 sync_component::{SyncComponent, SyncComponentPlugin},
48 sync_world::RenderEntity,
49 texture::{CachedTexture, TextureCache},
50 view::{
51 prepare_view_targets, ExtractedView, Msaa, ViewDepthTexture, ViewTarget, ViewUniform,
52 ViewUniformOffset, ViewUniforms,
53 },
54 Extract, ExtractSchedule, GpuResourceAppExt, Render, RenderApp, RenderStartup, RenderSystems,
55};
56use bevy_shader::Shader;
57use bevy_utils::{default, once};
58use smallvec::SmallVec;
59use tracing::{info, warn};
60
61use crate::bloom::bloom;
62use bevy_core_pipeline::{
63 core_3d::DEPTH_PREPASS_TEXTURE_SUPPORTED, schedule::Core3d, tonemapping::tonemapping,
64 FullscreenShader,
65};
66
67#[derive(#[automatically_derived]
impl ::core::default::Default for DepthOfFieldPlugin {
#[inline]
fn default() -> DepthOfFieldPlugin { DepthOfFieldPlugin {} }
}Default)]
69pub struct DepthOfFieldPlugin;
70
71#[derive(impl bevy_ecs::component::Component for DepthOfField where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component, #[automatically_derived]
impl ::core::clone::Clone for DepthOfField {
#[inline]
fn clone(&self) -> DepthOfField {
let _: ::core::clone::AssertParamIsClone<DepthOfFieldMode>;
let _: ::core::clone::AssertParamIsClone<f32>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for DepthOfField { }Copy, const _: () =
{
impl bevy_reflect::GetTypeRegistration for DepthOfField where {
fn get_type_registration() -> bevy_reflect::TypeRegistration {
let mut registration =
bevy_reflect::TypeRegistration::of::<Self>();
registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
registration.register_type_data::<ReflectComponent, Self>();
registration.register_type_data::<ReflectDefault, Self>();
registration
}
#[inline(never)]
fn register_type_dependencies(registry:
&mut bevy_reflect::TypeRegistry) {
<DepthOfFieldMode as
bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
<f32 as
bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
}
}
impl bevy_reflect::Typed for DepthOfField where {
#[inline]
fn type_info() -> &'static bevy_reflect::TypeInfo {
static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
bevy_reflect::utility::NonGenericTypeInfoCell::new();
CELL.get_or_set(||
{
bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<DepthOfFieldMode>("mode"),
bevy_reflect::NamedField::new::<f32>("focal_distance"),
bevy_reflect::NamedField::new::<f32>("sensor_height"),
bevy_reflect::NamedField::new::<f32>("aperture_f_stops"),
bevy_reflect::NamedField::new::<f32>("max_circle_of_confusion_diameter"),
bevy_reflect::NamedField::new::<f32>("max_depth")]))
})
}
}
#[allow(deprecated, reason =
"derives on a deprecated type shouldn't be considered a usage")]
impl bevy_reflect::TypePath for DepthOfField where {
fn type_path() -> &'static str {
"bevy_post_process::dof::DepthOfField"
}
fn short_type_path() -> &'static str { "DepthOfField" }
fn type_ident() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("DepthOfField")
}
fn crate_name() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_post_process::dof".split(':').next().unwrap())
}
fn module_path() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_post_process::dof")
}
}
impl bevy_reflect::Reflect for DepthOfField where {
#[inline]
fn into_any(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn ::core::any::Any { self }
#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
#[inline]
fn into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
self
}
#[inline]
fn set(&mut self,
value:
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
->
::core::result::Result<(),
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
*self = <dyn bevy_reflect::Reflect>::take(value)?;
::core::result::Result::Ok(())
}
}
#[allow(non_upper_case_globals)]
const _: () =
{
static __INVENTORY: ::inventory::Node =
::inventory::Node {
value: &{
bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<DepthOfField
as
bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
},
next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
};
#[link_section = ".text.startup"]
unsafe extern "C" fn __ctor() {
unsafe {
::inventory::ErasedNode::submit(__INVENTORY.value,
&__INVENTORY)
}
}
#[used]
#[link_section = ".init_array"]
static __CTOR: unsafe extern "C" fn() = __ctor;
};
impl bevy_reflect::structs::Struct for DepthOfField where {
fn field(&self, name: &str)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match name {
"mode" => ::core::option::Option::Some(&self.mode),
"focal_distance" =>
::core::option::Option::Some(&self.focal_distance),
"sensor_height" =>
::core::option::Option::Some(&self.sensor_height),
"aperture_f_stops" =>
::core::option::Option::Some(&self.aperture_f_stops),
"max_circle_of_confusion_diameter" =>
::core::option::Option::Some(&self.max_circle_of_confusion_diameter),
"max_depth" =>
::core::option::Option::Some(&self.max_depth),
_ => ::core::option::Option::None,
}
}
fn field_mut(&mut self, name: &str)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match name {
"mode" => ::core::option::Option::Some(&mut self.mode),
"focal_distance" =>
::core::option::Option::Some(&mut self.focal_distance),
"sensor_height" =>
::core::option::Option::Some(&mut self.sensor_height),
"aperture_f_stops" =>
::core::option::Option::Some(&mut self.aperture_f_stops),
"max_circle_of_confusion_diameter" =>
::core::option::Option::Some(&mut self.max_circle_of_confusion_diameter),
"max_depth" =>
::core::option::Option::Some(&mut self.max_depth),
_ => ::core::option::Option::None,
}
}
fn field_at(&self, index: usize)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match index {
0usize => ::core::option::Option::Some(&self.mode),
1usize =>
::core::option::Option::Some(&self.focal_distance),
2usize => ::core::option::Option::Some(&self.sensor_height),
3usize =>
::core::option::Option::Some(&self.aperture_f_stops),
4usize =>
::core::option::Option::Some(&self.max_circle_of_confusion_diameter),
5usize => ::core::option::Option::Some(&self.max_depth),
_ => ::core::option::Option::None,
}
}
fn field_at_mut(&mut self, index: usize)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match index {
0usize => ::core::option::Option::Some(&mut self.mode),
1usize =>
::core::option::Option::Some(&mut self.focal_distance),
2usize =>
::core::option::Option::Some(&mut self.sensor_height),
3usize =>
::core::option::Option::Some(&mut self.aperture_f_stops),
4usize =>
::core::option::Option::Some(&mut self.max_circle_of_confusion_diameter),
5usize => ::core::option::Option::Some(&mut self.max_depth),
_ => ::core::option::Option::None,
}
}
fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
match index {
0usize => ::core::option::Option::Some("mode"),
1usize => ::core::option::Option::Some("focal_distance"),
2usize => ::core::option::Option::Some("sensor_height"),
3usize => ::core::option::Option::Some("aperture_f_stops"),
4usize =>
::core::option::Option::Some("max_circle_of_confusion_diameter"),
5usize => ::core::option::Option::Some("max_depth"),
_ => ::core::option::Option::None,
}
}
fn index_of_name(&self, name: &str)
-> ::core::option::Option<usize> {
match name {
"mode" => ::core::option::Option::Some(0usize),
"focal_distance" => ::core::option::Option::Some(1usize),
"sensor_height" => ::core::option::Option::Some(2usize),
"aperture_f_stops" => ::core::option::Option::Some(3usize),
"max_circle_of_confusion_diameter" =>
::core::option::Option::Some(4usize),
"max_depth" => ::core::option::Option::Some(5usize),
_ => ::core::option::Option::None,
}
}
fn field_len(&self) -> usize { 6usize }
fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
bevy_reflect::structs::FieldIter::new(self)
}
fn to_dynamic_struct(&self)
-> bevy_reflect::structs::DynamicStruct {
let mut dynamic: bevy_reflect::structs::DynamicStruct =
::core::default::Default::default();
dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
dynamic.insert_boxed("mode",
bevy_reflect::PartialReflect::to_dynamic(&self.mode));
dynamic.insert_boxed("focal_distance",
bevy_reflect::PartialReflect::to_dynamic(&self.focal_distance));
dynamic.insert_boxed("sensor_height",
bevy_reflect::PartialReflect::to_dynamic(&self.sensor_height));
dynamic.insert_boxed("aperture_f_stops",
bevy_reflect::PartialReflect::to_dynamic(&self.aperture_f_stops));
dynamic.insert_boxed("max_circle_of_confusion_diameter",
bevy_reflect::PartialReflect::to_dynamic(&self.max_circle_of_confusion_diameter));
dynamic.insert_boxed("max_depth",
bevy_reflect::PartialReflect::to_dynamic(&self.max_depth));
dynamic
}
}
impl bevy_reflect::PartialReflect for DepthOfField where {
#[inline]
fn get_represented_type_info(&self)
-> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
::core::option::Option::Some(<Self as
bevy_reflect::Typed>::type_info())
}
#[inline]
fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
-> ::core::result::Result<(), bevy_reflect::ApplyError> {
if let bevy_reflect::ReflectRef::Struct(struct_value) =
bevy_reflect::PartialReflect::reflect_ref(value) {
for (name, value) in
bevy_reflect::structs::Struct::iter_fields(struct_value) {
if let ::core::option::Option::Some(v) =
bevy_reflect::structs::Struct::field_mut(self, name) {
bevy_reflect::PartialReflect::try_apply(v, value)?;
}
}
} else {
return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
to_kind: bevy_reflect::ReflectKind::Struct,
});
}
::core::result::Result::Ok(())
}
#[inline]
fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
bevy_reflect::ReflectKind::Struct
}
#[inline]
fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
bevy_reflect::ReflectRef::Struct(self)
}
#[inline]
fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
bevy_reflect::ReflectMut::Struct(self)
}
#[inline]
fn reflect_owned(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
-> bevy_reflect::ReflectOwned {
bevy_reflect::ReflectOwned::Struct(self)
}
#[inline]
fn try_into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
::core::result::Result::Ok(self)
}
#[inline]
fn try_as_reflect(&self)
-> ::core::option::Option<&dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn try_as_reflect_mut(&mut self)
-> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn into_partial_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
self
}
#[inline]
fn as_partial_reflect(&self)
-> &dyn bevy_reflect::PartialReflect {
self
}
#[inline]
fn as_partial_reflect_mut(&mut self)
-> &mut dyn bevy_reflect::PartialReflect {
self
}
fn reflect_partial_eq(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<bool> {
(bevy_reflect::structs::struct_partial_eq)(self, value)
}
fn reflect_partial_cmp(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<::core::cmp::Ordering> {
(bevy_reflect::structs::struct_partial_cmp)(self, value)
}
#[inline]
fn reflect_clone(&self)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::ReflectCloneError> {
::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
}
}
impl bevy_reflect::FromReflect for DepthOfField where {
fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<Self> {
if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
bevy_reflect::PartialReflect::reflect_ref(reflect) {
let mut __this =
<Self as ::core::default::Default>::default();
if let ::core::option::Option::Some(__field) =
(||
<DepthOfFieldMode as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
"mode")?))() {
__this.mode = __field;
}
if let ::core::option::Option::Some(__field) =
(||
<f32 as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
"focal_distance")?))() {
__this.focal_distance = __field;
}
if let ::core::option::Option::Some(__field) =
(||
<f32 as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
"sensor_height")?))() {
__this.sensor_height = __field;
}
if let ::core::option::Option::Some(__field) =
(||
<f32 as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
"aperture_f_stops")?))() {
__this.aperture_f_stops = __field;
}
if let ::core::option::Option::Some(__field) =
(||
<f32 as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
"max_circle_of_confusion_diameter")?))() {
__this.max_circle_of_confusion_diameter = __field;
}
if let ::core::option::Option::Some(__field) =
(||
<f32 as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
"max_depth")?))() {
__this.max_depth = __field;
}
::core::option::Option::Some(__this)
} else { ::core::option::Option::None }
}
}
};Reflect)]
76#[reflect(Component, Clone, Default)]
77pub struct DepthOfField {
78 pub mode: DepthOfFieldMode,
80
81 pub focal_distance: f32,
83
84 pub sensor_height: f32,
93
94 pub aperture_f_stops: f32,
97
98 pub max_circle_of_confusion_diameter: f32,
105
106 pub max_depth: f32,
116}
117
118#[derive(#[automatically_derived]
impl ::core::clone::Clone for DepthOfFieldMode {
#[inline]
fn clone(&self) -> DepthOfFieldMode { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for DepthOfFieldMode { }Copy, #[automatically_derived]
impl ::core::default::Default for DepthOfFieldMode {
#[inline]
fn default() -> DepthOfFieldMode { Self::Gaussian }
}Default, #[automatically_derived]
impl ::core::cmp::PartialEq for DepthOfFieldMode {
#[inline]
fn eq(&self, other: &DepthOfFieldMode) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for DepthOfFieldMode {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
DepthOfFieldMode::Bokeh => "Bokeh",
DepthOfFieldMode::Gaussian => "Gaussian",
})
}
}Debug, const _: () =
{
impl bevy_reflect::GetTypeRegistration for DepthOfFieldMode where {
fn get_type_registration() -> bevy_reflect::TypeRegistration {
let mut registration =
bevy_reflect::TypeRegistration::of::<Self>();
registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
registration.register_type_data::<ReflectDefault, Self>();
registration
}
#[inline(never)]
fn register_type_dependencies(registry:
&mut bevy_reflect::TypeRegistry) {}
}
impl bevy_reflect::Typed for DepthOfFieldMode where {
#[inline]
fn type_info() -> &'static bevy_reflect::TypeInfo {
static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
bevy_reflect::utility::NonGenericTypeInfoCell::new();
CELL.get_or_set(||
{
bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("Bokeh")),
bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("Gaussian"))]))
})
}
}
#[allow(deprecated, reason =
"derives on a deprecated type shouldn't be considered a usage")]
impl bevy_reflect::TypePath for DepthOfFieldMode where {
fn type_path() -> &'static str {
"bevy_post_process::dof::DepthOfFieldMode"
}
fn short_type_path() -> &'static str { "DepthOfFieldMode" }
fn type_ident() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("DepthOfFieldMode")
}
fn crate_name() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_post_process::dof".split(':').next().unwrap())
}
fn module_path() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_post_process::dof")
}
}
impl bevy_reflect::Reflect for DepthOfFieldMode where {
#[inline]
fn into_any(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn ::core::any::Any { self }
#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
#[inline]
fn into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
self
}
#[inline]
fn set(&mut self,
value:
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
->
::core::result::Result<(),
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
*self = <dyn bevy_reflect::Reflect>::take(value)?;
::core::result::Result::Ok(())
}
}
#[allow(non_upper_case_globals)]
const _: () =
{
static __INVENTORY: ::inventory::Node =
::inventory::Node {
value: &{
bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<DepthOfFieldMode
as
bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
},
next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
};
#[link_section = ".text.startup"]
unsafe extern "C" fn __ctor() {
unsafe {
::inventory::ErasedNode::submit(__INVENTORY.value,
&__INVENTORY)
}
}
#[used]
#[link_section = ".init_array"]
static __CTOR: unsafe extern "C" fn() = __ctor;
};
impl bevy_reflect::enums::Enum for DepthOfFieldMode where {
fn field(&self, __name_param: &str)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match self { _ => ::core::option::Option::None, }
}
fn field_at(&self, __index_param: usize)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match self { _ => ::core::option::Option::None, }
}
fn field_mut(&mut self, __name_param: &str)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match self { _ => ::core::option::Option::None, }
}
fn field_at_mut(&mut self, __index_param: usize)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match self { _ => ::core::option::Option::None, }
}
fn index_of(&self, __name_param: &str)
-> ::core::option::Option<usize> {
match self { _ => ::core::option::Option::None, }
}
fn name_at(&self, __index_param: usize)
-> ::core::option::Option<&str> {
match self { _ => ::core::option::Option::None, }
}
fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
bevy_reflect::enums::VariantFieldIter::new(self)
}
#[inline]
fn field_len(&self) -> usize {
match self {
DepthOfFieldMode::Bokeh { .. } => 0usize,
DepthOfFieldMode::Gaussian { .. } => 0usize,
_ => 0,
}
}
#[inline]
fn variant_name(&self) -> &str {
match self {
DepthOfFieldMode::Bokeh { .. } => "Bokeh",
DepthOfFieldMode::Gaussian { .. } => "Gaussian",
_ =>
::core::panicking::panic("internal error: entered unreachable code"),
}
}
#[inline]
fn variant_index(&self) -> usize {
match self {
DepthOfFieldMode::Bokeh { .. } => 0usize,
DepthOfFieldMode::Gaussian { .. } => 1usize,
_ =>
::core::panicking::panic("internal error: entered unreachable code"),
}
}
#[inline]
fn variant_type(&self) -> bevy_reflect::enums::VariantType {
match self {
DepthOfFieldMode::Bokeh { .. } =>
bevy_reflect::enums::VariantType::Unit,
DepthOfFieldMode::Gaussian { .. } =>
bevy_reflect::enums::VariantType::Unit,
_ =>
::core::panicking::panic("internal error: entered unreachable code"),
}
}
fn to_dynamic_enum(&self) -> bevy_reflect::enums::DynamicEnum {
bevy_reflect::enums::DynamicEnum::from_ref::<Self>(self)
}
}
impl bevy_reflect::PartialReflect for DepthOfFieldMode where {
#[inline]
fn get_represented_type_info(&self)
-> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
::core::option::Option::Some(<Self as
bevy_reflect::Typed>::type_info())
}
#[inline]
fn try_apply(&mut self,
__value_param: &dyn bevy_reflect::PartialReflect)
-> ::core::result::Result<(), bevy_reflect::ApplyError> {
if let bevy_reflect::ReflectRef::Enum(__value_param) =
bevy_reflect::PartialReflect::reflect_ref(__value_param) {
if bevy_reflect::enums::Enum::variant_name(self) ==
bevy_reflect::enums::Enum::variant_name(__value_param) {
match bevy_reflect::enums::Enum::variant_type(__value_param)
{
bevy_reflect::enums::VariantType::Struct => {
for field in
bevy_reflect::enums::Enum::iter_fields(__value_param) {
let name = field.name().unwrap();
if let ::core::option::Option::Some(v) =
bevy_reflect::enums::Enum::field_mut(self, name) {
bevy_reflect::PartialReflect::try_apply(v, field.value())?;
}
}
}
bevy_reflect::enums::VariantType::Tuple => {
for (index, field) in
::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
{
if let ::core::option::Option::Some(v) =
bevy_reflect::enums::Enum::field_at_mut(self, index) {
bevy_reflect::PartialReflect::try_apply(v, field.value())?;
}
}
}
_ => {}
}
} else {
match bevy_reflect::enums::Enum::variant_name(__value_param)
{
"Bokeh" => { *self = DepthOfFieldMode::Bokeh {} }
"Gaussian" => { *self = DepthOfFieldMode::Gaussian {} }
name => {
return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
variant_name: ::core::convert::Into::into(name),
});
}
}
}
} else {
return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
to_kind: bevy_reflect::ReflectKind::Enum,
});
}
::core::result::Result::Ok(())
}
fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
bevy_reflect::ReflectKind::Enum
}
fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
bevy_reflect::ReflectRef::Enum(self)
}
fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
bevy_reflect::ReflectMut::Enum(self)
}
fn reflect_owned(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
-> bevy_reflect::ReflectOwned {
bevy_reflect::ReflectOwned::Enum(self)
}
#[inline]
fn try_into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
::core::result::Result::Ok(self)
}
#[inline]
fn try_as_reflect(&self)
-> ::core::option::Option<&dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn try_as_reflect_mut(&mut self)
-> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn into_partial_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
self
}
#[inline]
fn as_partial_reflect(&self)
-> &dyn bevy_reflect::PartialReflect {
self
}
#[inline]
fn as_partial_reflect_mut(&mut self)
-> &mut dyn bevy_reflect::PartialReflect {
self
}
fn reflect_hash(&self) -> ::core::option::Option<u64> {
(bevy_reflect::enums::enum_hash)(self)
}
fn reflect_partial_eq(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<bool> {
let value =
<dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
if let ::core::option::Option::Some(value) = value {
::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
value))
} else { ::core::option::Option::Some(false) }
}
fn reflect_partial_cmp(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<::core::cmp::Ordering> {
(bevy_reflect::enums::enum_partial_cmp)(self, value)
}
#[inline]
fn reflect_clone(&self)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::ReflectCloneError> {
::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
}
}
impl bevy_reflect::FromReflect for DepthOfFieldMode where {
fn from_reflect(__param0: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<Self> {
if let bevy_reflect::ReflectRef::Enum(__param0) =
bevy_reflect::PartialReflect::reflect_ref(__param0) {
match bevy_reflect::enums::Enum::variant_name(__param0) {
"Bokeh" =>
::core::option::Option::Some(DepthOfFieldMode::Bokeh {}),
"Gaussian" =>
::core::option::Option::Some(DepthOfFieldMode::Gaussian {}),
name => ::core::option::Option::None,
}
} else { ::core::option::Option::None }
}
}
};Reflect)]
120#[reflect(Default, Clone, PartialEq)]
121pub enum DepthOfFieldMode {
122 Bokeh,
129
130 #[default]
137 Gaussian,
138}
139
140#[derive(#[automatically_derived]
impl ::core::clone::Clone for DepthOfFieldUniform {
#[inline]
fn clone(&self) -> DepthOfFieldUniform {
let _: ::core::clone::AssertParamIsClone<f32>;
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for DepthOfFieldUniform { }Copy, impl bevy_ecs::component::Component for DepthOfFieldUniform where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component, impl bevy_render::render_resource::encase::private::ShaderSize for
DepthOfFieldUniform where
f32: bevy_render::render_resource::encase::private::ShaderSize,
f32: bevy_render::render_resource::encase::private::ShaderSize,
f32: bevy_render::render_resource::encase::private::ShaderSize,
f32: bevy_render::render_resource::encase::private::ShaderSize,
f32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize,
u32: bevy_render::render_resource::encase::private::ShaderSize {}ShaderType)]
142pub struct DepthOfFieldUniform {
143 focal_distance: f32,
145
146 focal_length: f32,
149
150 coc_scale_factor: f32,
155
156 max_circle_of_confusion_diameter: f32,
159
160 max_depth: f32,
163
164 pad_a: u32,
166 pad_b: u32,
168 pad_c: u32,
170}
171
172#[derive(#[automatically_derived]
impl ::core::clone::Clone for DepthOfFieldPipelineKey {
#[inline]
fn clone(&self) -> DepthOfFieldPipelineKey {
let _: ::core::clone::AssertParamIsClone<DofPass>;
let _: ::core::clone::AssertParamIsClone<TextureFormat>;
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for DepthOfFieldPipelineKey { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for DepthOfFieldPipelineKey {
#[inline]
fn eq(&self, other: &DepthOfFieldPipelineKey) -> bool {
self.multisample == other.multisample && self.pass == other.pass &&
self.target_format == other.target_format
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for DepthOfFieldPipelineKey {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<DofPass>;
let _: ::core::cmp::AssertParamIsEq<TextureFormat>;
let _: ::core::cmp::AssertParamIsEq<bool>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for DepthOfFieldPipelineKey {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.pass, state);
::core::hash::Hash::hash(&self.target_format, state);
::core::hash::Hash::hash(&self.multisample, state)
}
}Hash)]
174pub struct DepthOfFieldPipelineKey {
175 pass: DofPass,
177 target_format: TextureFormat,
178 multisample: bool,
180}
181
182#[derive(#[automatically_derived]
impl ::core::clone::Clone for DofPass {
#[inline]
fn clone(&self) -> DofPass { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for DofPass { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for DofPass {
#[inline]
fn eq(&self, other: &DofPass) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for DofPass {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for DofPass {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash)]
184enum DofPass {
185 GaussianHorizontal,
187 GaussianVertical,
189 BokehPass0,
191 BokehPass1,
193}
194
195impl Plugin for DepthOfFieldPlugin {
196 fn build(&self, app: &mut App) {
197 {
{
let mut embedded =
app.world_mut().resource_mut::<::bevy_asset::io::embedded::EmbeddedAssetRegistry>();
let path =
{
let crate_name =
"bevy_post_process::dof".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/dof/mod.rs".as_ref(),
"dof.wgsl".as_ref())
};
let watched_path =
::bevy_asset::io::embedded::watched_path("src/dof/mod.rs",
"dof.wgsl");
embedded.insert_asset(watched_path, &path,
b"// Performs depth of field postprocessing, with both Gaussian and bokeh kernels.\n//\n// Gaussian blur is performed as a separable convolution: first blurring in the\n// X direction, and then in the Y direction. This is asymptotically more\n// efficient than performing a 2D convolution.\n//\n// The Bokeh blur uses a similar, but more complex, separable convolution\n// technique. The algorithm is described in Colin Barr\xc3\xa9-Brisebois, \"Hexagonal\n// Bokeh Blur Revisited\" [1]. It\'s motivated by the observation that we can use\n// separable convolutions not only to produce boxes but to produce\n// parallelograms. Thus, by performing three separable convolutions in sequence,\n// we can produce a hexagonal shape. The first and second convolutions are done\n// simultaneously using multiple render targets to cut the total number of\n// passes down to two.\n//\n// [1]: https://colinbarrebrisebois.com/2017/04/18/hexagonal-bokeh-blur-revisited-part-2-improved-2-pass-version/\n\n#import bevy_core_pipeline::fullscreen_vertex_shader::FullscreenVertexOutput\n#import bevy_pbr::mesh_view_bindings::view\n#import bevy_pbr::view_transformations::depth_ndc_to_view_z\n#import bevy_post_process::gaussian_blur::gaussian_blur\n#import bevy_render::view::View\n\n// Parameters that control the depth of field effect. See\n// `bevy_core_pipeline::dof::DepthOfFieldUniforms` for information on what these\n// parameters mean.\nstruct DepthOfFieldParams {\n /// The distance in meters to the location in focus.\n focal_distance: f32,\n\n /// The [focal length]. Physically speaking, this represents \"the distance\n /// from the center of the lens to the principal foci of the lens\". The\n /// default value, 50 mm, is considered representative of human eyesight.\n /// Real-world lenses range from anywhere from 5 mm for \"fisheye\" lenses to\n /// 2000 mm for \"super-telephoto\" lenses designed for very distant objects.\n ///\n /// The higher the value, the more blurry objects not in focus will be.\n ///\n /// [focal length]: https://en.wikipedia.org/wiki/Focal_length\n focal_length: f32,\n\n /// The premultiplied factor that we scale the circle of confusion by.\n ///\n /// This is calculated as `focal_length\xc2\xb2 / (sensor_height * aperture_f_stops)`.\n coc_scale_factor: f32,\n\n /// The maximum diameter, in pixels, that we allow a circle of confusion to be.\n ///\n /// A circle of confusion essentially describes the size of a blur.\n ///\n /// This value is nonphysical but is useful for avoiding pathologically-slow\n /// behavior.\n max_circle_of_confusion_diameter: f32,\n\n /// The depth value that we clamp distant objects to. See the comment in\n /// [`DepthOfField`] for more information.\n max_depth: f32,\n\n /// Padding.\n pad_a: u32,\n /// Padding.\n pad_b: u32,\n /// Padding.\n pad_c: u32,\n}\n\n// The first bokeh pass outputs to two render targets. We declare them here.\nstruct DualOutput {\n // The vertical output.\n @location(0) output_0: vec4<f32>,\n // The diagonal output.\n @location(1) output_1: vec4<f32>,\n}\n\n// @group(0) @binding(0) is `mesh_view_bindings::view`.\n\n// The depth texture for the main view.\n#ifdef MULTISAMPLED\n@group(0) @binding(1) var depth_texture: texture_depth_multisampled_2d;\n#else // MULTISAMPLED\n@group(0) @binding(1) var depth_texture: texture_depth_2d;\n#endif // MULTISAMPLED\n\n// The main color texture.\n@group(0) @binding(2) var color_texture_a: texture_2d<f32>;\n\n// The auxiliary color texture that we\'re sampling from. This is only used as\n// part of the second bokeh pass.\n#ifdef DUAL_INPUT\n@group(0) @binding(3) var color_texture_b: texture_2d<f32>;\n#endif // DUAL_INPUT\n\n// The global uniforms, representing data backed by buffers shared among all\n// views in the scene.\n\n// The parameters that control the depth of field effect.\n@group(1) @binding(0) var<uniform> dof_params: DepthOfFieldParams;\n\n// The sampler that\'s used to fetch texels from the source color buffer.\n@group(1) @binding(1) var color_texture_sampler: sampler;\n\n// used to ensure `depth * (focus - f)` is always a positive number,\nconst EPSILON: f32 = 1.19209290e-07;\n// cos(-30\xc2\xb0), used for the bokeh blur.\nconst COS_NEG_FRAC_PI_6: f32 = 0.8660254037844387;\n// sin(-30\xc2\xb0), used for the bokeh blur.\nconst SIN_NEG_FRAC_PI_6: f32 = -0.5;\n// cos(-150\xc2\xb0), used for the bokeh blur.\nconst COS_NEG_FRAC_PI_5_6: f32 = -0.8660254037844387;\n// sin(-150\xc2\xb0), used for the bokeh blur.\nconst SIN_NEG_FRAC_PI_5_6: f32 = -0.5;\n\n// Calculates and returns the diameter (not the radius) of the [circle of\n// confusion].\n//\n// [circle of confusion]: https://en.wikipedia.org/wiki/Circle_of_confusion\nfn calculate_circle_of_confusion(in_frag_coord: vec4<f32>) -> f32 {\n // Unpack the depth of field parameters.\n let focus = dof_params.focal_distance;\n let f = dof_params.focal_length;\n let scale = dof_params.coc_scale_factor;\n let max_coc_diameter = dof_params.max_circle_of_confusion_diameter;\n\n // Sample the depth.\n let frag_coord = vec2<i32>(floor(in_frag_coord.xy));\n let raw_depth = textureLoad(depth_texture, frag_coord, 0);\n let depth = min(-depth_ndc_to_view_z(raw_depth), dof_params.max_depth);\n\n // Calculate the circle of confusion.\n //\n // This is just the formula from Wikipedia [1].\n //\n // [1]: https://en.wikipedia.org/wiki/Circle_of_confusion#Determining_a_circle_of_confusion_diameter_from_the_object_field\n let candidate_coc = scale * abs(depth - focus) / (depth * max(focus - f, EPSILON));\n\n let framebuffer_size = vec2<f32>(textureDimensions(color_texture_a));\n return clamp(candidate_coc * framebuffer_size.y, 0.0, max_coc_diameter);\n}\n\n// Performs a box blur in a single direction, sampling `color_texture_a`.\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. This need not be horizontal or vertical.\nfn box_blur_a(frag_coord: vec4<f32>, coc: f32, frag_offset: vec2<f32>) -> vec4<f32> {\n let support = i32(round(coc * 0.5));\n let uv = frag_coord.xy / vec2<f32>(textureDimensions(color_texture_a));\n let offset = frag_offset / vec2<f32>(textureDimensions(color_texture_a));\n\n // Accumulate samples in a single direction.\n var sum = vec3(0.0);\n for (var i = 0; i <= support; i += 1) {\n sum += textureSampleLevel(\n color_texture_a, color_texture_sampler, uv + offset * f32(i), 0.0).rgb;\n }\n\n return vec4(sum / vec3(1.0 + f32(support)), 1.0);\n}\n\n// Performs a box blur in a single direction, sampling `color_texture_b`.\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. This need not be horizontal or vertical.\n#ifdef DUAL_INPUT\nfn box_blur_b(frag_coord: vec4<f32>, coc: f32, frag_offset: vec2<f32>) -> vec4<f32> {\n let support = i32(round(coc * 0.5));\n let uv = frag_coord.xy / vec2<f32>(textureDimensions(color_texture_b));\n let offset = frag_offset / vec2<f32>(textureDimensions(color_texture_b));\n\n // Accumulate samples in a single direction.\n var sum = vec3(0.0);\n for (var i = 0; i <= support; i += 1) {\n sum += textureSampleLevel(\n color_texture_b, color_texture_sampler, uv + offset * f32(i), 0.0).rgb;\n }\n\n return vec4(sum / vec3(1.0 + f32(support)), 1.0);\n}\n#endif\n\n// Calculates the horizontal component of the separable Gaussian blur.\n@fragment\nfn gaussian_horizontal(in: FullscreenVertexOutput) -> @location(0) vec4<f32> {\n let coc = calculate_circle_of_confusion(in.position);\n return gaussian_blur(color_texture_a, color_texture_sampler, in.position, coc, vec2(1.0, 0.0));\n}\n\n// Calculates the vertical component of the separable Gaussian blur.\n@fragment\nfn gaussian_vertical(in: FullscreenVertexOutput) -> @location(0) vec4<f32> {\n let coc = calculate_circle_of_confusion(in.position);\n return gaussian_blur(color_texture_a, color_texture_sampler, in.position, coc, vec2(0.0, 1.0));\n}\n\n// Calculates the vertical and first diagonal components of the separable\n// hexagonal bokeh blur.\n//\n// \xe2\x95\xb1\n// \xe2\x95\xb1\n// \xe2\x80\xa2\n// \xe2\x94\x82\n// \xe2\x94\x82\n@fragment\nfn bokeh_pass_a(in: FullscreenVertexOutput) -> DualOutput {\n let coc = calculate_circle_of_confusion(in.position);\n let vertical = box_blur_a(in.position, coc, vec2(0.0, 1.0));\n let diagonal = box_blur_a(in.position, coc, vec2(COS_NEG_FRAC_PI_6, SIN_NEG_FRAC_PI_6));\n\n // Note that the diagonal part is pre-mixed with the vertical component.\n var output: DualOutput;\n output.output_0 = vertical;\n output.output_1 = mix(vertical, diagonal, 0.5);\n return output;\n}\n\n// Calculates the second diagonal components of the separable hexagonal bokeh\n// blur.\n//\n// \xe2\x95\xb2 \xe2\x95\xb1\n// \xe2\x95\xb2 \xe2\x95\xb1\n// \xe2\x80\xa2\n#ifdef DUAL_INPUT\n@fragment\nfn bokeh_pass_b(in: FullscreenVertexOutput) -> @location(0) vec4<f32> {\n let coc = calculate_circle_of_confusion(in.position);\n let output_0 = box_blur_a(in.position, coc, vec2(COS_NEG_FRAC_PI_6, SIN_NEG_FRAC_PI_6));\n let output_1 = box_blur_b(in.position, coc, vec2(COS_NEG_FRAC_PI_5_6, SIN_NEG_FRAC_PI_5_6));\n return mix(output_0, output_1, 0.5);\n}\n#endif\n");
}
};embedded_asset!(app, "dof.wgsl");
198
199 app.add_plugins(UniformComponentPlugin::<DepthOfFieldUniform>::default());
200
201 app.add_plugins(SyncComponentPlugin::<DepthOfField>::default());
202
203 let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
204 return;
205 };
206
207 render_app
208 .init_gpu_resource::<SpecializedRenderPipelines<DepthOfFieldPipeline>>()
209 .init_resource::<DepthOfFieldGlobalBindGroup>()
210 .add_systems(RenderStartup, init_dof_global_bind_group_layout)
211 .add_systems(ExtractSchedule, extract_depth_of_field_settings)
212 .add_systems(
213 Render,
214 (
215 configure_depth_of_field_view_targets
216 .ambiguous_with(RenderSystems::PrepareViews),
217 prepare_auxiliary_depth_of_field_textures,
218 )
219 .after(prepare_view_targets)
220 .in_set(RenderSystems::PrepareViews),
221 )
222 .add_systems(
223 Render,
224 (
225 prepare_depth_of_field_view_bind_group_layouts,
226 prepare_depth_of_field_pipelines,
227 )
228 .chain()
229 .in_set(RenderSystems::Prepare),
230 )
231 .add_systems(
232 Render,
233 prepare_depth_of_field_global_bind_group.in_set(RenderSystems::PrepareBindGroups),
234 )
235 .add_systems(Core3d, depth_of_field.after(bloom).before(tonemapping));
236 }
237}
238
239#[derive(impl bevy_ecs::resource::Resource for DepthOfFieldGlobalBindGroupLayout where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource, #[automatically_derived]
impl ::core::clone::Clone for DepthOfFieldGlobalBindGroupLayout {
#[inline]
fn clone(&self) -> DepthOfFieldGlobalBindGroupLayout {
DepthOfFieldGlobalBindGroupLayout {
layout: ::core::clone::Clone::clone(&self.layout),
color_texture_sampler: ::core::clone::Clone::clone(&self.color_texture_sampler),
}
}
}Clone)]
242pub struct DepthOfFieldGlobalBindGroupLayout {
243 layout: BindGroupLayoutDescriptor,
245 color_texture_sampler: Sampler,
247}
248
249#[derive(impl bevy_ecs::resource::Resource for DepthOfFieldGlobalBindGroup where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Resource, #[automatically_derived]
impl ::core::default::Default for DepthOfFieldGlobalBindGroup {
#[inline]
fn default() -> DepthOfFieldGlobalBindGroup {
DepthOfFieldGlobalBindGroup(::core::default::Default::default())
}
}Default, impl ::core::ops::Deref for DepthOfFieldGlobalBindGroup {
type Target = Option<BindGroup>;
fn deref(&self) -> &Self::Target { &self.0 }
}Deref, impl ::core::ops::DerefMut for DepthOfFieldGlobalBindGroup {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}DerefMut)]
252pub struct DepthOfFieldGlobalBindGroup(Option<BindGroup>);
253
254#[derive(impl bevy_ecs::component::Component for DepthOfFieldPipelines where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn map_entities<M: bevy_ecs::entity::EntityMapper>(this: &mut Self,
mapper: &mut M) {
use bevy_ecs::entity::MapEntities;
match this {
Self::Gaussian { .. } => {}
Self::Bokeh { .. } => {}
_ => {}
}
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component)]
255pub enum DepthOfFieldPipelines {
256 Gaussian {
257 horizontal: CachedRenderPipelineId,
258 vertical: CachedRenderPipelineId,
259 },
260 Bokeh {
261 pass_0: CachedRenderPipelineId,
262 pass_1: CachedRenderPipelineId,
263 },
264}
265
266struct DepthOfFieldPipelineRenderInfo {
267 pass_label: &'static str,
268 view_bind_group_label: &'static str,
269 pipeline: CachedRenderPipelineId,
270 is_dual_input: bool,
271 is_dual_output: bool,
272}
273
274#[derive(impl bevy_ecs::component::Component for AuxiliaryDepthOfFieldTexture where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component, impl ::core::ops::Deref for AuxiliaryDepthOfFieldTexture {
type Target = CachedTexture;
fn deref(&self) -> &Self::Target { &self.0 }
}Deref, impl ::core::ops::DerefMut for AuxiliaryDepthOfFieldTexture {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}DerefMut)]
280pub struct AuxiliaryDepthOfFieldTexture(CachedTexture);
281
282#[derive(impl bevy_ecs::component::Component for ViewDepthOfFieldBindGroupLayouts where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component, #[automatically_derived]
impl ::core::clone::Clone for ViewDepthOfFieldBindGroupLayouts {
#[inline]
fn clone(&self) -> ViewDepthOfFieldBindGroupLayouts {
ViewDepthOfFieldBindGroupLayouts {
single_input: ::core::clone::Clone::clone(&self.single_input),
dual_input: ::core::clone::Clone::clone(&self.dual_input),
}
}
}Clone)]
284pub struct ViewDepthOfFieldBindGroupLayouts {
285 single_input: BindGroupLayoutDescriptor,
287
288 dual_input: Option<BindGroupLayoutDescriptor>,
292}
293
294pub struct DepthOfFieldPipeline {
297 view_bind_group_layouts: ViewDepthOfFieldBindGroupLayouts,
299 global_bind_group_layout: BindGroupLayoutDescriptor,
302 fullscreen_shader: FullscreenShader,
304 fragment_shader: Handle<Shader>,
306}
307
308impl Default for DepthOfField {
309 fn default() -> Self {
310 let physical_camera_default = PhysicalCameraParameters::default();
311 Self {
312 focal_distance: 10.0,
313 aperture_f_stops: physical_camera_default.aperture_f_stops,
314 sensor_height: physical_camera_default.sensor_height,
315 max_circle_of_confusion_diameter: 64.0,
316 max_depth: f32::INFINITY,
317 mode: DepthOfFieldMode::default(),
318 }
319 }
320}
321
322impl DepthOfField {
323 pub fn from_physical_camera(camera: &PhysicalCameraParameters) -> DepthOfField {
334 DepthOfField {
335 sensor_height: camera.sensor_height,
336 aperture_f_stops: camera.aperture_f_stops,
337 ..default()
338 }
339 }
340}
341
342pub fn init_dof_global_bind_group_layout(mut commands: Commands, render_device: Res<RenderDevice>) {
343 let layout = BindGroupLayoutDescriptor::new(
346 "depth of field global bind group layout",
347 &BindGroupLayoutEntries::sequential(
348 ShaderStages::FRAGMENT,
349 (
350 uniform_buffer::<DepthOfFieldUniform>(true),
352 sampler(SamplerBindingType::Filtering),
354 ),
355 ),
356 );
357
358 let sampler = render_device.create_sampler(&SamplerDescriptor {
360 label: Some("depth of field sampler"),
361 mag_filter: FilterMode::Linear,
362 min_filter: FilterMode::Linear,
363 ..default()
364 });
365
366 commands.insert_resource(DepthOfFieldGlobalBindGroupLayout {
367 color_texture_sampler: sampler,
368 layout,
369 });
370}
371
372pub fn prepare_depth_of_field_view_bind_group_layouts(
375 mut commands: Commands,
376 view_targets: Query<(Entity, &DepthOfField, &Msaa)>,
377) {
378 for (view, depth_of_field, msaa) in view_targets.iter() {
379 let single_input = BindGroupLayoutDescriptor::new(
381 "depth of field bind group layout (single input)",
382 &BindGroupLayoutEntries::sequential(
383 ShaderStages::FRAGMENT,
384 (
385 uniform_buffer::<ViewUniform>(true),
386 if *msaa != Msaa::Off {
387 texture_depth_2d_multisampled()
388 } else {
389 texture_depth_2d()
390 },
391 texture_2d(TextureSampleType::Float { filterable: true }),
392 ),
393 ),
394 );
395
396 let dual_input = match depth_of_field.mode {
399 DepthOfFieldMode::Gaussian => None,
400 DepthOfFieldMode::Bokeh => Some(BindGroupLayoutDescriptor::new(
401 "depth of field bind group layout (dual input)",
402 &BindGroupLayoutEntries::sequential(
403 ShaderStages::FRAGMENT,
404 (
405 uniform_buffer::<ViewUniform>(true),
406 if *msaa != Msaa::Off {
407 texture_depth_2d_multisampled()
408 } else {
409 texture_depth_2d()
410 },
411 texture_2d(TextureSampleType::Float { filterable: true }),
412 texture_2d(TextureSampleType::Float { filterable: true }),
413 ),
414 ),
415 )),
416 };
417
418 commands
419 .entity(view)
420 .insert(ViewDepthOfFieldBindGroupLayouts {
421 single_input,
422 dual_input,
423 });
424 }
425}
426
427pub fn configure_depth_of_field_view_targets(
435 mut view_targets: Query<&mut Camera3d, With<DepthOfField>>,
436) {
437 for mut camera_3d in view_targets.iter_mut() {
438 let mut depth_texture_usages = TextureUsages::from(camera_3d.depth_texture_usages);
439 depth_texture_usages |= TextureUsages::TEXTURE_BINDING;
440 camera_3d.depth_texture_usages = depth_texture_usages.into();
441 }
442}
443
444pub fn prepare_depth_of_field_global_bind_group(
447 global_bind_group_layout: Res<DepthOfFieldGlobalBindGroupLayout>,
448 mut dof_bind_group: ResMut<DepthOfFieldGlobalBindGroup>,
449 depth_of_field_uniforms: Res<ComponentUniforms<DepthOfFieldUniform>>,
450 render_device: Res<RenderDevice>,
451 pipeline_cache: Res<PipelineCache>,
452) {
453 let Some(depth_of_field_uniforms) = depth_of_field_uniforms.binding() else {
454 return;
455 };
456
457 **dof_bind_group = Some(render_device.create_bind_group(
458 Some("depth of field global bind group"),
459 &pipeline_cache.get_bind_group_layout(&global_bind_group_layout.layout),
460 &BindGroupEntries::sequential((
461 depth_of_field_uniforms, &global_bind_group_layout.color_texture_sampler, )),
464 ));
465}
466
467pub fn prepare_auxiliary_depth_of_field_textures(
470 mut commands: Commands,
471 render_device: Res<RenderDevice>,
472 mut texture_cache: ResMut<TextureCache>,
473 mut view_targets: Query<(Entity, &ViewTarget, &DepthOfField)>,
474) {
475 for (entity, view_target, depth_of_field) in view_targets.iter_mut() {
476 if depth_of_field.mode != DepthOfFieldMode::Bokeh {
478 continue;
479 }
480
481 let texture_descriptor = TextureDescriptor {
483 label: Some("depth of field auxiliary texture"),
484 size: view_target.main_texture().size(),
485 mip_level_count: 1,
486 sample_count: view_target.main_texture().sample_count(),
487 dimension: TextureDimension::D2,
488 format: view_target.main_texture_format(),
489 usage: TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING,
490 view_formats: &[],
491 };
492
493 let texture = texture_cache.get(&render_device, texture_descriptor);
494
495 commands
496 .entity(entity)
497 .insert(AuxiliaryDepthOfFieldTexture(texture));
498 }
499}
500
501pub fn prepare_depth_of_field_pipelines(
503 mut commands: Commands,
504 pipeline_cache: Res<PipelineCache>,
505 mut pipelines: ResMut<SpecializedRenderPipelines<DepthOfFieldPipeline>>,
506 global_bind_group_layout: Res<DepthOfFieldGlobalBindGroupLayout>,
507 view_targets: Query<
508 (
509 Entity,
510 &ExtractedView,
511 &DepthOfField,
512 &ViewDepthOfFieldBindGroupLayouts,
513 &Msaa,
514 ),
515 With<ExtractedCamera>,
516 >,
517 fullscreen_shader: Res<FullscreenShader>,
518 asset_server: Res<AssetServer>,
519) {
520 for (entity, view, depth_of_field, view_bind_group_layouts, msaa) in view_targets.iter() {
521 let dof_pipeline = DepthOfFieldPipeline {
522 view_bind_group_layouts: view_bind_group_layouts.clone(),
523 global_bind_group_layout: global_bind_group_layout.layout.clone(),
524 fullscreen_shader: fullscreen_shader.clone(),
525 fragment_shader: {
let (path, asset_server) =
{
let path =
{
{
let crate_name =
"bevy_post_process::dof".split(':').next().unwrap();
::bevy_asset::io::embedded::_embedded_asset_path(crate_name,
"src".as_ref(), "src/dof/mod.rs".as_ref(),
"dof.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(asset_server.as_ref());
(path, asset_server)
};
asset_server.load(path)
}load_embedded_asset!(asset_server.as_ref(), "dof.wgsl"),
526 };
527
528 let (target_format, multisample) = (view.target_format, *msaa != Msaa::Off);
530
531 match depth_of_field.mode {
533 DepthOfFieldMode::Gaussian => {
534 commands
535 .entity(entity)
536 .insert(DepthOfFieldPipelines::Gaussian {
537 horizontal: pipelines.specialize(
538 &pipeline_cache,
539 &dof_pipeline,
540 DepthOfFieldPipelineKey {
541 target_format,
542 multisample,
543 pass: DofPass::GaussianHorizontal,
544 },
545 ),
546 vertical: pipelines.specialize(
547 &pipeline_cache,
548 &dof_pipeline,
549 DepthOfFieldPipelineKey {
550 target_format,
551 multisample,
552 pass: DofPass::GaussianVertical,
553 },
554 ),
555 });
556 }
557
558 DepthOfFieldMode::Bokeh => {
559 commands
560 .entity(entity)
561 .insert(DepthOfFieldPipelines::Bokeh {
562 pass_0: pipelines.specialize(
563 &pipeline_cache,
564 &dof_pipeline,
565 DepthOfFieldPipelineKey {
566 target_format,
567 multisample,
568 pass: DofPass::BokehPass0,
569 },
570 ),
571 pass_1: pipelines.specialize(
572 &pipeline_cache,
573 &dof_pipeline,
574 DepthOfFieldPipelineKey {
575 target_format,
576 multisample,
577 pass: DofPass::BokehPass1,
578 },
579 ),
580 });
581 }
582 }
583 }
584}
585
586impl SpecializedRenderPipeline for DepthOfFieldPipeline {
587 type Key = DepthOfFieldPipelineKey;
588
589 fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
590 let (mut layout, mut shader_defs) = (::alloc::vec::Vec::new()vec![], ::alloc::vec::Vec::new()vec![]);
592 let mut targets = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Some(ColorTargetState {
format: key.target_format,
blend: None,
write_mask: ColorWrites::ALL,
})]))vec![Some(ColorTargetState {
593 format: key.target_format,
594 blend: None,
595 write_mask: ColorWrites::ALL,
596 })];
597
598 match key.pass {
600 DofPass::GaussianHorizontal | DofPass::GaussianVertical => {
601 layout.push(self.view_bind_group_layouts.single_input.clone());
603 }
604 DofPass::BokehPass0 => {
605 layout.push(self.view_bind_group_layouts.single_input.clone());
607 targets.push(targets[0].clone());
608 }
609 DofPass::BokehPass1 => {
610 let dual_input_bind_group_layout = self
613 .view_bind_group_layouts
614 .dual_input
615 .as_ref()
616 .expect("Dual-input depth of field bind group should have been created by now")
617 .clone();
618 layout.push(dual_input_bind_group_layout);
619 shader_defs.push("DUAL_INPUT".into());
620 }
621 }
622
623 layout.push(self.global_bind_group_layout.clone());
625
626 if key.multisample {
627 shader_defs.push("MULTISAMPLED".into());
628 }
629
630 RenderPipelineDescriptor {
631 label: Some("depth of field pipeline".into()),
632 layout,
633 vertex: self.fullscreen_shader.to_vertex_state(),
634 fragment: Some(FragmentState {
635 shader: self.fragment_shader.clone(),
636 shader_defs,
637 entry_point: Some(match key.pass {
638 DofPass::GaussianHorizontal => "gaussian_horizontal".into(),
639 DofPass::GaussianVertical => "gaussian_vertical".into(),
640 DofPass::BokehPass0 => "bokeh_pass_a".into(),
643 DofPass::BokehPass1 => "bokeh_pass_b".into(),
644 }),
645 targets,
646 }),
647 ..default()
648 }
649 }
650}
651
652impl SyncComponent for DepthOfField {
653 type Target = (
654 DepthOfField,
655 DepthOfFieldUniform,
656 DepthOfFieldPipelines,
657 AuxiliaryDepthOfFieldTexture,
658 ViewDepthOfFieldBindGroupLayouts,
659 );
660}
661
662fn extract_depth_of_field_settings(
664 mut commands: Commands,
665 mut query: Extract<Query<(RenderEntity, &DepthOfField, &Projection)>>,
666) {
667 if !DEPTH_PREPASS_TEXTURE_SUPPORTED {
668 {
static SHOULD_FIRE: ::bevy_utils::OnceFlag =
::bevy_utils::OnceFlag::new();
if SHOULD_FIRE.set() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/dof/mod.rs:668",
"bevy_post_process::dof", ::tracing::Level::INFO,
::tracing_core::__macro_support::Option::Some("src/dof/mod.rs"),
::tracing_core::__macro_support::Option::Some(668u32),
::tracing_core::__macro_support::Option::Some("bevy_post_process::dof"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::INFO <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::INFO <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Disabling depth of field on this platform because depth textures aren\'t supported correctly")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
}
};once!(info!(
669 "Disabling depth of field on this platform because depth textures aren't supported correctly"
670 ));
671 return;
672 }
673
674 for (entity, depth_of_field, projection) in query.iter_mut() {
675 let mut entity_commands = commands
676 .get_entity(entity)
677 .expect("Depth of field entity wasn't synced.");
678
679 let Projection::Perspective(ref perspective_projection) = *projection else {
681 entity_commands.remove::<<DepthOfField as SyncComponent>::Target>();
682
683 continue;
684 };
685
686 let focal_length =
687 calculate_focal_length(depth_of_field.sensor_height, perspective_projection.fov);
688
689 entity_commands.insert((
691 *depth_of_field,
692 DepthOfFieldUniform {
693 focal_distance: depth_of_field.focal_distance,
694 focal_length,
695 coc_scale_factor: focal_length * focal_length
696 / (depth_of_field.sensor_height * depth_of_field.aperture_f_stops),
697 max_circle_of_confusion_diameter: depth_of_field.max_circle_of_confusion_diameter,
698 max_depth: depth_of_field.max_depth,
699 pad_a: 0,
700 pad_b: 0,
701 pad_c: 0,
702 },
703 ));
704 }
705}
706
707pub fn calculate_focal_length(sensor_height: f32, fov: f32) -> f32 {
711 0.5 * sensor_height / ops::tan(0.5 * fov)
712}
713
714impl DepthOfFieldPipelines {
715 fn pipeline_render_info(&self) -> [DepthOfFieldPipelineRenderInfo; 2] {
718 match *self {
719 DepthOfFieldPipelines::Gaussian {
720 horizontal: horizontal_pipeline,
721 vertical: vertical_pipeline,
722 } => [
723 DepthOfFieldPipelineRenderInfo {
724 pass_label: "depth of field pass (horizontal Gaussian)",
725 view_bind_group_label: "depth of field view bind group (horizontal Gaussian)",
726 pipeline: horizontal_pipeline,
727 is_dual_input: false,
728 is_dual_output: false,
729 },
730 DepthOfFieldPipelineRenderInfo {
731 pass_label: "depth of field pass (vertical Gaussian)",
732 view_bind_group_label: "depth of field view bind group (vertical Gaussian)",
733 pipeline: vertical_pipeline,
734 is_dual_input: false,
735 is_dual_output: false,
736 },
737 ],
738
739 DepthOfFieldPipelines::Bokeh {
740 pass_0: pass_0_pipeline,
741 pass_1: pass_1_pipeline,
742 } => [
743 DepthOfFieldPipelineRenderInfo {
744 pass_label: "depth of field pass (bokeh pass 0)",
745 view_bind_group_label: "depth of field view bind group (bokeh pass 0)",
746 pipeline: pass_0_pipeline,
747 is_dual_input: false,
748 is_dual_output: true,
749 },
750 DepthOfFieldPipelineRenderInfo {
751 pass_label: "depth of field pass (bokeh pass 1)",
752 view_bind_group_label: "depth of field view bind group (bokeh pass 1)",
753 pipeline: pass_1_pipeline,
754 is_dual_input: true,
755 is_dual_output: false,
756 },
757 ],
758 }
759 }
760}
761
762pub(crate) fn depth_of_field(
763 view: ViewQuery<(
764 &ViewUniformOffset,
765 &ViewTarget,
766 &ViewDepthTexture,
767 &DepthOfFieldPipelines,
768 &ViewDepthOfFieldBindGroupLayouts,
769 &DynamicUniformIndex<DepthOfFieldUniform>,
770 Option<&AuxiliaryDepthOfFieldTexture>,
771 )>,
772 pipeline_cache: Res<PipelineCache>,
773 view_uniforms: Res<ViewUniforms>,
774 global_bind_group: Res<DepthOfFieldGlobalBindGroup>,
775 mut ctx: RenderContext,
776) {
777 let (
778 view_uniform_offset,
779 view_target,
780 view_depth_texture,
781 view_pipelines,
782 view_bind_group_layouts,
783 depth_of_field_uniform_index,
784 auxiliary_dof_texture,
785 ) = view.into_inner();
786
787 for pipeline_render_info in view_pipelines.pipeline_render_info().iter() {
790 let (Some(render_pipeline), Some(view_uniforms_binding), Some(global_bind_group)) = (
791 pipeline_cache.get_render_pipeline(pipeline_render_info.pipeline),
792 view_uniforms.uniforms.binding(),
793 &**global_bind_group,
794 ) else {
795 return;
796 };
797
798 let postprocess = view_target.post_process_write();
803
804 let view_bind_group = if pipeline_render_info.is_dual_input {
805 let (Some(auxiliary_dof_texture), Some(dual_input_bind_group_layout)) = (
806 auxiliary_dof_texture,
807 view_bind_group_layouts.dual_input.as_ref(),
808 ) else {
809 {
static SHOULD_FIRE: ::bevy_utils::OnceFlag =
::bevy_utils::OnceFlag::new();
if SHOULD_FIRE.set() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/dof/mod.rs:809",
"bevy_post_process::dof", ::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("src/dof/mod.rs"),
::tracing_core::__macro_support::Option::Some(809u32),
::tracing_core::__macro_support::Option::Some("bevy_post_process::dof"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Should have created the auxiliary depth of field texture by now")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
}
};once!(warn!(
810 "Should have created the auxiliary depth of field texture by now"
811 ));
812 continue;
813 };
814 ctx.render_device().create_bind_group(
815 Some(pipeline_render_info.view_bind_group_label),
816 &pipeline_cache.get_bind_group_layout(dual_input_bind_group_layout),
817 &BindGroupEntries::sequential((
818 view_uniforms_binding,
819 view_depth_texture.view(),
820 postprocess.source,
821 &auxiliary_dof_texture.default_view,
822 )),
823 )
824 } else {
825 ctx.render_device().create_bind_group(
826 Some(pipeline_render_info.view_bind_group_label),
827 &pipeline_cache.get_bind_group_layout(&view_bind_group_layouts.single_input),
828 &BindGroupEntries::sequential((
829 view_uniforms_binding,
830 view_depth_texture.view(),
831 postprocess.source,
832 )),
833 )
834 };
835
836 let mut color_attachments: SmallVec<[_; 2]> = SmallVec::new();
838 color_attachments.push(Some(RenderPassColorAttachment {
839 view: postprocess.destination,
840 depth_slice: None,
841 resolve_target: None,
842 ops: Operations {
843 load: LoadOp::Clear(default()),
844 store: StoreOp::Store,
845 },
846 }));
847
848 if pipeline_render_info.is_dual_output {
853 let Some(auxiliary_dof_texture) = auxiliary_dof_texture else {
854 {
static SHOULD_FIRE: ::bevy_utils::OnceFlag =
::bevy_utils::OnceFlag::new();
if SHOULD_FIRE.set() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event src/dof/mod.rs:854",
"bevy_post_process::dof", ::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("src/dof/mod.rs"),
::tracing_core::__macro_support::Option::Some(854u32),
::tracing_core::__macro_support::Option::Some("bevy_post_process::dof"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Should have created the auxiliary depth of field texture by now")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
}
};once!(warn!(
855 "Should have created the auxiliary depth of field texture by now"
856 ));
857 continue;
858 };
859 color_attachments.push(Some(RenderPassColorAttachment {
860 view: &auxiliary_dof_texture.default_view,
861 depth_slice: None,
862 resolve_target: None,
863 ops: Operations {
864 load: LoadOp::Clear(default()),
865 store: StoreOp::Store,
866 },
867 }));
868 }
869
870 let render_pass_descriptor = RenderPassDescriptor {
871 label: Some(pipeline_render_info.pass_label),
872 color_attachments: &color_attachments,
873 ..default()
874 };
875
876 let mut render_pass = ctx
877 .command_encoder()
878 .begin_render_pass(&render_pass_descriptor);
879
880 render_pass.set_pipeline(render_pipeline);
881 render_pass.set_bind_group(0, &view_bind_group, &[view_uniform_offset.offset]);
883 render_pass.set_bind_group(
885 1,
886 global_bind_group,
887 &[depth_of_field_uniform_index.index()],
888 );
889 render_pass.draw(0..3, 0..1);
891 }
892}