From fffb75b20c04955760017b9741adebdb544b764c Mon Sep 17 00:00:00 2001 From: Robin KAY Date: Fri, 16 Feb 2024 00:30:51 +0000 Subject: [PATCH] Initial port to Bevy 0.13. --- Cargo.toml | 6 +- examples/animated_fox.rs | 2 +- examples/flying_objects.rs | 21 +++--- examples/pieces.rs | 55 ++++++-------- examples/render_layers.rs | 15 ++-- examples/shapes.rs | 6 +- src/computed.rs | 44 ++++++----- src/lib.rs | 33 ++++----- src/node.rs | 30 ++++---- src/pipeline.rs | 146 ++++++++++++++++++------------------- src/uniforms.rs | 23 +++--- src/view_uniforms.rs | 8 +- 12 files changed, 188 insertions(+), 201 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5924182..af24399 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["gamedev", "bevy", "outline"] categories = ["game-engines", "rendering"] [dependencies] -bevy = { version = "0.12", default-features = false, features = [ +bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "4ebc560dfb0fee5d3728d1d8f7362f484b784e4c", default-features = false, features = [ "bevy_asset", "bevy_render", "bevy_pbr", @@ -24,10 +24,10 @@ bitfield = "0.14" interpolation = "0.2" interpolation_03 = { package = "interpolation", version = "0.3", optional = true } thiserror = "1.0" -wgpu-types = "0.17" +wgpu-types = "0.19" [dev-dependencies] -bevy = { version = "0.12", default-features = false, features = [ +bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "4ebc560dfb0fee5d3728d1d8f7362f484b784e4c", default-features = false, features = [ "animation", "bevy_gltf", "bevy_pbr", diff --git a/examples/animated_fox.rs b/examples/animated_fox.rs index 416b349..3acb785 100644 --- a/examples/animated_fox.rs +++ b/examples/animated_fox.rs @@ -51,7 +51,7 @@ fn setup( size: 500000.0, subdivisions: 0, })), - material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()), + material: materials.add(StandardMaterial::from(Color::rgb(0.3, 0.5, 0.3))), ..default() }); diff --git a/examples/flying_objects.rs b/examples/flying_objects.rs index 6e6cc20..190f344 100644 --- a/examples/flying_objects.rs +++ b/examples/flying_objects.rs @@ -36,18 +36,15 @@ fn setup( mut materials: ResMut>, ) { commands.insert_resource(MyAssets { - mesh: meshes.add( - Capsule { - radius: 1.0, - rings: 10, - depth: 2.0, - latitudes: 15, - longitudes: 15, - ..default() - } - .into(), - ), - material: materials.add(Color::BEIGE.into()), + mesh: meshes.add(Mesh::from(Capsule { + radius: 1.0, + rings: 10, + depth: 2.0, + latitudes: 15, + longitudes: 15, + ..default() + })), + material: materials.add(StandardMaterial::from(Color::BEIGE)), }); // Add light source and camera diff --git a/examples/pieces.rs b/examples/pieces.rs index 2e04dec..30557c4 100644 --- a/examples/pieces.rs +++ b/examples/pieces.rs @@ -32,15 +32,12 @@ fn setup( // Add sphere with child meshes sticking out of it commands .spawn(PbrBundle { - mesh: meshes.add( - UVSphere { - radius: 0.75, - sectors: 30, - stacks: 30, - } - .into(), - ), - material: materials.add(Color::rgb(0.9, 0.1, 0.1).into()), + mesh: meshes.add(Mesh::from(UVSphere { + radius: 0.75, + sectors: 30, + stacks: 30, + })), + material: materials.add(StandardMaterial::from(Color::rgb(0.9, 0.1, 0.1))), transform: Transform::from_translation(Vec3::new(0.0, 1.0, 0.0)), ..default() }) @@ -60,18 +57,15 @@ fn setup( .with_children(|parent| { parent .spawn(PbrBundle { - mesh: meshes.add( - Capsule { - radius: 0.2, - rings: 15, - depth: 1.0, - latitudes: 15, - longitudes: 15, - ..Default::default() - } - .into(), - ), - material: materials.add(Color::rgb(0.1, 0.1, 0.9).into()), + mesh: meshes.add(Mesh::from(Capsule { + radius: 0.2, + rings: 15, + depth: 1.0, + latitudes: 15, + longitudes: 15, + ..Default::default() + })), + material: materials.add(StandardMaterial::from(Color::rgb(0.1, 0.1, 0.9))), transform: Transform::from_rotation(Quat::from_axis_angle(Vec3::X, TAU / 4.0)) .with_translation(Vec3::new(0.0, 0.0, 0.75)), ..default() @@ -79,16 +73,13 @@ fn setup( .insert(InheritOutlineBundle::default()); parent .spawn(PbrBundle { - mesh: meshes.add( - Torus { - radius: 0.5, - ring_radius: 0.1, - subdivisions_segments: 30, - subdivisions_sides: 15, - } - .into(), - ), - material: materials.add(Color::rgb(0.1, 0.1, 0.9).into()), + mesh: meshes.add(Mesh::from(Torus { + radius: 0.5, + ring_radius: 0.1, + subdivisions_segments: 30, + subdivisions_sides: 15, + })), + material: materials.add(StandardMaterial::from(Color::rgb(0.1, 0.1, 0.9))), transform: Transform::from_rotation(Quat::from_axis_angle(Vec3::Z, TAU / 4.0)) .with_translation(Vec3::new(0.0, 0.0, -0.75)), ..default() @@ -102,7 +93,7 @@ fn setup( size: 5.0, subdivisions: 0, })), - material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()), + material: materials.add(StandardMaterial::from(Color::rgb(0.3, 0.5, 0.3))), ..default() }); commands.spawn(PointLightBundle { diff --git a/examples/render_layers.rs b/examples/render_layers.rs index 3dae2ad..e379f53 100644 --- a/examples/render_layers.rs +++ b/examples/render_layers.rs @@ -1,7 +1,6 @@ use std::f32::consts::PI; use bevy::{ - core_pipeline::clear_color::ClearColorConfig, prelude::{ shape::{Plane, Torus}, *, @@ -45,7 +44,7 @@ fn setup( subdivisions_segments: 40, subdivisions_sides: 20, })), - material: materials.add(Color::rgb(0.1, 0.1, 0.9).into()), + material: materials.add(StandardMaterial::from(Color::rgb(0.1, 0.1, 0.9))), transform: Transform::from_rotation(Quat::from_rotation_x(0.5 * PI)) .with_translation(0.8 * Vec3::Y), ..default() @@ -67,7 +66,7 @@ fn setup( size: 5.0, subdivisions: 0, })), - material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()), + material: materials.add(StandardMaterial::from(Color::rgb(0.3, 0.5, 0.3))), ..default() }); commands.spawn(PointLightBundle { @@ -95,9 +94,6 @@ fn setup( .spawn(Camera3dBundle { camera: Camera { order: i, - ..default() - }, - camera_3d: Camera3d { clear_color: if i > 0 { ClearColorConfig::None } else { @@ -105,6 +101,7 @@ fn setup( }, ..default() }, + camera_3d: Camera3d { ..default() }, transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y), ..default() }) @@ -117,11 +114,11 @@ fn setup( } fn set_camera_viewports( - win_query: Query<(&Window, Changed), With>, + win_query: Query, With>, mut query: Query<(&mut Camera, &CameraMode)>, ) { - let (win, win_changed) = win_query.get_single().unwrap(); - if win_changed { + let win = win_query.get_single().unwrap(); + if win.is_changed() { // Divide window into quadrants let size = UVec2::new(win.physical_width() / 2, win.physical_height() / 2); for (mut camera, mode) in query.iter_mut() { diff --git a/examples/shapes.rs b/examples/shapes.rs index 96ed028..6f3ecb4 100644 --- a/examples/shapes.rs +++ b/examples/shapes.rs @@ -38,7 +38,7 @@ fn setup( commands .spawn(PbrBundle { mesh: meshes.add(cube_mesh), - material: materials.add(Color::rgb(0.1, 0.1, 0.9).into()), + material: materials.add(StandardMaterial::from(Color::rgb(0.1, 0.1, 0.9))), transform: Transform::from_xyz(0.0, 1.0, 0.0), ..default() }) @@ -61,7 +61,7 @@ fn setup( subdivisions_segments: 20, subdivisions_sides: 10, })), - material: materials.add(Color::rgb(0.9, 0.1, 0.1).into()), + material: materials.add(StandardMaterial::from(Color::rgb(0.9, 0.1, 0.1))), transform: Transform::from_xyz(0.0, 1.2, 2.0) .with_rotation(Quat::from_rotation_x(0.5 * PI)), ..default() @@ -82,7 +82,7 @@ fn setup( size: 5.0, subdivisions: 0, })), - material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()), + material: materials.add(StandardMaterial::from(Color::rgb(0.3, 0.5, 0.3))), ..default() }); commands.spawn(PointLightBundle { diff --git a/src/computed.rs b/src/computed.rs index f25d009..6d7fe6d 100644 --- a/src/computed.rs +++ b/src/computed.rs @@ -58,9 +58,13 @@ impl Sourced { } } - pub fn is_changed(&self, tuple: Option<(&U, bool)>) -> bool { + pub fn is_changed(&self, tuple: &Option>) -> bool { tuple.is_some() != matches!(self.source, Source::Set) - || if let Some((_, c)) = tuple { c } else { false } + || if let Some(r) = tuple { + r.is_changed() + } else { + false + } } } @@ -77,11 +81,11 @@ pub(crate) struct ComputedInternal { pub struct ComputedOutline(pub(crate) Option); type OutlineComponents<'a> = ( - (&'a InheritedVisibility, Changed), - (&'a GlobalTransform, Changed), - Option<(&'a OutlineVolume, Changed)>, - Option<(&'a OutlineStencil, Changed)>, - Option<(&'a OutlineMode, Changed)>, + Ref<'a, InheritedVisibility>, + Ref<'a, GlobalTransform>, + Option>, + Option>, + Option>, ); #[allow(clippy::type_complexity)] @@ -150,7 +154,7 @@ fn propagate_computed_outline( fn update_computed_outline( computed: &mut ComputedOutline, - ((visibility, changed_visibility), (transform, changed_transform), volume, stencil, mode): QueryItem<'_, OutlineComponents>, + (visibility, transform, volume, stencil, mode): QueryItem<'_, OutlineComponents>, parent_computed: &ComputedInternal, parent_entity: Option, force_update: bool, @@ -158,27 +162,31 @@ fn update_computed_outline( let changed = force_update || if let ComputedOutline(Some(computed)) = computed { computed.inherited_from != parent_entity - || changed_visibility - || (changed_transform && matches!(mode, Some((OutlineMode::FlatVertex { .. }, _)))) - || computed.volume.is_changed(volume) - || computed.stencil.is_changed(stencil) - || computed.mode.is_changed(mode) + || visibility.is_changed() + || (transform.is_changed() + && mode + .as_ref() + .map(|r| matches!(r.as_ref(), OutlineMode::FlatVertex { .. })) + .unwrap_or(false)) + || computed.volume.is_changed(&volume) + || computed.stencil.is_changed(&stencil) + || computed.mode.is_changed(&mode) } else { true }; if changed { *computed = ComputedOutline(Some(ComputedInternal { inherited_from: parent_entity, - volume: if let Some((vol, _)) = volume { + volume: if let Some(vol) = volume { Sourced::set(ComputedVolume { enabled: visibility.get() && vol.visible && vol.colour.a() != 0.0, offset: vol.width, - colour: vol.colour.into(), + colour: vol.colour.as_linear_rgba_f32().into(), }) } else { Sourced::inherit(&parent_computed.volume.value) }, - stencil: if let Some((sten, _)) = stencil { + stencil: if let Some(sten) = stencil { Sourced::set(ComputedStencil { enabled: visibility.get() && sten.enabled, offset: sten.offset, @@ -186,8 +194,8 @@ fn update_computed_outline( } else { Sourced::inherit(&parent_computed.stencil.value) }, - mode: if let Some((m, _)) = mode { - Sourced::set(match m { + mode: if let Some(m) = mode { + Sourced::set(match m.as_ref() { OutlineMode::FlatVertex { model_origin: origin, } => ComputedMode { diff --git a/src/lib.rs b/src/lib.rs index 63b9cd3..800a012 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,18 +23,20 @@ //! [`AutoGenerateOutlineNormalsPlugin`]. use bevy::asset::load_internal_asset; +use bevy::core_pipeline::core_3d::graph::{Labels3d, SubGraph3d}; use bevy::prelude::*; use bevy::render::batching::{batch_and_prepare_render_phase, write_batched_instance_buffer}; use bevy::render::extract_component::{ ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin, }; use bevy::render::mesh::MeshVertexAttribute; -use bevy::render::render_graph::RenderGraph; +use bevy::render::render_graph::{RenderGraph, RenderLabel}; use bevy::render::render_phase::{sort_phase_system, AddRenderCommand, DrawFunctions}; use bevy::render::render_resource::{SpecializedMeshPipelines, VertexFormat}; use bevy::render::view::{RenderLayers, VisibilitySystems}; use bevy::render::{Render, RenderApp, RenderSet}; use bevy::transform::TransformSystem; +use bevy::ui::graph::LabelsUi; use interpolation::Lerp; use crate::draw::{ @@ -72,7 +74,10 @@ pub const ATTRIBUTE_OUTLINE_NORMAL: MeshVertexAttribute = /// /// 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. -pub const OUTLINE_PASS_NODE_NAME: &str = "bevy_mod_outline_node"; +#[derive(Copy, Clone, Debug, RenderLabel, Hash, PartialEq, Eq)] +pub enum LabelsOutline { + OutlinePass, +} /// A component for stenciling meshes during outline rendering. #[derive(Clone, Component)] @@ -108,7 +113,7 @@ impl Lerp for OutlineStencil { fn lerp(&self, other: &Self, scalar: &Self::Scalar) -> Self { OutlineStencil { enabled: lerp_bool(self.enabled, other.enabled, *scalar), - offset: self.offset.lerp(&other.offset, scalar), + offset: self.offset.lerp(other.offset, *scalar), } } } @@ -139,7 +144,7 @@ impl Lerp for OutlineVolume { fn lerp(&self, other: &Self, scalar: &Self::Scalar) -> Self { OutlineVolume { visible: lerp_bool(self.visible, other.visible, *scalar), - width: self.width.lerp(&other.width, scalar), + width: self.width.lerp(other.width, *scalar), colour: { let [r, g, b, a] = self .colour @@ -165,11 +170,11 @@ impl interpolation_03::Lerp for OutlineVolume { pub struct OutlineRenderLayers(pub RenderLayers); impl ExtractComponent for OutlineRenderLayers { - type Query = ( + type QueryData = ( Option<&'static OutlineRenderLayers>, Option<&'static RenderLayers>, ); - type Filter = With; + type QueryFilter = With; type Out = Self; fn extract_component( @@ -319,21 +324,13 @@ impl Plugin for OutlinePlugin { let mut graph = world.resource_mut::(); - let draw_3d_graph = graph - .get_sub_graph_mut(bevy::core_pipeline::core_3d::graph::NAME) - .unwrap(); - draw_3d_graph.add_node(OUTLINE_PASS_NODE_NAME, node); + let draw_3d_graph = graph.get_sub_graph_mut(SubGraph3d).unwrap(); + draw_3d_graph.add_node(LabelsOutline::OutlinePass, node); // Run after main 3D pass, but before UI psss - draw_3d_graph.add_node_edge( - bevy::core_pipeline::core_3d::graph::node::END_MAIN_PASS, - OUTLINE_PASS_NODE_NAME, - ); + draw_3d_graph.add_node_edge(Labels3d::EndMainPass, LabelsOutline::OutlinePass); #[cfg(feature = "bevy_ui")] - draw_3d_graph.add_node_edge( - OUTLINE_PASS_NODE_NAME, - bevy::ui::draw_ui_graph::node::UI_PASS, - ); + draw_3d_graph.add_node_edge(LabelsOutline::OutlinePass, LabelsUi::UiPass); } fn finish(&self, app: &mut App) { diff --git a/src/node.rs b/src/node.rs index 41f1bfa..b952653 100644 --- a/src/node.rs +++ b/src/node.rs @@ -10,7 +10,7 @@ use bevy::render::render_phase::{ }; use bevy::render::render_resource::{ CachedRenderPipelineId, LoadOp, Operations, RenderPassDepthStencilAttachment, - RenderPassDescriptor, + RenderPassDescriptor, StoreOp, }; use bevy::render::view::{ExtractedView, ViewDepthTexture, ViewTarget}; use bevy::render::{ @@ -217,13 +217,15 @@ impl Node for OutlineNode { label: Some("outline_stencil_pass"), color_attachments: &[], depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { - view: &depth.view, + view: &depth.view(), depth_ops: Some(Operations { load: camera_3d.depth_load_op.clone().into(), - store: true, + store: StoreOp::Store, }), stencil_ops: None, }), + timestamp_writes: None, + occlusion_query_set: None, }; let mut tracked_pass = render_context.begin_tracked_render_pass(pass_descriptor); if let Some(viewport) = camera.viewport.as_ref() { @@ -235,18 +237,17 @@ impl Node for OutlineNode { if !opaque_phase.items.is_empty() { let pass_descriptor = RenderPassDescriptor { label: Some("outline_opaque_pass"), - color_attachments: &[Some(target.get_color_attachment(Operations { - load: LoadOp::Load, - store: true, - }))], + color_attachments: &[Some(target.get_color_attachment())], depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { - view: &depth.view, + view: &depth.view(), depth_ops: Some(Operations { load: LoadOp::Load, - store: true, + store: StoreOp::Store, }), stencil_ops: None, }), + timestamp_writes: None, + occlusion_query_set: None, }; let mut tracked_pass = render_context.begin_tracked_render_pass(pass_descriptor); if let Some(viewport) = camera.viewport.as_ref() { @@ -258,18 +259,17 @@ impl Node for OutlineNode { if !transparent_phase.items.is_empty() { let pass_descriptor = RenderPassDescriptor { label: Some("outline_transparent_pass"), - color_attachments: &[Some(target.get_color_attachment(Operations { - load: LoadOp::Load, - store: true, - }))], + color_attachments: &[Some(target.get_color_attachment())], depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { - view: &depth.view, + view: &depth.view(), depth_ops: Some(Operations { load: LoadOp::Load, - store: true, + store: StoreOp::Store, }), stencil_ops: None, }), + timestamp_writes: None, + occlusion_query_set: None, }; let mut tracked_pass = render_context.begin_tracked_render_pass(pass_descriptor); if let Some(viewport) = camera.viewport.as_ref() { diff --git a/src/pipeline.rs b/src/pipeline.rs index 1cebe5f..12dad97 100644 --- a/src/pipeline.rs +++ b/src/pipeline.rs @@ -1,7 +1,6 @@ use std::borrow::Cow; -use bevy::ecs::query::QueryItem; -use bevy::ecs::system::lifetimeless::Read; +use bevy::ecs::system::lifetimeless::SQuery; use bevy::ecs::system::SystemParamItem; use bevy::pbr::{ setup_morph_and_skinning_defs, MeshFlags, MeshPipelineKey, MeshTransforms, MeshUniform, @@ -9,11 +8,10 @@ use bevy::pbr::{ use bevy::prelude::*; use bevy::render::batching::GetBatchData; use bevy::render::render_resource::{ - BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BlendState, - BufferBindingType, BufferSize, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState, - DepthStencilState, Face, FragmentState, FrontFace, MultisampleState, PolygonMode, - PrimitiveState, PrimitiveTopology, ShaderDefVal, ShaderSize, ShaderStages, ShaderType, - StencilState, TextureFormat, VertexState, + BindGroupLayout, BindGroupLayoutEntry, BindingType, BlendState, BufferBindingType, BufferSize, + ColorTargetState, ColorWrites, CompareFunction, DepthBiasState, DepthStencilState, Face, + FragmentState, FrontFace, MultisampleState, PolygonMode, PrimitiveState, PrimitiveTopology, + ShaderDefVal, ShaderSize, ShaderStages, ShaderType, StencilState, TextureFormat, VertexState, }; use bevy::render::renderer::RenderDevice; use bevy::render::settings::WgpuSettings; @@ -168,76 +166,71 @@ impl FromWorld for OutlinePipeline { let world = world.cell(); let mesh_pipeline = world.get_resource::().unwrap().clone(); let render_device = world.get_resource::().unwrap(); - let outline_view_bind_group_layout = - render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { - label: Some("outline_view_bind_group_layout"), - entries: &[ - BindGroupLayoutEntry { - binding: 0, - 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: BufferBindingType::Uniform, - has_dynamic_offset: true, - min_binding_size: Some(OutlineViewUniform::min_size()), - }, - count: None, - }, - ], - }); - let outline_volume_bind_group_layout = - render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { - label: Some("outline_volume_bind_group_layout"), - entries: &[ - BindGroupLayoutEntry { - binding: 0, - visibility: ShaderStages::VERTEX, - ty: BindingType::Buffer { - ty: BufferBindingType::Uniform, - has_dynamic_offset: true, - min_binding_size: BufferSize::new( - OutlineVolumeUniform::SHADER_SIZE.get(), - ), - }, - count: None, - }, - BindGroupLayoutEntry { - binding: 1, - visibility: ShaderStages::FRAGMENT, - ty: BindingType::Buffer { - ty: BufferBindingType::Uniform, - has_dynamic_offset: true, - min_binding_size: BufferSize::new( - OutlineFragmentUniform::SHADER_SIZE.get(), - ), - }, - count: None, - }, - ], - }); - let outline_stencil_bind_group_layout = - render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { - label: Some("outline_stencil_bind_group_layout"), - entries: &[BindGroupLayoutEntry { + let outline_view_bind_group_layout = render_device.create_bind_group_layout( + "outline_view_bind_group_layout", + &[ + BindGroupLayoutEntry { binding: 0, visibility: ShaderStages::VERTEX, ty: BindingType::Buffer { ty: BufferBindingType::Uniform, has_dynamic_offset: true, - min_binding_size: BufferSize::new(OutlineStencilUniform::SHADER_SIZE.get()), + min_binding_size: Some(ViewUniform::min_size()), }, count: None, - }], - }); + }, + BindGroupLayoutEntry { + binding: 1, + visibility: ShaderStages::VERTEX, + ty: BindingType::Buffer { + ty: BufferBindingType::Uniform, + has_dynamic_offset: true, + min_binding_size: Some(OutlineViewUniform::min_size()), + }, + count: None, + }, + ], + ); + let outline_volume_bind_group_layout = render_device.create_bind_group_layout( + "outline_volume_bind_group_layout", + &[ + BindGroupLayoutEntry { + binding: 0, + visibility: ShaderStages::VERTEX, + ty: BindingType::Buffer { + ty: BufferBindingType::Uniform, + has_dynamic_offset: true, + min_binding_size: BufferSize::new(OutlineVolumeUniform::SHADER_SIZE.get()), + }, + count: None, + }, + BindGroupLayoutEntry { + binding: 1, + visibility: ShaderStages::FRAGMENT, + ty: BindingType::Buffer { + ty: BufferBindingType::Uniform, + has_dynamic_offset: true, + min_binding_size: BufferSize::new( + OutlineFragmentUniform::SHADER_SIZE.get(), + ), + }, + count: None, + }, + ], + ); + let outline_stencil_bind_group_layout = render_device.create_bind_group_layout( + "outline_stencil_bind_group_layout", + &[BindGroupLayoutEntry { + binding: 0, + visibility: ShaderStages::VERTEX, + ty: BindingType::Buffer { + ty: BufferBindingType::Uniform, + has_dynamic_offset: true, + min_binding_size: BufferSize::new(OutlineStencilUniform::SHADER_SIZE.get()), + }, + count: None, + }], + ); OutlinePipeline { mesh_pipeline, outline_view_bind_group_layout, @@ -373,21 +366,20 @@ impl SpecializedMeshPipeline for OutlinePipeline { } impl GetBatchData for OutlinePipeline { - type Param = (); - type Query = Read; - type QueryFilter = (); + type Param = SQuery<&'static ExtractedOutline>; type CompareData = (); type BufferData = MeshUniform; fn get_batch_data( - _: &SystemParamItem, - outline: &QueryItem, - ) -> (Self::BufferData, Option) { + param: &SystemParamItem, + entity: Entity, + ) -> Option<(Self::BufferData, Option)> { + let outline = param.get(entity).unwrap(); let ts = MeshTransforms { transform: (&outline.transform).into(), previous_transform: (&outline.transform).into(), flags: MeshFlags::NONE.bits(), }; - ((&ts).into(), None) + Some((MeshUniform::new(&ts, None), None)) } } diff --git a/src/uniforms.rs b/src/uniforms.rs index 86b04e7..6f9eb96 100644 --- a/src/uniforms.rs +++ b/src/uniforms.rs @@ -149,20 +149,23 @@ pub(crate) fn prepare_outline_volume_bind_group( pub(crate) struct SetOutlineStencilBindGroup(); impl RenderCommand for SetOutlineStencilBindGroup { - type ViewWorldQuery = (); - type ItemWorldQuery = Read>; + type ViewQuery = (); + type ItemQuery = Read>; type Param = SRes; fn render<'w>( _item: &StencilOutline, _view_data: (), - entity_data: &DynamicUniformIndex, + entity_data: Option<&DynamicUniformIndex>, bind_group: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { + let Some(dyn_uniform) = entity_data else { + return RenderCommandResult::Failure; + }; pass.set_bind_group( I, &bind_group.into_inner().bind_group, - &[entity_data.index()], + &[dyn_uniform.index()], ); RenderCommandResult::Success } @@ -171,8 +174,8 @@ impl RenderCommand for SetOutlineStencilBindGrou pub(crate) struct SetOutlineVolumeBindGroup(); impl RenderCommand

for SetOutlineVolumeBindGroup { - type ViewWorldQuery = (); - type ItemWorldQuery = ( + type ViewQuery = (); + type ItemQuery = ( Read>, Read>, ); @@ -180,14 +183,16 @@ impl RenderCommand

for SetOutlineVolumeBindGrou fn render<'w>( _item: &P, _view_data: (), - entity_data: ( + entity_data: Option<( &DynamicUniformIndex, &DynamicUniformIndex, - ), + )>, bind_group: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { - let (vertex, fragment) = entity_data; + let Some((vertex, fragment)) = entity_data else { + return RenderCommandResult::Failure; + }; pass.set_bind_group( I, &bind_group.into_inner().bind_group, diff --git a/src/view_uniforms.rs b/src/view_uniforms.rs index 5582e92..4d8eb76 100644 --- a/src/view_uniforms.rs +++ b/src/view_uniforms.rs @@ -82,16 +82,16 @@ pub(crate) fn prepare_outline_view_bind_group( pub(crate) struct SetOutlineViewBindGroup(); impl RenderCommand

for SetOutlineViewBindGroup { - type ViewWorldQuery = ( + type ViewQuery = ( Read, Read>, ); - type ItemWorldQuery = (); + type ItemQuery = (); type Param = SRes; fn render<'w>( _item: &P, - (core_view_data, outline_view_data): ROQueryItem<'w, Self::ViewWorldQuery>, - _entity_data: (), + (core_view_data, outline_view_data): ROQueryItem<'w, Self::ViewQuery>, + _entity_data: Option<()>, bind_group: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult {