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_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<DrawFunctions<StencilOutline>>,
|
||||
stencil_pipeline: Res<OutlinePipeline>,
|
||||
|
@ -35,8 +36,13 @@ pub(crate) fn queue_outline_stencil_mesh(
|
|||
&Handle<Mesh>,
|
||||
&OutlineStencilUniform,
|
||||
&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
|
||||
.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<DrawFunctions<OpaqueOutline>>,
|
||||
transparent_draw_functions: Res<DrawFunctions<TransparentOutline>>,
|
||||
|
@ -95,11 +108,13 @@ pub(crate) fn queue_outline_volume_mesh(
|
|||
&OutlineVolumeUniform,
|
||||
&OutlineVolumeFlags,
|
||||
&OutlineFragmentUniform,
|
||||
Option<&OutlineRenderLayers>,
|
||||
)>,
|
||||
mut views: Query<(
|
||||
&ExtractedView,
|
||||
&mut RenderPhase<OpaqueOutline>,
|
||||
&mut RenderPhase<TransparentOutline>,
|
||||
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
|
||||
|
|
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_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::<OutlineStencil>::extract_visible())
|
||||
.add_plugin(ExtractComponentPlugin::<OutlineRenderLayers>::default())
|
||||
.add_plugin(UniformComponentPlugin::<OutlineStencilUniform>::default())
|
||||
.add_plugin(UniformComponentPlugin::<OutlineVolumeUniform>::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::{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<(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 {
|
||||
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::<StencilOutline>::default())
|
||||
.insert(RenderPhase::<OpaqueOutline>::default())
|
||||
.insert(RenderPhase::<TransparentOutline>::default());
|
||||
|
||||
if let Some(view_mask) = view_mask {
|
||||
entity_commands.insert(*view_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue