Add offset field to OutlineStencil and offset_zero flag to pipeline key.
This commit is contained in:
parent
5898d7c17c
commit
59d867bf1f
@ -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);
|
||||||
|
29
src/draw.rs
29
src/draw.rs
@ -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();
|
||||||
|
13
src/lib.rs
13
src/lib.rs
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)?];
|
||||||
|
@ -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,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user