Add offset field to OutlineStencil and offset_zero flag to pipeline key.

This commit is contained in:
Robin KAY 2022-11-21 20:32:25 +00:00
parent 5898d7c17c
commit 59d867bf1f
5 changed files with 52 additions and 26 deletions

View File

@ -53,6 +53,7 @@ fn setup(
colour: Color::WHITE, colour: Color::WHITE,
width: 10.0, width: 10.0,
}, },
stencil: OutlineStencil { offset: 5.0 },
..default() ..default()
}) })
.insert(Rotates) .insert(Rotates)
@ -81,6 +82,7 @@ fn setup(
colour: Color::WHITE, colour: Color::WHITE,
width: 10.0, width: 10.0,
}, },
stencil: OutlineStencil { offset: 5.0 },
..default() ..default()
}) })
.insert(InheritOutlineDepth); .insert(InheritOutlineDepth);
@ -106,6 +108,7 @@ fn setup(
colour: Color::WHITE, colour: Color::WHITE,
width: 10.0, width: 10.0,
}, },
stencil: OutlineStencil { offset: 5.0 },
..default() ..default()
}) })
.insert(InheritOutlineDepth); .insert(InheritOutlineDepth);

View File

@ -8,10 +8,10 @@ use bevy::render::view::ExtractedView;
use crate::node::{OpaqueOutline, StencilOutline, TransparentOutline}; use crate::node::{OpaqueOutline, StencilOutline, TransparentOutline};
use crate::pipeline::{OutlinePipeline, PassType, PipelineKey}; use crate::pipeline::{OutlinePipeline, PassType, PipelineKey};
use crate::uniforms::{ use crate::uniforms::{
OutlineFragmentUniform, SetOutlineStencilBindGroup, SetOutlineVolumeBindGroup, OutlineFragmentUniform, OutlineStencilUniform, OutlineVolumeUniform,
SetOutlineStencilBindGroup, SetOutlineVolumeBindGroup,
}; };
use crate::view_uniforms::SetOutlineViewBindGroup; use crate::view_uniforms::SetOutlineViewBindGroup;
use crate::OutlineStencil;
pub type DrawStencil = ( pub type DrawStencil = (
SetItemPipeline, SetItemPipeline,
@ -30,7 +30,7 @@ pub fn queue_outline_stencil_mesh(
mut pipelines: ResMut<SpecializedMeshPipelines<OutlinePipeline>>, mut pipelines: ResMut<SpecializedMeshPipelines<OutlinePipeline>>,
mut pipeline_cache: ResMut<PipelineCache>, mut pipeline_cache: ResMut<PipelineCache>,
render_meshes: Res<RenderAssets<Mesh>>, render_meshes: Res<RenderAssets<Mesh>>,
material_meshes: Query<(Entity, &MeshUniform, &Handle<Mesh>), With<OutlineStencil>>, material_meshes: Query<(Entity, &MeshUniform, &Handle<Mesh>, &OutlineStencilUniform)>,
mut views: Query<(&ExtractedView, &mut RenderPhase<StencilOutline>)>, mut views: Query<(&ExtractedView, &mut RenderPhase<StencilOutline>)>,
) { ) {
let draw_stencil = stencil_draw_functions let draw_stencil = stencil_draw_functions
@ -44,9 +44,11 @@ pub fn queue_outline_stencil_mesh(
for (view, mut stencil_phase) in views.iter_mut() { for (view, mut stencil_phase) in views.iter_mut() {
let rangefinder = view.rangefinder3d(); let rangefinder = view.rangefinder3d();
for (entity, mesh_uniform, mesh_handle) in material_meshes.iter() { for (entity, mesh_uniform, mesh_handle, stencil_uniform) in material_meshes.iter() {
if let Some(mesh) = render_meshes.get(mesh_handle) { if let Some(mesh) = render_meshes.get(mesh_handle) {
let key = base_key.with_primitive_topology(mesh.primitive_topology); let key = base_key
.with_primitive_topology(mesh.primitive_topology)
.with_offset_zero(stencil_uniform.offset == 0.0);
let pipeline = pipelines let pipeline = pipelines
.specialize(&mut pipeline_cache, &stencil_pipeline, key, &mesh.layout) .specialize(&mut pipeline_cache, &stencil_pipeline, key, &mesh.layout)
.unwrap(); .unwrap();
@ -80,7 +82,13 @@ pub fn queue_outline_volume_mesh(
mut pipelines: ResMut<SpecializedMeshPipelines<OutlinePipeline>>, mut pipelines: ResMut<SpecializedMeshPipelines<OutlinePipeline>>,
mut pipeline_cache: ResMut<PipelineCache>, mut pipeline_cache: ResMut<PipelineCache>,
render_meshes: Res<RenderAssets<Mesh>>, render_meshes: Res<RenderAssets<Mesh>>,
material_meshes: Query<(Entity, &MeshUniform, &Handle<Mesh>, &OutlineFragmentUniform)>, material_meshes: Query<(
Entity,
&MeshUniform,
&Handle<Mesh>,
&OutlineVolumeUniform,
&OutlineFragmentUniform,
)>,
mut views: Query<( mut views: Query<(
&ExtractedView, &ExtractedView,
&mut RenderPhase<OpaqueOutline>, &mut RenderPhase<OpaqueOutline>,
@ -100,16 +108,19 @@ pub fn queue_outline_volume_mesh(
for (view, mut opaque_phase, mut transparent_phase) in views.iter_mut() { for (view, mut opaque_phase, mut transparent_phase) in views.iter_mut() {
let rangefinder = view.rangefinder3d(); let rangefinder = view.rangefinder3d();
for (entity, mesh_uniform, mesh_handle, outline_fragment) in material_meshes.iter() { for (entity, mesh_uniform, mesh_handle, volume_uniform, fragment_uniform) in
material_meshes.iter()
{
if let Some(mesh) = render_meshes.get(mesh_handle) { if let Some(mesh) = render_meshes.get(mesh_handle) {
let transparent = outline_fragment.colour[3] < 1.0; let transparent = fragment_uniform.colour[3] < 1.0;
let key = base_key let key = base_key
.with_primitive_topology(mesh.primitive_topology) .with_primitive_topology(mesh.primitive_topology)
.with_pass_type(if transparent { .with_pass_type(if transparent {
PassType::Transparent PassType::Transparent
} else { } else {
PassType::Opaque PassType::Opaque
}); })
.with_offset_zero(volume_uniform.offset == 0.0);
let pipeline = pipelines let pipeline = pipelines
.specialize(&mut pipeline_cache, &outline_pipeline, key, &mesh.layout) .specialize(&mut pipeline_cache, &outline_pipeline, key, &mesh.layout)
.unwrap(); .unwrap();

View File

@ -67,14 +67,17 @@ pub const OUTLINE_PASS_NODE_NAME: &str = "bevy_mod_outline_node";
/// A component for stenciling meshes during outline rendering. /// A component for stenciling meshes during outline rendering.
#[derive(Clone, Component, Default)] #[derive(Clone, Component, Default)]
pub struct OutlineStencil; pub struct OutlineStencil {
/// Offset of the stencil in logical pixels
pub offset: f32,
}
impl ExtractComponent for OutlineStencil { impl ExtractComponent for OutlineStencil {
type Query = (); type Query = &'static OutlineStencil;
type Filter = With<OutlineStencil>; type Filter = ();
fn extract_component(_item: QueryItem<Self::Query>) -> Self { fn extract_component(item: QueryItem<Self::Query>) -> Self {
OutlineStencil item.clone()
} }
} }

View File

@ -49,6 +49,7 @@ impl PipelineKey {
msaa_samples_minus_one, set_msaa_samples_minus_one: 5, 0; msaa_samples_minus_one, set_msaa_samples_minus_one: 5, 0;
primitive_topology_int, set_primitive_topology_int: 8, 6; primitive_topology_int, set_primitive_topology_int: 8, 6;
pass_type_int, set_pass_type_int: 10, 9; pass_type_int, set_pass_type_int: 10, 9;
pub offset_zero, set_offset_zero: 11;
} }
pub fn new() -> Self { pub fn new() -> Self {
@ -93,6 +94,11 @@ impl PipelineKey {
x => panic!("Invalid value for PassType: {}", x), x => panic!("Invalid value for PassType: {}", x),
} }
} }
pub fn with_offset_zero(mut self, offset_zero: bool) -> Self {
self.set_offset_zero(offset_zero);
self
}
} }
pub struct OutlinePipeline { pub struct OutlinePipeline {
@ -200,9 +206,20 @@ impl SpecializedMeshPipeline for OutlinePipeline {
}, },
); );
bind_layouts.push(self.outline_view_bind_group_layout.clone()); bind_layouts.push(self.outline_view_bind_group_layout.clone());
if key.offset_zero() {
vertex_defs.push("OFFSET_ZERO".to_string());
} else {
buffer_attrs.push(
if mesh_layout.contains(ATTRIBUTE_OUTLINE_NORMAL) {
ATTRIBUTE_OUTLINE_NORMAL
} else {
Mesh::ATTRIBUTE_NORMAL
}
.at_shader_location(1),
);
}
match key.pass_type() { match key.pass_type() {
PassType::Stencil => { PassType::Stencil => {
vertex_defs.push("OFFSET_ZERO".to_string());
bind_layouts.push(self.outline_stencil_bind_group_layout.clone()); bind_layouts.push(self.outline_stencil_bind_group_layout.clone());
} }
PassType::Opaque | PassType::Transparent => { PassType::Opaque | PassType::Transparent => {
@ -218,14 +235,6 @@ impl SpecializedMeshPipeline for OutlinePipeline {
})); }));
bind_layouts.push(self.outline_volume_bind_group_layout.clone()); bind_layouts.push(self.outline_volume_bind_group_layout.clone());
buffer_attrs.push(
if mesh_layout.contains(ATTRIBUTE_OUTLINE_NORMAL) {
ATTRIBUTE_OUTLINE_NORMAL
} else {
Mesh::ATTRIBUTE_NORMAL
}
.at_shader_location(1),
);
} }
} }
let buffers = vec![mesh_layout.get_layout(&buffer_attrs)?]; let buffers = vec![mesh_layout.get_layout(&buffer_attrs)?];

View File

@ -45,12 +45,12 @@ pub struct OutlineVolumeBindGroup {
pub fn extract_outline_stencil_uniforms( pub fn extract_outline_stencil_uniforms(
mut commands: Commands, mut commands: Commands,
query: Extract<Query<(Entity, &ComputedOutlineDepth), With<OutlineStencil>>>, query: Extract<Query<(Entity, &OutlineStencil, &ComputedOutlineDepth)>>,
) { ) {
for (entity, computed) in query.iter() { for (entity, stencil, computed) in query.iter() {
commands.get_or_spawn(entity).insert(OutlineStencilUniform { commands.get_or_spawn(entity).insert(OutlineStencilUniform {
origin: computed.origin, origin: computed.origin,
offset: 0.0, offset: stencil.offset,
}); });
} }
} }