diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components.rs | 22 | ||||
-rw-r--r-- | src/lib.rs | 21 | ||||
-rw-r--r-- | src/nodes.rs | 7 | ||||
-rw-r--r-- | src/resources.rs | 6 |
4 files changed, 41 insertions, 15 deletions
diff --git a/src/components.rs b/src/components.rs index 22de86c..bdce6c9 100644 --- a/src/components.rs +++ b/src/components.rs @@ -1,7 +1,7 @@ use bevy::{ + core_pipeline::prepass::{DeferredPrepass, DepthPrepass, NormalPrepass}, prelude::*, render::{extract_component::ExtractComponent, render_resource::ShaderType}, - core_pipeline::prepass::{NormalPrepass, DepthPrepass, DeferredPrepass}, }; /// Component which, when inserted into an entity with a camera and normal prepass, enables an outline effect for that @@ -14,20 +14,29 @@ pub struct OutlinePostProcessSettings { /// A threshold for normal differences, values below this threshold will not become outlines. /// Higher values will result in more outlines which may look better on smooth surfaces. normal_threshold: f32, + /// A threshold for depth differences (in units), values below this threshold will not become outlines. + /// Higher values will result in more outlines which may look better on smooth surfaces. + depth_threshold: f32, /// Whether to use adaptive outlines. White outlines will be drawn around darker objects, while black ones will be drawn around lighter ones. adaptive: u32, - /// Threshold of illumination for outlines to apply. Requires deferred prepass. - light_threshold: f32, + /// Near plane depth of camera, used for linearization of depth buffer values + pub(crate) camera_near: f32, } impl OutlinePostProcessSettings { /// Create a new instance with the given settings - pub fn new(weight: f32, normal_threshold: f32, adaptive: bool, light_threshold: f32) -> Self { + pub fn new( + weight: f32, + normal_threshold: f32, + depth_threshold: f32, + adaptive: bool, + ) -> Self { Self { weight, normal_threshold, adaptive: adaptive as u32, - light_threshold, + depth_threshold, + camera_near: 0.0, } } } @@ -38,7 +47,8 @@ impl Default for OutlinePostProcessSettings { weight: 1.0, normal_threshold: 0.0, adaptive: 0, - light_threshold: 0.0, + depth_threshold: 0.05, + camera_near: 0.0, } } } @@ -1,7 +1,7 @@ #![warn(missing_docs)] //! A plugin for the Bevy game engine which provides an outline post-process effect. The effect -//! makes use of a normal prepass to generate outlines where differences in the normal buffer +//! makes use of a normal and depth prepass to generate outlines where significant differences in the values //! occur. use bevy::{ @@ -9,12 +9,11 @@ use bevy::{ core_pipeline::core_3d::graph::{Core3d, Node3d}, prelude::*, render::{ - extract_component::{ExtractComponentPlugin, UniformComponentPlugin}, - render_graph::{RenderGraphApp, ViewNodeRunner}, - RenderApp, + extract_component::{ExtractComponentPlugin, UniformComponentPlugin}, render_graph::{RenderGraphApp, ViewNodeRunner}, RenderApp }, }; +use components::OutlinePostProcessSettings; pub use nodes::OutlineRenderLabel; /// Components used by this plugin. @@ -32,7 +31,7 @@ impl Plugin for OutlinePostProcessPlugin { app.add_plugins(( UniformComponentPlugin::<components::OutlinePostProcessSettings>::default(), ExtractComponentPlugin::<components::OutlinePostProcessSettings>::default(), - )); + )).add_systems(Update, update_shader_clip_planes); let Some(render_app) = app.get_sub_app_mut(RenderApp) else { return; @@ -61,3 +60,15 @@ impl Plugin for OutlinePostProcessPlugin { render_app.init_resource::<resources::OutlinePostProcessPipeline>(); } } + +fn update_shader_clip_planes( + mut settings_query: Query<(Ref<Projection>, &mut OutlinePostProcessSettings)>, +) { + for (projection, mut settings) in settings_query.iter_mut() { + if projection.is_changed() { + if let Projection::Perspective(projection) = projection.into_inner() { + settings.camera_near = projection.near; + } + } + } +} diff --git a/src/nodes.rs b/src/nodes.rs index 1c750c7..b2b4a22 100644 --- a/src/nodes.rs +++ b/src/nodes.rs @@ -57,8 +57,8 @@ impl ViewNode for OutlineRenderNode { return Ok(()); }; - let Some(deferred_buffer_view) = view_prepass_textures.deferred_view() else { - error!("Failed to get deferred buffer view"); + let Some(depth_buffer_view) = view_prepass_textures.depth_view() else { + error!("Failed to get normal buffer view"); return Ok(()); }; @@ -72,7 +72,8 @@ impl ViewNode for OutlineRenderNode { &render_pipeline.screen_sampler, normal_buffer_view, &render_pipeline.normal_sampler, - deferred_buffer_view, + depth_buffer_view, + &render_pipeline.depth_sampler, uniform_binding, )), ); diff --git a/src/resources.rs b/src/resources.rs index 072b21c..4460558 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -20,6 +20,7 @@ pub struct OutlinePostProcessPipeline { pub layout: BindGroupLayout, pub screen_sampler: Sampler, pub normal_sampler: Sampler, + pub depth_sampler: Sampler, pub pipeline_id: CachedRenderPipelineId, } @@ -36,7 +37,8 @@ impl FromWorld for OutlinePostProcessPipeline { sampler(SamplerBindingType::Filtering), texture_2d(TextureSampleType::Float { filterable: true }), sampler(SamplerBindingType::Filtering), - texture_2d(TextureSampleType::Uint), + texture_2d(TextureSampleType::Depth), + sampler(SamplerBindingType::NonFiltering), uniform_buffer::<components::OutlinePostProcessSettings>(false), ), ), @@ -44,6 +46,7 @@ impl FromWorld for OutlinePostProcessPipeline { let screen_sampler = render_device.create_sampler(&SamplerDescriptor::default()); let normal_sampler = render_device.create_sampler(&SamplerDescriptor::default()); + let depth_sampler = render_device.create_sampler(&SamplerDescriptor::default()); let shader = world.resource::<AssetServer>().load::<Shader>( "embedded://bevy_outline_post_process/../assets/shaders/outline_post_process.wgsl", @@ -77,6 +80,7 @@ impl FromWorld for OutlinePostProcessPipeline { layout, screen_sampler, normal_sampler, + depth_sampler, pipeline_id, } } |