Merge pull request #9 from mxgrey/outline_render_layers_v0.2
Introduce OutlineRenderLayers for masking which views an outline appears on.
This commit is contained in:
parent
cfd5d12261
commit
ae1fe650c6
36
src/draw.rs
36
src/draw.rs
@ -3,7 +3,7 @@ use bevy::prelude::*;
|
|||||||
use bevy::render::render_asset::RenderAssets;
|
use bevy::render::render_asset::RenderAssets;
|
||||||
use bevy::render::render_phase::{DrawFunctions, RenderPhase, SetItemPipeline};
|
use bevy::render::render_phase::{DrawFunctions, RenderPhase, SetItemPipeline};
|
||||||
use bevy::render::render_resource::{PipelineCache, SpecializedMeshPipelines};
|
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::node::{OpaqueOutline, StencilOutline, TransparentOutline};
|
||||||
use crate::pipeline::{OutlinePipeline, PassType, PipelineKey};
|
use crate::pipeline::{OutlinePipeline, PassType, PipelineKey};
|
||||||
@ -12,6 +12,7 @@ use crate::uniforms::{
|
|||||||
OutlineVolumeUniform, SetOutlineStencilBindGroup, SetOutlineVolumeBindGroup,
|
OutlineVolumeUniform, SetOutlineStencilBindGroup, SetOutlineVolumeBindGroup,
|
||||||
};
|
};
|
||||||
use crate::view_uniforms::SetOutlineViewBindGroup;
|
use crate::view_uniforms::SetOutlineViewBindGroup;
|
||||||
|
use crate::OutlineRenderLayers;
|
||||||
|
|
||||||
pub(crate) type DrawStencil = (
|
pub(crate) type DrawStencil = (
|
||||||
SetItemPipeline,
|
SetItemPipeline,
|
||||||
@ -22,7 +23,7 @@ pub(crate) type DrawStencil = (
|
|||||||
DrawMesh,
|
DrawMesh,
|
||||||
);
|
);
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
||||||
pub(crate) fn queue_outline_stencil_mesh(
|
pub(crate) fn queue_outline_stencil_mesh(
|
||||||
stencil_draw_functions: Res<DrawFunctions<StencilOutline>>,
|
stencil_draw_functions: Res<DrawFunctions<StencilOutline>>,
|
||||||
stencil_pipeline: Res<OutlinePipeline>,
|
stencil_pipeline: Res<OutlinePipeline>,
|
||||||
@ -35,8 +36,13 @@ pub(crate) fn queue_outline_stencil_mesh(
|
|||||||
&Handle<Mesh>,
|
&Handle<Mesh>,
|
||||||
&OutlineStencilUniform,
|
&OutlineStencilUniform,
|
||||||
&OutlineStencilFlags,
|
&OutlineStencilFlags,
|
||||||
|
Option<&OutlineRenderLayers>,
|
||||||
|
)>,
|
||||||
|
mut views: Query<(
|
||||||
|
&ExtractedView,
|
||||||
|
&mut RenderPhase<StencilOutline>,
|
||||||
|
Option<&RenderLayers>,
|
||||||
)>,
|
)>,
|
||||||
mut views: Query<(&ExtractedView, &mut RenderPhase<StencilOutline>)>,
|
|
||||||
) {
|
) {
|
||||||
let draw_stencil = stencil_draw_functions
|
let draw_stencil = stencil_draw_functions
|
||||||
.read()
|
.read()
|
||||||
@ -47,9 +53,16 @@ pub(crate) fn queue_outline_stencil_mesh(
|
|||||||
.with_msaa_samples(msaa.samples)
|
.with_msaa_samples(msaa.samples)
|
||||||
.with_pass_type(PassType::Stencil);
|
.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();
|
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) {
|
if let Some(mesh) = render_meshes.get(mesh_handle) {
|
||||||
let key = base_key
|
let key = base_key
|
||||||
.with_primitive_topology(mesh.primitive_topology)
|
.with_primitive_topology(mesh.primitive_topology)
|
||||||
@ -80,7 +93,7 @@ pub(crate) type DrawOutline = (
|
|||||||
DrawMesh,
|
DrawMesh,
|
||||||
);
|
);
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
||||||
pub(crate) fn queue_outline_volume_mesh(
|
pub(crate) fn queue_outline_volume_mesh(
|
||||||
opaque_draw_functions: Res<DrawFunctions<OpaqueOutline>>,
|
opaque_draw_functions: Res<DrawFunctions<OpaqueOutline>>,
|
||||||
transparent_draw_functions: Res<DrawFunctions<TransparentOutline>>,
|
transparent_draw_functions: Res<DrawFunctions<TransparentOutline>>,
|
||||||
@ -95,11 +108,13 @@ pub(crate) fn queue_outline_volume_mesh(
|
|||||||
&OutlineVolumeUniform,
|
&OutlineVolumeUniform,
|
||||||
&OutlineVolumeFlags,
|
&OutlineVolumeFlags,
|
||||||
&OutlineFragmentUniform,
|
&OutlineFragmentUniform,
|
||||||
|
Option<&OutlineRenderLayers>,
|
||||||
)>,
|
)>,
|
||||||
mut views: Query<(
|
mut views: Query<(
|
||||||
&ExtractedView,
|
&ExtractedView,
|
||||||
&mut RenderPhase<OpaqueOutline>,
|
&mut RenderPhase<OpaqueOutline>,
|
||||||
&mut RenderPhase<TransparentOutline>,
|
&mut RenderPhase<TransparentOutline>,
|
||||||
|
Option<&RenderLayers>,
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
let draw_opaque_outline = opaque_draw_functions
|
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);
|
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();
|
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()
|
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) {
|
if let Some(mesh) = render_meshes.get(mesh_handle) {
|
||||||
let transparent = fragment_uniform.colour[3] < 1.0;
|
let transparent = fragment_uniform.colour[3] < 1.0;
|
||||||
let key = base_key
|
let key = base_key
|
||||||
|
15
src/lib.rs
15
src/lib.rs
@ -30,6 +30,7 @@ use bevy::render::mesh::MeshVertexAttribute;
|
|||||||
use bevy::render::render_graph::RenderGraph;
|
use bevy::render::render_graph::RenderGraph;
|
||||||
use bevy::render::render_phase::{sort_phase_system, AddRenderCommand, DrawFunctions};
|
use bevy::render::render_phase::{sort_phase_system, AddRenderCommand, DrawFunctions};
|
||||||
use bevy::render::render_resource::{SpecializedMeshPipelines, VertexFormat};
|
use bevy::render::render_resource::{SpecializedMeshPipelines, VertexFormat};
|
||||||
|
use bevy::render::view::RenderLayers;
|
||||||
use bevy::render::{RenderApp, RenderStage};
|
use bevy::render::{RenderApp, RenderStage};
|
||||||
use bevy::transform::TransformSystem;
|
use bevy::transform::TransformSystem;
|
||||||
use interpolation::Lerp;
|
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.
|
/// A bundle for rendering stenciled outlines around meshes.
|
||||||
#[derive(Bundle, Clone, Default)]
|
#[derive(Bundle, Clone, Default)]
|
||||||
pub struct OutlineBundle {
|
pub struct OutlineBundle {
|
||||||
@ -166,6 +180,7 @@ impl Plugin for OutlinePlugin {
|
|||||||
);
|
);
|
||||||
|
|
||||||
app.add_plugin(ExtractComponentPlugin::<OutlineStencil>::extract_visible())
|
app.add_plugin(ExtractComponentPlugin::<OutlineStencil>::extract_visible())
|
||||||
|
.add_plugin(ExtractComponentPlugin::<OutlineRenderLayers>::default())
|
||||||
.add_plugin(UniformComponentPlugin::<OutlineStencilUniform>::default())
|
.add_plugin(UniformComponentPlugin::<OutlineStencilUniform>::default())
|
||||||
.add_plugin(UniformComponentPlugin::<OutlineVolumeUniform>::default())
|
.add_plugin(UniformComponentPlugin::<OutlineVolumeUniform>::default())
|
||||||
.add_plugin(UniformComponentPlugin::<OutlineFragmentUniform>::default())
|
.add_plugin(UniformComponentPlugin::<OutlineFragmentUniform>::default())
|
||||||
|
@ -8,6 +8,7 @@ use bevy::render::render_phase::{
|
|||||||
use bevy::render::render_resource::ShaderType;
|
use bevy::render::render_resource::ShaderType;
|
||||||
use bevy::render::render_resource::{BindGroup, BindGroupDescriptor, BindGroupEntry};
|
use bevy::render::render_resource::{BindGroup, BindGroupDescriptor, BindGroupEntry};
|
||||||
use bevy::render::renderer::RenderDevice;
|
use bevy::render::renderer::RenderDevice;
|
||||||
|
use bevy::render::view::RenderLayers;
|
||||||
use bevy::render::Extract;
|
use bevy::render::Extract;
|
||||||
|
|
||||||
use crate::node::{OpaqueOutline, StencilOutline, TransparentOutline};
|
use crate::node::{OpaqueOutline, StencilOutline, TransparentOutline};
|
||||||
@ -24,21 +25,26 @@ pub(crate) struct OutlineViewBindGroup {
|
|||||||
bind_group: BindGroup,
|
bind_group: BindGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
pub(crate) fn extract_outline_view_uniforms(
|
pub(crate) fn extract_outline_view_uniforms(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
query: Extract<Query<(Entity, &Camera), With<Camera3d>>>,
|
query: Extract<Query<(Entity, &Camera, Option<&RenderLayers>), With<Camera3d>>>,
|
||||||
) {
|
) {
|
||||||
for (entity, camera) in query.iter() {
|
for (entity, camera, view_mask) in query.iter() {
|
||||||
if !camera.is_active {
|
if !camera.is_active {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(size) = camera.logical_viewport_size() {
|
if let Some(size) = camera.logical_viewport_size() {
|
||||||
commands
|
let mut entity_commands = commands.get_or_spawn(entity);
|
||||||
.get_or_spawn(entity)
|
entity_commands
|
||||||
.insert(OutlineViewUniform { scale: 2.0 / size })
|
.insert(OutlineViewUniform { scale: 2.0 / size })
|
||||||
.insert(RenderPhase::<StencilOutline>::default())
|
.insert(RenderPhase::<StencilOutline>::default())
|
||||||
.insert(RenderPhase::<OpaqueOutline>::default())
|
.insert(RenderPhase::<OpaqueOutline>::default())
|
||||||
.insert(RenderPhase::<TransparentOutline>::default());
|
.insert(RenderPhase::<TransparentOutline>::default());
|
||||||
|
|
||||||
|
if let Some(view_mask) = view_mask {
|
||||||
|
entity_commands.insert(*view_mask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user