From ae1fe650c6eeb955dcb838489259b1b4970ae457 Mon Sep 17 00:00:00 2001 From: Robin KAY Date: Sat, 14 Jan 2023 02:36:03 +0000 Subject: [PATCH] Merge pull request #9 from mxgrey/outline_render_layers_v0.2 Introduce OutlineRenderLayers for masking which views an outline appears on. --- src/draw.rs | 36 ++++++++++++++++++++++++++++-------- src/lib.rs | 15 +++++++++++++++ src/view_uniforms.rs | 14 ++++++++++---- 3 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/draw.rs b/src/draw.rs index c0cac71..7b9f947 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -3,7 +3,7 @@ use bevy::prelude::*; use bevy::render::render_asset::RenderAssets; use bevy::render::render_phase::{DrawFunctions, RenderPhase, SetItemPipeline}; use bevy::render::render_resource::{PipelineCache, SpecializedMeshPipelines}; -use bevy::render::view::ExtractedView; +use bevy::render::view::{ExtractedView, RenderLayers}; use crate::node::{OpaqueOutline, StencilOutline, TransparentOutline}; use crate::pipeline::{OutlinePipeline, PassType, PipelineKey}; @@ -12,6 +12,7 @@ use crate::uniforms::{ OutlineVolumeUniform, SetOutlineStencilBindGroup, SetOutlineVolumeBindGroup, }; use crate::view_uniforms::SetOutlineViewBindGroup; +use crate::OutlineRenderLayers; pub(crate) type DrawStencil = ( SetItemPipeline, @@ -22,7 +23,7 @@ pub(crate) type DrawStencil = ( DrawMesh, ); -#[allow(clippy::too_many_arguments)] +#[allow(clippy::too_many_arguments, clippy::type_complexity)] pub(crate) fn queue_outline_stencil_mesh( stencil_draw_functions: Res>, stencil_pipeline: Res, @@ -35,8 +36,13 @@ pub(crate) fn queue_outline_stencil_mesh( &Handle, &OutlineStencilUniform, &OutlineStencilFlags, + Option<&OutlineRenderLayers>, + )>, + mut views: Query<( + &ExtractedView, + &mut RenderPhase, + Option<&RenderLayers>, )>, - mut views: Query<(&ExtractedView, &mut RenderPhase)>, ) { let draw_stencil = stencil_draw_functions .read() @@ -47,9 +53,16 @@ pub(crate) fn queue_outline_stencil_mesh( .with_msaa_samples(msaa.samples) .with_pass_type(PassType::Stencil); - for (view, mut stencil_phase) in views.iter_mut() { + for (view, mut stencil_phase, view_mask) in views.iter_mut() { let rangefinder = view.rangefinder3d(); - for (entity, mesh_handle, stencil_uniform, stencil_flags) in material_meshes.iter() { + let view_mask = view_mask.copied().unwrap_or_default(); + for (entity, mesh_handle, stencil_uniform, stencil_flags, outline_mask) in + material_meshes.iter() + { + let outline_mask = outline_mask.copied().unwrap_or_default(); + if !view_mask.intersects(&outline_mask) { + continue; + } if let Some(mesh) = render_meshes.get(mesh_handle) { let key = base_key .with_primitive_topology(mesh.primitive_topology) @@ -80,7 +93,7 @@ pub(crate) type DrawOutline = ( DrawMesh, ); -#[allow(clippy::too_many_arguments)] +#[allow(clippy::too_many_arguments, clippy::type_complexity)] pub(crate) fn queue_outline_volume_mesh( opaque_draw_functions: Res>, transparent_draw_functions: Res>, @@ -95,11 +108,13 @@ pub(crate) fn queue_outline_volume_mesh( &OutlineVolumeUniform, &OutlineVolumeFlags, &OutlineFragmentUniform, + Option<&OutlineRenderLayers>, )>, mut views: Query<( &ExtractedView, &mut RenderPhase, &mut RenderPhase, + Option<&RenderLayers>, )>, ) { let draw_opaque_outline = opaque_draw_functions @@ -113,11 +128,16 @@ pub(crate) fn queue_outline_volume_mesh( let base_key = PipelineKey::new().with_msaa_samples(msaa.samples); - for (view, mut opaque_phase, mut transparent_phase) in views.iter_mut() { + for (view, mut opaque_phase, mut transparent_phase, view_mask) in views.iter_mut() { + let view_mask = view_mask.copied().unwrap_or_default(); let rangefinder = view.rangefinder3d(); - for (entity, mesh_handle, volume_uniform, volume_flags, fragment_uniform) in + for (entity, mesh_handle, volume_uniform, volume_flags, fragment_uniform, outline_mask) in material_meshes.iter() { + let outline_mask = outline_mask.copied().unwrap_or_default(); + if !view_mask.intersects(&outline_mask) { + continue; + } if let Some(mesh) = render_meshes.get(mesh_handle) { let transparent = fragment_uniform.colour[3] < 1.0; let key = base_key diff --git a/src/lib.rs b/src/lib.rs index 8fec0ba..99c01ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,7 @@ use bevy::render::mesh::MeshVertexAttribute; use bevy::render::render_graph::RenderGraph; use bevy::render::render_phase::{sort_phase_system, AddRenderCommand, DrawFunctions}; use bevy::render::render_resource::{SpecializedMeshPipelines, VertexFormat}; +use bevy::render::view::RenderLayers; use bevy::render::{RenderApp, RenderStage}; use bevy::transform::TransformSystem; use interpolation::Lerp; @@ -132,6 +133,19 @@ impl Lerp for OutlineVolume { } } +/// A component for specifying what layer(s) the outline should be rendered for. +#[derive(Component, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Deref, DerefMut, Default)] +pub struct OutlineRenderLayers(pub RenderLayers); + +impl ExtractComponent for OutlineRenderLayers { + type Query = &'static OutlineRenderLayers; + type Filter = (); + + fn extract_component(item: &OutlineRenderLayers) -> Self { + *item + } +} + /// A bundle for rendering stenciled outlines around meshes. #[derive(Bundle, Clone, Default)] pub struct OutlineBundle { @@ -166,6 +180,7 @@ impl Plugin for OutlinePlugin { ); app.add_plugin(ExtractComponentPlugin::::extract_visible()) + .add_plugin(ExtractComponentPlugin::::default()) .add_plugin(UniformComponentPlugin::::default()) .add_plugin(UniformComponentPlugin::::default()) .add_plugin(UniformComponentPlugin::::default()) diff --git a/src/view_uniforms.rs b/src/view_uniforms.rs index dd0e18c..4e579c5 100644 --- a/src/view_uniforms.rs +++ b/src/view_uniforms.rs @@ -8,6 +8,7 @@ use bevy::render::render_phase::{ use bevy::render::render_resource::ShaderType; use bevy::render::render_resource::{BindGroup, BindGroupDescriptor, BindGroupEntry}; use bevy::render::renderer::RenderDevice; +use bevy::render::view::RenderLayers; use bevy::render::Extract; use crate::node::{OpaqueOutline, StencilOutline, TransparentOutline}; @@ -24,21 +25,26 @@ pub(crate) struct OutlineViewBindGroup { bind_group: BindGroup, } +#[allow(clippy::type_complexity)] pub(crate) fn extract_outline_view_uniforms( mut commands: Commands, - query: Extract>>, + query: Extract), With>>, ) { - for (entity, camera) in query.iter() { + for (entity, camera, view_mask) in query.iter() { if !camera.is_active { continue; } if let Some(size) = camera.logical_viewport_size() { - commands - .get_or_spawn(entity) + let mut entity_commands = commands.get_or_spawn(entity); + entity_commands .insert(OutlineViewUniform { scale: 2.0 / size }) .insert(RenderPhase::::default()) .insert(RenderPhase::::default()) .insert(RenderPhase::::default()); + + if let Some(view_mask) = view_mask { + entity_commands.insert(*view_mask); + } } } }