Compare commits

...

10 Commits

Author SHA1 Message Date
Robin KAY
249a07f202 Fix clippy lint. 2024-03-03 00:43:16 +00:00
Robin KAY
ff99c20c77 Run outline pass after TAA if TAA plugin added first. 2024-03-02 22:54:02 +00:00
Robin KAY
c4d058c94e Revert back to using SetMeshViewBindGroup. 2024-03-02 22:32:29 +00:00
Robin KAY
72e8d73008 Rename LabelsOutline to NodeOutline and fix docs. 2024-03-01 23:06:40 +00:00
Robin KAY
8964bdf9d6 Upgrade base interpolation to 0.3 and remove interpolation_03 feature. 2024-03-01 21:31:12 +00:00
Robin KAY
76ecdc80b6 Update version and read-me for 0.7.0. 2024-03-01 21:22:37 +00:00
Robin KAY
66db3b8065 Temporarily disable MSAA in render_layers example pending Bevy 0.13.1. 2024-02-19 23:01:46 +00:00
Robin KAY
a78157a85b Update deps to 0.13 release. 2024-02-18 10:25:07 +00:00
Robin KAY
6f3f08a9e2 Fix formatting. 2024-02-17 00:02:07 +00:00
Robin KAY
76c802bf3e Update Bevy master commit hash. 2024-02-16 21:58:17 +00:00
9 changed files with 129 additions and 112 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "bevy_mod_outline" name = "bevy_mod_outline"
version = "0.6.2" version = "0.7.0"
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "A mesh outlining plugin for Bevy." description = "A mesh outlining plugin for Bevy."
@ -11,7 +11,7 @@ keywords = ["gamedev", "bevy", "outline"]
categories = ["game-engines", "rendering"] categories = ["game-engines", "rendering"]
[dependencies] [dependencies]
bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "4ebc560dfb0fee5d3728d1d8f7362f484b784e4c", default-features = false, features = [ bevy = { version = "0.13", default-features = false, features = [
"bevy_asset", "bevy_asset",
"bevy_render", "bevy_render",
"bevy_pbr", "bevy_pbr",
@ -21,13 +21,12 @@ bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "4ebc560dfb0fee5d
"bevy_core_pipeline", "bevy_core_pipeline",
] } ] }
bitfield = "0.14" bitfield = "0.14"
interpolation = "0.2" interpolation = "0.3"
interpolation_03 = { package = "interpolation", version = "0.3", optional = true }
thiserror = "1.0" thiserror = "1.0"
wgpu-types = "0.19" wgpu-types = "0.19"
[dev-dependencies] [dev-dependencies]
bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "4ebc560dfb0fee5d3728d1d8f7362f484b784e4c", default-features = false, features = [ bevy = { version = "0.13", default-features = false, features = [
"animation", "animation",
"bevy_gltf", "bevy_gltf",
"bevy_pbr", "bevy_pbr",

View File

@ -12,7 +12,7 @@ vertex extrusion method.
```toml ```toml
[dependencies] [dependencies]
bevy_mod_outline = "0.6" bevy_mod_outline = "0.7"
``` ```
## Examples ## Examples
@ -66,6 +66,7 @@ cargo run --example morph_targets
| This Version | Bevy version | | This Version | Bevy version |
|--------------|--------------| |--------------|--------------|
| 0.7.x | 0.13.x |
| 0.6.x | 0.12.x | | 0.6.x | 0.12.x |
| 0.5.x | 0.11.x | | 0.5.x | 0.11.x |
| 0.4.x | 0.10.x | | 0.4.x | 0.10.x |
@ -78,9 +79,6 @@ cargo run --example morph_targets
- `bevy_ui` _(default)_ - Adds a render graph edge to prevent clashing with the - `bevy_ui` _(default)_ - Adds a render graph edge to prevent clashing with the
UI. This adds a dependency on the `bevy_ui` crate and can be disabled if it is UI. This adds a dependency on the `bevy_ui` crate and can be disabled if it is
not used. not used.
- `interpolation_03` - Define `Lerp` trait impls using version 0.3 of the
`interpolation` crate in addition to 0.2. This will become the default in the
next breaking release.
## Licence ## Licence

View File

@ -10,7 +10,7 @@ use bevy_mod_outline::{OutlineBundle, OutlinePlugin, OutlineRenderLayers, Outlin
#[bevy_main] #[bevy_main]
fn main() { fn main() {
App::new() App::new()
.insert_resource(Msaa::Sample4) .insert_resource(Msaa::Off) // Disabled temporarily due to bevyengine/bevy#11968.
.insert_resource(ClearColor(Color::BLACK)) .insert_resource(ClearColor(Color::BLACK))
.add_plugins((DefaultPlugins, OutlinePlugin)) .add_plugins((DefaultPlugins, OutlinePlugin))
.add_systems(Startup, setup) .add_systems(Startup, setup)

View File

@ -1,4 +1,7 @@
use bevy::pbr::{DrawMesh, SetMeshBindGroup}; use bevy::core_pipeline::prepass::{
DeferredPrepass, DepthPrepass, MotionVectorPrepass, NormalPrepass,
};
use bevy::pbr::{DrawMesh, MeshPipelineViewLayoutKey, SetMeshBindGroup, SetMeshViewBindGroup};
use bevy::prelude::*; 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};
@ -16,12 +19,47 @@ use crate::OutlineRenderLayers;
pub(crate) type DrawStencil = ( pub(crate) type DrawStencil = (
SetItemPipeline, SetItemPipeline,
SetOutlineViewBindGroup<0>, SetMeshViewBindGroup<0>,
SetMeshBindGroup<1>, SetMeshBindGroup<1>,
SetOutlineStencilBindGroup<2>, SetOutlineViewBindGroup<2>,
SetOutlineStencilBindGroup<3>,
DrawMesh, DrawMesh,
); );
fn build_mesh_pipeline_view_layout_key(
msaa: Msaa,
(normal_prepass, depth_prepass, motion_vector_prepass, deferred_prepass): (
bool,
bool,
bool,
bool,
),
) -> MeshPipelineViewLayoutKey {
let mut view_key = MeshPipelineViewLayoutKey::empty();
if msaa != Msaa::Off {
view_key |= MeshPipelineViewLayoutKey::MULTISAMPLED;
}
if normal_prepass {
view_key |= MeshPipelineViewLayoutKey::NORMAL_PREPASS;
}
if depth_prepass {
view_key |= MeshPipelineViewLayoutKey::DEPTH_PREPASS;
}
if motion_vector_prepass {
view_key |= MeshPipelineViewLayoutKey::MOTION_VECTOR_PREPASS;
}
if deferred_prepass {
view_key |= MeshPipelineViewLayoutKey::DEFERRED_PREPASS;
}
view_key
}
#[allow(clippy::too_many_arguments, clippy::type_complexity)] #[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>>,
@ -40,6 +78,12 @@ pub(crate) fn queue_outline_stencil_mesh(
&ExtractedView, &ExtractedView,
&mut RenderPhase<StencilOutline>, &mut RenderPhase<StencilOutline>,
Option<&RenderLayers>, Option<&RenderLayers>,
(
Has<NormalPrepass>,
Has<DepthPrepass>,
Has<MotionVectorPrepass>,
Has<DeferredPrepass>,
),
)>, )>,
) { ) {
let draw_stencil = stencil_draw_functions let draw_stencil = stencil_draw_functions
@ -51,7 +95,7 @@ pub(crate) fn queue_outline_stencil_mesh(
.with_msaa(*msaa) .with_msaa(*msaa)
.with_pass_type(PassType::Stencil); .with_pass_type(PassType::Stencil);
for (view, mut stencil_phase, view_mask) in views.iter_mut() { for (view, mut stencil_phase, view_mask, prepasses) in views.iter_mut() {
let rangefinder = view.rangefinder3d(); let rangefinder = view.rangefinder3d();
let view_mask = view_mask.copied().unwrap_or_default(); let view_mask = view_mask.copied().unwrap_or_default();
for (entity, stencil_uniform, outline, outline_mask) in material_meshes.iter() { for (entity, stencil_uniform, outline, outline_mask) in material_meshes.iter() {
@ -65,7 +109,8 @@ pub(crate) fn queue_outline_stencil_mesh(
.with_primitive_topology(mesh.primitive_topology) .with_primitive_topology(mesh.primitive_topology)
.with_depth_mode(outline.depth_mode) .with_depth_mode(outline.depth_mode)
.with_offset_zero(stencil_uniform.offset == 0.0) .with_offset_zero(stencil_uniform.offset == 0.0)
.with_morph_targets(mesh.morph_targets.is_some()); .with_morph_targets(mesh.morph_targets.is_some())
.with_view_key(build_mesh_pipeline_view_layout_key(*msaa, prepasses));
let Ok(pipeline) = let Ok(pipeline) =
pipelines.specialize(&pipeline_cache, &stencil_pipeline, key, &mesh.layout) pipelines.specialize(&pipeline_cache, &stencil_pipeline, key, &mesh.layout)
else { else {
@ -86,9 +131,10 @@ pub(crate) fn queue_outline_stencil_mesh(
pub(crate) type DrawOutline = ( pub(crate) type DrawOutline = (
SetItemPipeline, SetItemPipeline,
SetOutlineViewBindGroup<0>, SetMeshViewBindGroup<0>,
SetMeshBindGroup<1>, SetMeshBindGroup<1>,
SetOutlineVolumeBindGroup<2>, SetOutlineViewBindGroup<2>,
SetOutlineVolumeBindGroup<3>,
DrawMesh, DrawMesh,
); );
@ -113,6 +159,12 @@ pub(crate) fn queue_outline_volume_mesh(
&mut RenderPhase<OpaqueOutline>, &mut RenderPhase<OpaqueOutline>,
&mut RenderPhase<TransparentOutline>, &mut RenderPhase<TransparentOutline>,
Option<&RenderLayers>, Option<&RenderLayers>,
(
Has<NormalPrepass>,
Has<DepthPrepass>,
Has<MotionVectorPrepass>,
Has<DeferredPrepass>,
),
)>, )>,
) { ) {
let draw_opaque_outline = opaque_draw_functions let draw_opaque_outline = opaque_draw_functions
@ -126,7 +178,7 @@ pub(crate) fn queue_outline_volume_mesh(
let base_key = PipelineKey::new().with_msaa(*msaa); let base_key = PipelineKey::new().with_msaa(*msaa);
for (view, mut opaque_phase, mut transparent_phase, view_mask) in views.iter_mut() { for (view, mut opaque_phase, mut transparent_phase, view_mask, prepasses) in views.iter_mut() {
let view_mask = view_mask.copied().unwrap_or_default(); let view_mask = view_mask.copied().unwrap_or_default();
let rangefinder = view.rangefinder3d(); let rangefinder = view.rangefinder3d();
for (entity, volume_uniform, outline, fragment_uniform, outline_mask) in for (entity, volume_uniform, outline, fragment_uniform, outline_mask) in
@ -149,7 +201,8 @@ pub(crate) fn queue_outline_volume_mesh(
.with_depth_mode(outline.depth_mode) .with_depth_mode(outline.depth_mode)
.with_offset_zero(volume_uniform.offset == 0.0) .with_offset_zero(volume_uniform.offset == 0.0)
.with_hdr_format(view.hdr) .with_hdr_format(view.hdr)
.with_morph_targets(mesh.morph_targets.is_some()); .with_morph_targets(mesh.morph_targets.is_some())
.with_view_key(build_mesh_pipeline_view_layout_key(*msaa, prepasses));
let Ok(pipeline) = let Ok(pipeline) =
pipelines.specialize(&pipeline_cache, &outline_pipeline, key, &mesh.layout) pipelines.specialize(&pipeline_cache, &outline_pipeline, key, &mesh.layout)
else { else {

View File

@ -11,7 +11,7 @@ struct OutlineFragmentUniform {
}; };
#ifdef VOLUME #ifdef VOLUME
@group(2) @binding(1) @group(3) @binding(1)
var<uniform> fstage: OutlineFragmentUniform; var<uniform> fstage: OutlineFragmentUniform;
#endif #endif

View File

@ -23,7 +23,7 @@
//! [`AutoGenerateOutlineNormalsPlugin`]. //! [`AutoGenerateOutlineNormalsPlugin`].
use bevy::asset::load_internal_asset; use bevy::asset::load_internal_asset;
use bevy::core_pipeline::core_3d::graph::{Labels3d, SubGraph3d}; use bevy::core_pipeline::core_3d::graph::{Core3d, Node3d};
use bevy::prelude::*; use bevy::prelude::*;
use bevy::render::batching::{batch_and_prepare_render_phase, write_batched_instance_buffer}; use bevy::render::batching::{batch_and_prepare_render_phase, write_batched_instance_buffer};
use bevy::render::extract_component::{ use bevy::render::extract_component::{
@ -36,7 +36,7 @@ use bevy::render::render_resource::{SpecializedMeshPipelines, VertexFormat};
use bevy::render::view::{RenderLayers, VisibilitySystems}; use bevy::render::view::{RenderLayers, VisibilitySystems};
use bevy::render::{Render, RenderApp, RenderSet}; use bevy::render::{Render, RenderApp, RenderSet};
use bevy::transform::TransformSystem; use bevy::transform::TransformSystem;
use bevy::ui::graph::LabelsUi; use bevy::ui::graph::NodeUi;
use interpolation::Lerp; use interpolation::Lerp;
use crate::draw::{ use crate::draw::{
@ -70,12 +70,10 @@ pub use generate::*;
pub const ATTRIBUTE_OUTLINE_NORMAL: MeshVertexAttribute = pub const ATTRIBUTE_OUTLINE_NORMAL: MeshVertexAttribute =
MeshVertexAttribute::new("Outline_Normal", 1585570526, VertexFormat::Float32x3); MeshVertexAttribute::new("Outline_Normal", 1585570526, VertexFormat::Float32x3);
/// Name of the render graph node which draws the outlines. /// Labels for render graph nodes which draw outlines.
///
/// This node runs after the main 3D passes and before the UI pass. The name can be used to
/// add additional constraints on node execution order with respect to other passes.
#[derive(Copy, Clone, Debug, RenderLabel, Hash, PartialEq, Eq)] #[derive(Copy, Clone, Debug, RenderLabel, Hash, PartialEq, Eq)]
pub enum LabelsOutline { pub enum NodeOutline {
/// This node runs after the main 3D passes and before the UI pass.
OutlinePass, OutlinePass,
} }
@ -118,15 +116,6 @@ impl Lerp for OutlineStencil {
} }
} }
#[cfg(feature = "interpolation_03")]
impl interpolation_03::Lerp for OutlineStencil {
type Scalar = f32;
fn lerp(&self, other: &Self, scalar: &Self::Scalar) -> Self {
<Self as Lerp>::lerp(self, other, scalar)
}
}
/// A component for rendering outlines around meshes. /// A component for rendering outlines around meshes.
#[derive(Clone, Component, Default)] #[derive(Clone, Component, Default)]
pub struct OutlineVolume { pub struct OutlineVolume {
@ -156,15 +145,6 @@ impl Lerp for OutlineVolume {
} }
} }
#[cfg(feature = "interpolation_03")]
impl interpolation_03::Lerp for OutlineVolume {
type Scalar = f32;
fn lerp(&self, other: &Self, scalar: &Self::Scalar) -> Self {
<Self as Lerp>::lerp(self, other, scalar)
}
}
/// A component for specifying what layer(s) the outline should be rendered for. /// A component for specifying what layer(s) the outline should be rendered for.
#[derive(Component, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Deref, DerefMut, Default)] #[derive(Component, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Deref, DerefMut, Default)]
pub struct OutlineRenderLayers(pub RenderLayers); pub struct OutlineRenderLayers(pub RenderLayers);
@ -324,13 +304,16 @@ impl Plugin for OutlinePlugin {
let mut graph = world.resource_mut::<RenderGraph>(); let mut graph = world.resource_mut::<RenderGraph>();
let draw_3d_graph = graph.get_sub_graph_mut(SubGraph3d).unwrap(); let draw_3d_graph = graph.get_sub_graph_mut(Core3d).unwrap();
draw_3d_graph.add_node(LabelsOutline::OutlinePass, node); draw_3d_graph.add_node(NodeOutline::OutlinePass, node);
// Run after main 3D pass, but before UI psss // Run after main 3D pass, but before UI psss
draw_3d_graph.add_node_edge(Labels3d::EndMainPass, LabelsOutline::OutlinePass); draw_3d_graph.add_node_edge(Node3d::EndMainPass, NodeOutline::OutlinePass);
if draw_3d_graph.get_node_state(Node3d::Taa).is_ok() {
draw_3d_graph.add_node_edge(Node3d::Taa, NodeOutline::OutlinePass);
}
#[cfg(feature = "bevy_ui")] #[cfg(feature = "bevy_ui")]
draw_3d_graph.add_node_edge(LabelsOutline::OutlinePass, LabelsUi::UiPass); draw_3d_graph.add_node_edge(NodeOutline::OutlinePass, NodeUi::UiPass);
} }
fn finish(&self, app: &mut App) { fn finish(&self, app: &mut App) {

View File

@ -42,14 +42,14 @@ struct OutlineVertexUniform {
@group(0) @binding(0) @group(0) @binding(0)
var<uniform> view: View; var<uniform> view: View;
@group(0) @binding(1)
var<uniform> view_uniform: OutlineViewUniform;
#import bevy_pbr::mesh_bindings #import bevy_pbr::mesh_bindings
#import bevy_pbr::skinning #import bevy_pbr::skinning
#import bevy_pbr::morph #import bevy_pbr::morph
@group(2) @binding(0) @group(2) @binding(0)
var<uniform> view_uniform: OutlineViewUniform;
@group(3) @binding(0)
var<uniform> vstage: OutlineVertexUniform; var<uniform> vstage: OutlineVertexUniform;
#ifdef MORPH_TARGETS #ifdef MORPH_TARGETS

View File

@ -3,7 +3,8 @@ use std::borrow::Cow;
use bevy::ecs::system::lifetimeless::SQuery; use bevy::ecs::system::lifetimeless::SQuery;
use bevy::ecs::system::SystemParamItem; use bevy::ecs::system::SystemParamItem;
use bevy::pbr::{ use bevy::pbr::{
setup_morph_and_skinning_defs, MeshFlags, MeshPipelineKey, MeshTransforms, MeshUniform, setup_morph_and_skinning_defs, MeshFlags, MeshPipelineKey, MeshPipelineViewLayoutKey,
MeshTransforms, MeshUniform,
}; };
use bevy::prelude::*; use bevy::prelude::*;
use bevy::render::batching::GetBatchData; use bevy::render::batching::GetBatchData;
@ -16,7 +17,7 @@ use bevy::render::render_resource::{
use bevy::render::renderer::RenderDevice; use bevy::render::renderer::RenderDevice;
use bevy::render::settings::WgpuSettings; use bevy::render::settings::WgpuSettings;
use bevy::render::texture::BevyDefault; use bevy::render::texture::BevyDefault;
use bevy::render::view::{ViewTarget, ViewUniform}; use bevy::render::view::ViewTarget;
use bevy::{ use bevy::{
pbr::MeshPipeline, pbr::MeshPipeline,
render::{ render::{
@ -63,6 +64,7 @@ impl PipelineKey {
pub offset_zero, set_offset_zero: 13; pub offset_zero, set_offset_zero: 13;
pub hdr_format, set_hdr_format: 14; pub hdr_format, set_hdr_format: 14;
pub morph_targets, set_morph_targets: 15; pub morph_targets, set_morph_targets: 15;
view_key_int, set_view_key_int: 23, 16;
} }
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
@ -141,6 +143,15 @@ impl PipelineKey {
self.set_morph_targets(morph_targets); self.set_morph_targets(morph_targets);
self self
} }
pub(crate) fn with_view_key(mut self, view_key: MeshPipelineViewLayoutKey) -> Self {
self.set_view_key_int(view_key.bits());
self
}
pub(crate) fn view_key(&self) -> MeshPipelineViewLayoutKey {
MeshPipelineViewLayoutKey::from_bits(self.view_key_int()).unwrap()
}
} }
impl From<PipelineKey> for MeshPipelineKey { impl From<PipelineKey> for MeshPipelineKey {
@ -168,28 +179,16 @@ impl FromWorld for OutlinePipeline {
let render_device = world.get_resource::<RenderDevice>().unwrap(); let render_device = world.get_resource::<RenderDevice>().unwrap();
let outline_view_bind_group_layout = render_device.create_bind_group_layout( let outline_view_bind_group_layout = render_device.create_bind_group_layout(
"outline_view_bind_group_layout", "outline_view_bind_group_layout",
&[ &[BindGroupLayoutEntry {
BindGroupLayoutEntry {
binding: 0, binding: 0,
visibility: ShaderStages::VERTEX, visibility: ShaderStages::VERTEX,
ty: BindingType::Buffer {
ty: BufferBindingType::Uniform,
has_dynamic_offset: true,
min_binding_size: Some(ViewUniform::min_size()),
},
count: None,
},
BindGroupLayoutEntry {
binding: 1,
visibility: ShaderStages::VERTEX,
ty: BindingType::Buffer { ty: BindingType::Buffer {
ty: BufferBindingType::Uniform, ty: BufferBindingType::Uniform,
has_dynamic_offset: true, has_dynamic_offset: true,
min_binding_size: Some(OutlineViewUniform::min_size()), min_binding_size: Some(OutlineViewUniform::min_size()),
}, },
count: None, count: None,
}, }],
],
); );
let outline_volume_bind_group_layout = render_device.create_bind_group_layout( let outline_volume_bind_group_layout = render_device.create_bind_group_layout(
"outline_volume_bind_group_layout", "outline_volume_bind_group_layout",
@ -258,16 +257,18 @@ impl SpecializedMeshPipeline for OutlinePipeline {
buffer_attrs.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0)); buffer_attrs.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0));
} }
let mut bind_layouts = vec![self.outline_view_bind_group_layout.clone()]; let mut bind_layouts = vec![
self.mesh_pipeline.get_view_layout(key.view_key()).clone(),
bind_layouts.push(setup_morph_and_skinning_defs( setup_morph_and_skinning_defs(
&self.mesh_pipeline.mesh_layouts, &self.mesh_pipeline.mesh_layouts,
layout, layout,
5, 5,
&key.into(), &key.into(),
&mut vertex_defs, &mut vertex_defs,
&mut buffer_attrs, &mut buffer_attrs,
)); ),
self.outline_view_bind_group_layout.clone(),
];
let cull_mode; let cull_mode;
if key.depth_mode() == DepthMode::Flat { if key.depth_mode() == DepthMode::Flat {

View File

@ -9,7 +9,7 @@ use bevy::render::render_phase::{
use bevy::render::render_resource::ShaderType; use bevy::render::render_resource::ShaderType;
use bevy::render::render_resource::{BindGroup, BindGroupEntry}; use bevy::render::render_resource::{BindGroup, BindGroupEntry};
use bevy::render::renderer::RenderDevice; use bevy::render::renderer::RenderDevice;
use bevy::render::view::{RenderLayers, ViewUniformOffset, ViewUniforms}; 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};
@ -54,26 +54,16 @@ pub(crate) fn prepare_outline_view_bind_group(
mut commands: Commands, mut commands: Commands,
render_device: Res<RenderDevice>, render_device: Res<RenderDevice>,
outline_pipeline: Res<OutlinePipeline>, outline_pipeline: Res<OutlinePipeline>,
core_view_uniforms: Res<ViewUniforms>, view_uniforms: Res<ComponentUniforms<OutlineViewUniform>>,
outline_view_uniforms: Res<ComponentUniforms<OutlineViewUniform>>,
) {
if let (Some(core_view_binding), Some(outline_view_binding)) = (
core_view_uniforms.uniforms.binding(),
outline_view_uniforms.binding(),
) { ) {
if let Some(view_binding) = view_uniforms.binding() {
let bind_group = render_device.create_bind_group( let bind_group = render_device.create_bind_group(
"outline_view_bind_group", "outline_view_bind_group",
&outline_pipeline.outline_view_bind_group_layout, &outline_pipeline.outline_view_bind_group_layout,
&[ &[BindGroupEntry {
BindGroupEntry {
binding: 0, binding: 0,
resource: core_view_binding.clone(), resource: view_binding.clone(),
}, }],
BindGroupEntry {
binding: 1,
resource: outline_view_binding.clone(),
},
],
); );
commands.insert_resource(OutlineViewBindGroup { bind_group }); commands.insert_resource(OutlineViewBindGroup { bind_group });
} }
@ -82,24 +72,17 @@ pub(crate) fn prepare_outline_view_bind_group(
pub(crate) struct SetOutlineViewBindGroup<const I: usize>(); pub(crate) struct SetOutlineViewBindGroup<const I: usize>();
impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetOutlineViewBindGroup<I> { impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetOutlineViewBindGroup<I> {
type ViewQuery = ( type ViewQuery = Read<DynamicUniformIndex<OutlineViewUniform>>;
Read<ViewUniformOffset>,
Read<DynamicUniformIndex<OutlineViewUniform>>,
);
type ItemQuery = (); type ItemQuery = ();
type Param = SRes<OutlineViewBindGroup>; type Param = SRes<OutlineViewBindGroup>;
fn render<'w>( fn render<'w>(
_item: &P, _item: &P,
(core_view_data, outline_view_data): ROQueryItem<'w, Self::ViewQuery>, view_data: ROQueryItem<'w, Self::ViewQuery>,
_entity_data: Option<()>, _entity_data: Option<()>,
bind_group: SystemParamItem<'w, '_, Self::Param>, bind_group: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>, pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult { ) -> RenderCommandResult {
pass.set_bind_group( pass.set_bind_group(I, &bind_group.into_inner().bind_group, &[view_data.index()]);
I,
&bind_group.into_inner().bind_group,
&[core_view_data.offset, outline_view_data.index()],
);
RenderCommandResult::Success RenderCommandResult::Success
} }
} }