From 4b457cc2cecbe0042c3bad547c09bfe1dd57f439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Mockers?= Date: Mon, 17 Mar 2025 23:23:42 +0100 Subject: [PATCH] Revert "don't use bevy_pbr for base bevy_gizmos plugin" (#18327) # Objective - #17581 broke gizmos - Fixes #18325 ## Solution - Revert #17581 - Add gizmos to testbed ## Testing - Run any example with gizmos, it renders correctly --- crates/bevy_gizmos/Cargo.toml | 1 + crates/bevy_gizmos/src/config.rs | 10 +- crates/bevy_gizmos/src/lib.rs | 76 ++++++++---- crates/bevy_gizmos/src/pipeline_2d.rs | 68 ++++++---- crates/bevy_gizmos/src/pipeline_3d.rs | 171 +++++++++++++++++++------- crates/bevy_gizmos/src/retained.rs | 1 + crates/bevy_gizmos/src/view.rs | 90 -------------- crates/bevy_internal/Cargo.toml | 2 +- examples/testbed/2d.rs | 23 +++- examples/testbed/3d.rs | 30 ++++- 10 files changed, 278 insertions(+), 194 deletions(-) delete mode 100644 crates/bevy_gizmos/src/view.rs diff --git a/crates/bevy_gizmos/Cargo.toml b/crates/bevy_gizmos/Cargo.toml index a7f9f4b778..3a264c6244 100644 --- a/crates/bevy_gizmos/Cargo.toml +++ b/crates/bevy_gizmos/Cargo.toml @@ -16,6 +16,7 @@ bevy_render = ["dep:bevy_render", "bevy_core_pipeline"] [dependencies] # Bevy bevy_pbr = { path = "../bevy_pbr", version = "0.16.0-dev", optional = true } +bevy_sprite = { path = "../bevy_sprite", version = "0.16.0-dev", optional = true } bevy_app = { path = "../bevy_app", version = "0.16.0-dev" } bevy_color = { path = "../bevy_color", version = "0.16.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev" } diff --git a/crates/bevy_gizmos/src/config.rs b/crates/bevy_gizmos/src/config.rs index de52246ef7..973fa1cf0f 100644 --- a/crates/bevy_gizmos/src/config.rs +++ b/crates/bevy_gizmos/src/config.rs @@ -2,7 +2,10 @@ pub use bevy_gizmos_macros::GizmoConfigGroup; -#[cfg(feature = "bevy_render")] +#[cfg(all( + feature = "bevy_render", + any(feature = "bevy_pbr", feature = "bevy_sprite") +))] use {crate::GizmoAsset, bevy_asset::Handle, bevy_ecs::component::Component}; use bevy_ecs::{reflect::ReflectResource, resource::Resource}; @@ -241,7 +244,10 @@ impl Default for GizmoLineConfig { } } -#[cfg(feature = "bevy_render")] +#[cfg(all( + feature = "bevy_render", + any(feature = "bevy_pbr", feature = "bevy_sprite") +))] #[derive(Component)] pub(crate) struct GizmoMeshConfig { pub line_perspective: bool, diff --git a/crates/bevy_gizmos/src/lib.rs b/crates/bevy_gizmos/src/lib.rs index 7a8aa39727..373e248fb2 100644 --- a/crates/bevy_gizmos/src/lib.rs +++ b/crates/bevy_gizmos/src/lib.rs @@ -26,8 +26,10 @@ extern crate self as bevy_gizmos; #[derive(SystemSet, Clone, Debug, Hash, PartialEq, Eq)] pub enum GizmoRenderSystem { /// Adds gizmos to the [`Transparent2d`](bevy_core_pipeline::core_2d::Transparent2d) render phase + #[cfg(feature = "bevy_sprite")] QueueLineGizmos2d, /// Adds gizmos to the [`Transparent3d`](bevy_core_pipeline::core_3d::Transparent3d) render phase + #[cfg(feature = "bevy_pbr")] QueueLineGizmos3d, } @@ -44,16 +46,13 @@ pub mod grid; pub mod primitives; pub mod retained; pub mod rounded_box; -#[cfg(feature = "bevy_render")] -mod view; #[cfg(all(feature = "bevy_pbr", feature = "bevy_render"))] pub mod light; -#[cfg(feature = "bevy_render")] +#[cfg(all(feature = "bevy_sprite", feature = "bevy_render"))] mod pipeline_2d; - -#[cfg(feature = "bevy_render")] +#[cfg(all(feature = "bevy_pbr", feature = "bevy_render"))] mod pipeline_3d; /// The gizmos prelude. @@ -86,12 +85,13 @@ use bevy_ecs::{ schedule::{IntoScheduleConfigs, SystemSet}, system::{Res, ResMut}, }; -use bevy_math::Vec4; +use bevy_math::{Vec3, Vec4}; use bevy_reflect::TypePath; -#[cfg(feature = "bevy_render")] -use view::OnlyViewLayout; -#[cfg(feature = "bevy_render")] +#[cfg(all( + feature = "bevy_render", + any(feature = "bevy_pbr", feature = "bevy_sprite") +))] use crate::config::GizmoMeshConfig; use crate::{config::ErasedGizmoConfigGroup, gizmos::GizmoBuffer}; @@ -125,7 +125,10 @@ use { bytemuck::cast_slice, }; -#[cfg(feature = "bevy_render")] +#[cfg(all( + feature = "bevy_render", + any(feature = "bevy_pbr", feature = "bevy_sprite"), +))] use bevy_render::render_resource::{VertexAttribute, VertexBufferLayout, VertexStepMode}; use bevy_time::Fixed; use bevy_utils::TypeIdMap; @@ -143,10 +146,9 @@ const LINE_SHADER_HANDLE: Handle = weak_handle!("15dc5869-ad30-4664-b35a const LINE_JOINT_SHADER_HANDLE: Handle = weak_handle!("7b5bdda5-df81-4711-a6cf-e587700de6f2"); -/// A [`Plugin`] for the [`RenderApp`] that provides an immediate mode drawing api for visual debugging. +/// A [`Plugin`] that provides an immediate mode drawing api for visual debugging. /// -/// Additionally, it can support debugging light when the `bevy_pbr` feature is enabled, -/// see [`LightGizmoPlugin`] +/// Requires to be loaded after [`PbrPlugin`](bevy_pbr::PbrPlugin) or [`SpritePlugin`](bevy_sprite::SpritePlugin). #[derive(Default)] pub struct GizmoPlugin; @@ -187,8 +189,19 @@ impl Plugin for GizmoPlugin { ); render_app.add_systems(ExtractSchedule, (extract_gizmo_data, extract_linegizmos)); - app.add_plugins(pipeline_3d::LineGizmo3dPlugin) - .add_plugins(pipeline_2d::LineGizmo2dPlugin); + + #[cfg(feature = "bevy_sprite")] + if app.is_plugin_added::() { + app.add_plugins(pipeline_2d::LineGizmo2dPlugin); + } else { + tracing::warn!("bevy_sprite feature is enabled but bevy_sprite::SpritePlugin was not detected. Are you sure you loaded GizmoPlugin after SpritePlugin?"); + } + #[cfg(feature = "bevy_pbr")] + if app.is_plugin_added::() { + app.add_plugins(pipeline_3d::LineGizmo3dPlugin); + } else { + tracing::warn!("bevy_pbr feature is enabled but bevy_pbr::PbrPlugin was not detected. Are you sure you loaded GizmoPlugin after PbrPlugin?"); + } } else { tracing::warn!("bevy_render feature is enabled but RenderApp was not detected. Are you sure you loaded GizmoPlugin after RenderPlugin?"); } @@ -209,11 +222,9 @@ impl Plugin for GizmoPlugin { ), ); - render_app - .init_resource::() - .insert_resource(LineGizmoUniformBindgroupLayout { - layout: line_layout, - }); + render_app.insert_resource(LineGizmoUniformBindgroupLayout { + layout: line_layout, + }); } } @@ -463,6 +474,7 @@ fn extract_gizmo_data( #[cfg(feature = "webgl")] _padding: Default::default(), }, + #[cfg(any(feature = "bevy_pbr", feature = "bevy_sprite"))] GizmoMeshConfig { line_perspective: config.line.perspective, line_style: config.line.style, @@ -491,7 +503,7 @@ struct LineGizmoUniform { line_scale: f32, /// WebGL2 structs must be 16 byte aligned. #[cfg(feature = "webgl")] - _padding: bevy_math::Vec3, + _padding: Vec3, } /// A collection of gizmos. @@ -622,7 +634,7 @@ impl RenderCommand

for SetLineGizmoBindGroup #[inline] fn render<'w>( _item: &P, - _views: ROQueryItem<'w, Self::ViewQuery>, + _view: ROQueryItem<'w, Self::ViewQuery>, uniform_index: Option>, bind_group: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, @@ -641,7 +653,10 @@ impl RenderCommand

for SetLineGizmoBindGroup #[cfg(feature = "bevy_render")] struct DrawLineGizmo; -#[cfg(feature = "bevy_render")] +#[cfg(all( + feature = "bevy_render", + any(feature = "bevy_pbr", feature = "bevy_sprite") +))] impl RenderCommand

for DrawLineGizmo { type Param = SRes>; type ViewQuery = (); @@ -701,7 +716,10 @@ impl RenderCommand

for DrawLineGizmo #[cfg(feature = "bevy_render")] struct DrawLineJointGizmo; -#[cfg(feature = "bevy_render")] +#[cfg(all( + feature = "bevy_render", + any(feature = "bevy_pbr", feature = "bevy_sprite") +))] impl RenderCommand

for DrawLineJointGizmo { type Param = SRes>; type ViewQuery = (); @@ -771,7 +789,10 @@ impl RenderCommand

for DrawLineJointGizmo { } } -#[cfg(feature = "bevy_render")] +#[cfg(all( + feature = "bevy_render", + any(feature = "bevy_pbr", feature = "bevy_sprite") +))] fn line_gizmo_vertex_buffer_layouts(strip: bool) -> Vec { use VertexFormat::*; let mut position_layout = VertexBufferLayout { @@ -826,7 +847,10 @@ fn line_gizmo_vertex_buffer_layouts(strip: bool) -> Vec { } } -#[cfg(feature = "bevy_render")] +#[cfg(all( + feature = "bevy_render", + any(feature = "bevy_pbr", feature = "bevy_sprite") +))] fn line_joint_gizmo_vertex_buffer_layouts() -> Vec { use VertexFormat::*; let mut position_layout = VertexBufferLayout { diff --git a/crates/bevy_gizmos/src/pipeline_2d.rs b/crates/bevy_gizmos/src/pipeline_2d.rs index ebd8db9386..d81c55ecac 100644 --- a/crates/bevy_gizmos/src/pipeline_2d.rs +++ b/crates/bevy_gizmos/src/pipeline_2d.rs @@ -1,4 +1,3 @@ -use crate::view::{OnlyViewLayout, SetViewBindGroup}; use crate::{ config::{GizmoLineJoint, GizmoLineStyle, GizmoMeshConfig}, line_gizmo_vertex_buffer_layouts, line_joint_gizmo_vertex_buffer_layouts, DrawLineGizmo, @@ -26,8 +25,9 @@ use bevy_render::{ }, render_resource::*, view::{ExtractedView, Msaa, RenderLayers, ViewTarget}, - Render, RenderApp, + Render, RenderApp, RenderSet, }; +use bevy_sprite::{Mesh2dPipeline, Mesh2dPipelineKey, SetMesh2dViewBindGroup}; use tracing::error; pub struct LineGizmo2dPlugin; @@ -44,6 +44,15 @@ impl Plugin for LineGizmo2dPlugin { .add_render_command::() .init_resource::>() .init_resource::>() + .configure_sets( + Render, + GizmoRenderSystem::QueueLineGizmos2d + .in_set(RenderSet::Queue) + .ambiguous_with(bevy_sprite::queue_sprites) + .ambiguous_with( + bevy_sprite::queue_material2d_meshes::, + ), + ) .add_systems( Render, (queue_line_gizmos_2d, queue_line_joint_gizmos_2d) @@ -64,15 +73,14 @@ impl Plugin for LineGizmo2dPlugin { #[derive(Clone, Resource)] struct LineGizmoPipeline { - view_layout: BindGroupLayout, + mesh_pipeline: Mesh2dPipeline, uniform_layout: BindGroupLayout, } impl FromWorld for LineGizmoPipeline { fn from_world(render_world: &mut World) -> Self { - let view_layout = render_world.resource::().0.clone(); LineGizmoPipeline { - view_layout, + mesh_pipeline: render_world.resource::().clone(), uniform_layout: render_world .resource::() .layout @@ -83,8 +91,7 @@ impl FromWorld for LineGizmoPipeline { #[derive(PartialEq, Eq, Hash, Clone)] struct LineGizmoPipelineKey { - hdr: bool, - msaa: Msaa, + mesh_key: Mesh2dPipelineKey, strip: bool, line_style: GizmoLineStyle, } @@ -93,7 +100,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline { type Key = LineGizmoPipelineKey; fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { - let format = if key.hdr { + let format = if key.mesh_key.contains(Mesh2dPipelineKey::HDR) { ViewTarget::TEXTURE_FORMAT_HDR } else { TextureFormat::bevy_default() @@ -104,7 +111,10 @@ impl SpecializedRenderPipeline for LineGizmoPipeline { "SIXTEEN_BYTE_ALIGNMENT".into(), ]; - let layout = vec![self.view_layout.clone(), self.uniform_layout.clone()]; + let layout = vec![ + self.mesh_pipeline.view_layout.clone(), + self.uniform_layout.clone(), + ]; let fragment_entry_point = match key.line_style { GizmoLineStyle::Solid => "fragment_solid", @@ -148,7 +158,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline { }, }), multisample: MultisampleState { - count: key.msaa.samples(), + count: key.mesh_key.msaa_samples(), mask: !0, alpha_to_coverage_enabled: false, }, @@ -161,15 +171,14 @@ impl SpecializedRenderPipeline for LineGizmoPipeline { #[derive(Clone, Resource)] struct LineJointGizmoPipeline { - view_layout: BindGroupLayout, + mesh_pipeline: Mesh2dPipeline, uniform_layout: BindGroupLayout, } impl FromWorld for LineJointGizmoPipeline { fn from_world(render_world: &mut World) -> Self { - let view_layout = render_world.resource::().0.clone(); LineJointGizmoPipeline { - view_layout, + mesh_pipeline: render_world.resource::().clone(), uniform_layout: render_world .resource::() .layout @@ -180,8 +189,7 @@ impl FromWorld for LineJointGizmoPipeline { #[derive(PartialEq, Eq, Hash, Clone)] struct LineJointGizmoPipelineKey { - hdr: bool, - msaa: Msaa, + mesh_key: Mesh2dPipelineKey, joints: GizmoLineJoint, } @@ -189,7 +197,7 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { type Key = LineJointGizmoPipelineKey; fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { - let format = if key.hdr { + let format = if key.mesh_key.contains(Mesh2dPipelineKey::HDR) { ViewTarget::TEXTURE_FORMAT_HDR } else { TextureFormat::bevy_default() @@ -200,7 +208,10 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { "SIXTEEN_BYTE_ALIGNMENT".into(), ]; - let layout = vec![self.view_layout.clone(), self.uniform_layout.clone()]; + let layout = vec![ + self.mesh_pipeline.view_layout.clone(), + self.uniform_layout.clone(), + ]; if key.joints == GizmoLineJoint::None { error!("There is no entry point for line joints with GizmoLineJoints::None. Please consider aborting the drawing process before reaching this stage."); @@ -248,7 +259,7 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { }, }), multisample: MultisampleState { - count: key.msaa.samples(), + count: key.mesh_key.msaa_samples(), mask: !0, alpha_to_coverage_enabled: false, }, @@ -261,19 +272,19 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { type DrawLineGizmo2d = ( SetItemPipeline, - SetViewBindGroup<0>, + SetMesh2dViewBindGroup<0>, SetLineGizmoBindGroup<1>, DrawLineGizmo, ); type DrawLineGizmo2dStrip = ( SetItemPipeline, - SetViewBindGroup<0>, + SetMesh2dViewBindGroup<0>, SetLineGizmoBindGroup<1>, DrawLineGizmo, ); type DrawLineJointGizmo2d = ( SetItemPipeline, - SetViewBindGroup<0>, + SetMesh2dViewBindGroup<0>, SetLineGizmoBindGroup<1>, DrawLineJointGizmo, ); @@ -300,6 +311,9 @@ fn queue_line_gizmos_2d( continue; }; + let mesh_key = Mesh2dPipelineKey::from_msaa_samples(msaa.samples()) + | Mesh2dPipelineKey::from_hdr(view.hdr); + let render_layers = render_layers.unwrap_or_default(); for (entity, main_entity, config) in &line_gizmos { if !config.render_layers.intersects(render_layers) { @@ -315,8 +329,7 @@ fn queue_line_gizmos_2d( &pipeline_cache, &pipeline, LineGizmoPipelineKey { - msaa: *msaa, - hdr: view.hdr, + mesh_key, strip: false, line_style: config.line_style, }, @@ -337,8 +350,7 @@ fn queue_line_gizmos_2d( &pipeline_cache, &pipeline, LineGizmoPipelineKey { - msaa: *msaa, - hdr: view.hdr, + mesh_key, strip: true, line_style: config.line_style, }, @@ -377,6 +389,9 @@ fn queue_line_joint_gizmos_2d( continue; }; + let mesh_key = Mesh2dPipelineKey::from_msaa_samples(msaa.samples()) + | Mesh2dPipelineKey::from_hdr(view.hdr); + let render_layers = render_layers.unwrap_or_default(); for (entity, main_entity, config) in &line_gizmos { if !config.render_layers.intersects(render_layers) { @@ -395,8 +410,7 @@ fn queue_line_joint_gizmos_2d( &pipeline_cache, &pipeline, LineJointGizmoPipelineKey { - msaa: *msaa, - hdr: view.hdr, + mesh_key, joints: config.line_joints, }, ); diff --git a/crates/bevy_gizmos/src/pipeline_3d.rs b/crates/bevy_gizmos/src/pipeline_3d.rs index c598ce81ee..799793e6cb 100644 --- a/crates/bevy_gizmos/src/pipeline_3d.rs +++ b/crates/bevy_gizmos/src/pipeline_3d.rs @@ -1,22 +1,26 @@ use crate::{ config::{GizmoLineJoint, GizmoLineStyle, GizmoMeshConfig}, - line_gizmo_vertex_buffer_layouts, line_joint_gizmo_vertex_buffer_layouts, - view::{prepare_view_bind_groups, OnlyViewLayout, SetViewBindGroup}, - DrawLineGizmo, DrawLineJointGizmo, GizmoRenderSystem, GpuLineGizmo, - LineGizmoUniformBindgroupLayout, SetLineGizmoBindGroup, LINE_JOINT_SHADER_HANDLE, - LINE_SHADER_HANDLE, + line_gizmo_vertex_buffer_layouts, line_joint_gizmo_vertex_buffer_layouts, DrawLineGizmo, + DrawLineJointGizmo, GizmoRenderSystem, GpuLineGizmo, LineGizmoUniformBindgroupLayout, + SetLineGizmoBindGroup, LINE_JOINT_SHADER_HANDLE, LINE_SHADER_HANDLE, }; use bevy_app::{App, Plugin}; -use bevy_core_pipeline::core_3d::{Transparent3d, CORE_3D_DEPTH_FORMAT}; +use bevy_core_pipeline::{ + core_3d::{Transparent3d, CORE_3D_DEPTH_FORMAT}, + oit::OrderIndependentTransparencySettings, + prepass::{DeferredPrepass, DepthPrepass, MotionVectorPrepass, NormalPrepass}, +}; use bevy_ecs::{ prelude::Entity, + query::Has, resource::Resource, schedule::IntoScheduleConfigs, system::{Query, Res, ResMut}, world::{FromWorld, World}, }; use bevy_image::BevyDefault as _; +use bevy_pbr::{MeshPipeline, MeshPipelineKey, SetMeshViewBindGroup}; use bevy_render::sync_world::MainEntity; use bevy_render::{ render_asset::{prepare_assets, RenderAssets}, @@ -29,6 +33,7 @@ use bevy_render::{ Render, RenderApp, RenderSet, }; use tracing::error; + pub struct LineGizmo3dPlugin; impl Plugin for LineGizmo3dPlugin { fn build(&self, app: &mut App) { @@ -42,13 +47,15 @@ impl Plugin for LineGizmo3dPlugin { .add_render_command::() .init_resource::>() .init_resource::>() + .configure_sets( + Render, + GizmoRenderSystem::QueueLineGizmos3d + .in_set(RenderSet::Queue) + .ambiguous_with(bevy_pbr::queue_material_meshes::), + ) .add_systems( Render, - ( - queue_line_gizmos_3d, - queue_line_joint_gizmos_3d, - prepare_view_bind_groups.in_set(RenderSet::Prepare), - ) + (queue_line_gizmos_3d, queue_line_joint_gizmos_3d) .in_set(GizmoRenderSystem::QueueLineGizmos3d) .after(prepare_assets::), ); @@ -65,17 +72,15 @@ impl Plugin for LineGizmo3dPlugin { } #[derive(Clone, Resource)] -pub(crate) struct LineGizmoPipeline { - view_layout: BindGroupLayout, +struct LineGizmoPipeline { + mesh_pipeline: MeshPipeline, uniform_layout: BindGroupLayout, } impl FromWorld for LineGizmoPipeline { fn from_world(render_world: &mut World) -> Self { - let view_layout = render_world.resource::().0.clone(); - LineGizmoPipeline { - view_layout, + mesh_pipeline: render_world.resource::().clone(), uniform_layout: render_world .resource::() .layout @@ -85,9 +90,8 @@ impl FromWorld for LineGizmoPipeline { } #[derive(PartialEq, Eq, Hash, Clone)] -pub(crate) struct LineGizmoPipelineKey { - msaa: Msaa, - hdr: bool, +struct LineGizmoPipelineKey { + view_key: MeshPipelineKey, strip: bool, perspective: bool, line_style: GizmoLineStyle, @@ -106,13 +110,18 @@ impl SpecializedRenderPipeline for LineGizmoPipeline { shader_defs.push("PERSPECTIVE".into()); } - let format = if key.hdr { + let format = if key.view_key.contains(MeshPipelineKey::HDR) { ViewTarget::TEXTURE_FORMAT_HDR } else { TextureFormat::bevy_default() }; - let layout = vec![self.view_layout.clone(), self.uniform_layout.clone()]; + let view_layout = self + .mesh_pipeline + .get_view_layout(key.view_key.into()) + .clone(); + + let layout = vec![view_layout, self.uniform_layout.clone()]; let fragment_entry_point = match key.line_style { GizmoLineStyle::Solid => "fragment_solid", @@ -147,7 +156,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline { bias: DepthBiasState::default(), }), multisample: MultisampleState { - count: key.msaa.samples(), + count: key.view_key.msaa_samples(), mask: !0, alpha_to_coverage_enabled: false, }, @@ -160,16 +169,14 @@ impl SpecializedRenderPipeline for LineGizmoPipeline { #[derive(Clone, Resource)] struct LineJointGizmoPipeline { - view_layout: BindGroupLayout, + mesh_pipeline: MeshPipeline, uniform_layout: BindGroupLayout, } impl FromWorld for LineJointGizmoPipeline { fn from_world(render_world: &mut World) -> Self { - let view_layout = render_world.resource::().0.clone(); - LineJointGizmoPipeline { - view_layout, + mesh_pipeline: render_world.resource::().clone(), uniform_layout: render_world .resource::() .layout @@ -180,8 +187,7 @@ impl FromWorld for LineJointGizmoPipeline { #[derive(PartialEq, Eq, Hash, Clone)] struct LineJointGizmoPipelineKey { - msaa: Msaa, - hdr: bool, + view_key: MeshPipelineKey, perspective: bool, joints: GizmoLineJoint, } @@ -199,13 +205,18 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { shader_defs.push("PERSPECTIVE".into()); } - let format = if key.hdr { + let format = if key.view_key.contains(MeshPipelineKey::HDR) { ViewTarget::TEXTURE_FORMAT_HDR } else { TextureFormat::bevy_default() }; - let layout = vec![self.view_layout.clone(), self.uniform_layout.clone()]; + let view_layout = self + .mesh_pipeline + .get_view_layout(key.view_key.into()) + .clone(); + + let layout = vec![view_layout, self.uniform_layout.clone()]; if key.joints == GizmoLineJoint::None { error!("There is no entry point for line joints with GizmoLineJoints::None. Please consider aborting the drawing process before reaching this stage."); @@ -244,7 +255,7 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { bias: DepthBiasState::default(), }), multisample: MultisampleState { - count: key.msaa.samples(), + count: key.view_key.msaa_samples(), mask: !0, alpha_to_coverage_enabled: false, }, @@ -257,19 +268,19 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { type DrawLineGizmo3d = ( SetItemPipeline, - SetViewBindGroup<0>, + SetMeshViewBindGroup<0>, SetLineGizmoBindGroup<1>, DrawLineGizmo, ); type DrawLineGizmo3dStrip = ( SetItemPipeline, - SetViewBindGroup<0>, + SetMeshViewBindGroup<0>, SetLineGizmoBindGroup<1>, DrawLineGizmo, ); type DrawLineJointGizmo3d = ( SetItemPipeline, - SetViewBindGroup<0>, + SetMeshViewBindGroup<0>, SetLineGizmoBindGroup<1>, DrawLineJointGizmo, ); @@ -282,7 +293,18 @@ fn queue_line_gizmos_3d( line_gizmos: Query<(Entity, &MainEntity, &GizmoMeshConfig)>, line_gizmo_assets: Res>, mut transparent_render_phases: ResMut>, - views: Query<(&ExtractedView, &Msaa, Option<&RenderLayers>)>, + views: Query<( + &ExtractedView, + &Msaa, + Option<&RenderLayers>, + ( + Has, + Has, + Has, + Has, + Has, + ), + )>, ) { let draw_function = draw_functions.read().get_id::().unwrap(); let draw_function_strip = draw_functions @@ -290,7 +312,13 @@ fn queue_line_gizmos_3d( .get_id::() .unwrap(); - for (view, msaa, render_layers) in &views { + for ( + view, + msaa, + render_layers, + (normal_prepass, depth_prepass, motion_vector_prepass, deferred_prepass, oit), + ) in &views + { let Some(transparent_phase) = transparent_render_phases.get_mut(&view.retained_view_entity) else { continue; @@ -298,6 +326,29 @@ fn queue_line_gizmos_3d( let render_layers = render_layers.unwrap_or_default(); + let mut view_key = MeshPipelineKey::from_msaa_samples(msaa.samples()) + | MeshPipelineKey::from_hdr(view.hdr); + + if normal_prepass { + view_key |= MeshPipelineKey::NORMAL_PREPASS; + } + + if depth_prepass { + view_key |= MeshPipelineKey::DEPTH_PREPASS; + } + + if motion_vector_prepass { + view_key |= MeshPipelineKey::MOTION_VECTOR_PREPASS; + } + + if deferred_prepass { + view_key |= MeshPipelineKey::DEFERRED_PREPASS; + } + + if oit { + view_key |= MeshPipelineKey::OIT_ENABLED; + } + for (entity, main_entity, config) in &line_gizmos { if !config.render_layers.intersects(render_layers) { continue; @@ -312,8 +363,7 @@ fn queue_line_gizmos_3d( &pipeline_cache, &pipeline, LineGizmoPipelineKey { - msaa: *msaa, - hdr: view.hdr, + view_key, strip: false, perspective: config.line_perspective, line_style: config.line_style, @@ -335,8 +385,7 @@ fn queue_line_gizmos_3d( &pipeline_cache, &pipeline, LineGizmoPipelineKey { - msaa: *msaa, - hdr: view.hdr, + view_key, strip: true, perspective: config.line_perspective, line_style: config.line_style, @@ -364,14 +413,30 @@ fn queue_line_joint_gizmos_3d( line_gizmos: Query<(Entity, &MainEntity, &GizmoMeshConfig)>, line_gizmo_assets: Res>, mut transparent_render_phases: ResMut>, - mut views: Query<(&ExtractedView, &Msaa, Option<&RenderLayers>)>, + views: Query<( + &ExtractedView, + &Msaa, + Option<&RenderLayers>, + ( + Has, + Has, + Has, + Has, + ), + )>, ) { let draw_function = draw_functions .read() .get_id::() .unwrap(); - for (view, msaa, render_layers) in &mut views { + for ( + view, + msaa, + render_layers, + (normal_prepass, depth_prepass, motion_vector_prepass, deferred_prepass), + ) in &views + { let Some(transparent_phase) = transparent_render_phases.get_mut(&view.retained_view_entity) else { continue; @@ -379,6 +444,25 @@ fn queue_line_joint_gizmos_3d( let render_layers = render_layers.unwrap_or_default(); + let mut view_key = MeshPipelineKey::from_msaa_samples(msaa.samples()) + | MeshPipelineKey::from_hdr(view.hdr); + + if normal_prepass { + view_key |= MeshPipelineKey::NORMAL_PREPASS; + } + + if depth_prepass { + view_key |= MeshPipelineKey::DEPTH_PREPASS; + } + + if motion_vector_prepass { + view_key |= MeshPipelineKey::MOTION_VECTOR_PREPASS; + } + + if deferred_prepass { + view_key |= MeshPipelineKey::DEFERRED_PREPASS; + } + for (entity, main_entity, config) in &line_gizmos { if !config.render_layers.intersects(render_layers) { continue; @@ -396,8 +480,7 @@ fn queue_line_joint_gizmos_3d( &pipeline_cache, &pipeline, LineJointGizmoPipelineKey { - msaa: *msaa, - hdr: view.hdr, + view_key, perspective: config.line_perspective, joints: config.line_joints, }, diff --git a/crates/bevy_gizmos/src/retained.rs b/crates/bevy_gizmos/src/retained.rs index f6b2209418..88610b9744 100644 --- a/crates/bevy_gizmos/src/retained.rs +++ b/crates/bevy_gizmos/src/retained.rs @@ -143,6 +143,7 @@ pub(crate) fn extract_linegizmos( #[cfg(feature = "webgl")] _padding: Default::default(), }, + #[cfg(any(feature = "bevy_pbr", feature = "bevy_sprite"))] crate::config::GizmoMeshConfig { line_perspective: gizmo.line_config.perspective, line_style: gizmo.line_config.style, diff --git a/crates/bevy_gizmos/src/view.rs b/crates/bevy_gizmos/src/view.rs deleted file mode 100644 index 34fa94c6c5..0000000000 --- a/crates/bevy_gizmos/src/view.rs +++ /dev/null @@ -1,90 +0,0 @@ -use bevy_ecs::{ - component::Component, - entity::Entity, - query::With, - resource::Resource, - system::{lifetimeless::Read, Commands, Query, Res}, - world::FromWorld, -}; -use bevy_render::{ - render_phase::{PhaseItem, RenderCommand, RenderCommandResult}, - render_resource::{ - binding_types::uniform_buffer, BindGroup, BindGroupLayout, BindGroupLayoutEntry, - DynamicBindGroupEntries, DynamicBindGroupLayoutEntries, ShaderStages, - }, - renderer::RenderDevice, - view::{ExtractedView, ViewUniform, ViewUniforms}, -}; - -#[derive(Component)] -pub(crate) struct ViewBindGroup(BindGroup); - -/// very common layout: just the view uniform -#[derive(Resource)] -pub(crate) struct OnlyViewLayout(pub BindGroupLayout); - -impl FromWorld for OnlyViewLayout { - fn from_world(world: &mut bevy_ecs::world::World) -> Self { - let render_device = world.resource::(); - - let view_layout = - render_device.create_bind_group_layout("mesh_view_layout", &view_layout_entries()); - - Self(view_layout) - } -} - -pub(crate) struct SetViewBindGroup; - -impl RenderCommand

for SetViewBindGroup { - type Param = (); - - type ViewQuery = Read; - - type ItemQuery = (); - - fn render<'w>( - _: &P, - view: bevy_ecs::query::ROQueryItem<'w, Self::ViewQuery>, - _: Option>, - _: bevy_ecs::system::SystemParamItem<'w, '_, Self::Param>, - pass: &mut bevy_render::render_phase::TrackedRenderPass<'w>, - ) -> RenderCommandResult { - pass.set_bind_group(I, &view.0, &[0]); - RenderCommandResult::Success - } -} - -pub(crate) fn prepare_view_bind_groups( - mut commands: Commands, - render_device: Res, - view_uniforms: Res, - layout: Res, - views: Query>, -) { - let Some(view_binding) = view_uniforms.uniforms.binding() else { - return; - }; - - let entries = DynamicBindGroupEntries::new_with_indices(((0, view_binding.clone()),)); - for entity in &views { - commands - .entity(entity) - .insert(ViewBindGroup(render_device.create_bind_group( - "view_bind_group", - &layout.0, - &entries, - ))); - } -} - -pub(crate) fn view_layout_entries() -> Vec { - DynamicBindGroupLayoutEntries::new_with_indices( - ShaderStages::FRAGMENT, - (( - 0, - uniform_buffer::(true).visibility(ShaderStages::VERTEX_FRAGMENT), - ),), - ) - .to_vec() -} diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index 073de918bd..b0be2f00c8 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -172,7 +172,7 @@ bevy_ci_testing = ["bevy_dev_tools/bevy_ci_testing", "bevy_render?/ci_limits"] # Enable animation support, and glTF animation loading animation = ["bevy_animation", "bevy_gltf?/bevy_animation"] -bevy_sprite = ["dep:bevy_sprite", "bevy_gizmos", "bevy_image"] +bevy_sprite = ["dep:bevy_sprite", "bevy_gizmos?/bevy_sprite", "bevy_image"] bevy_pbr = ["dep:bevy_pbr", "bevy_gizmos?/bevy_pbr", "bevy_image"] bevy_window = ["dep:bevy_window", "dep:bevy_a11y"] bevy_core_pipeline = ["dep:bevy_core_pipeline", "bevy_image"] diff --git a/examples/testbed/2d.rs b/examples/testbed/2d.rs index d74e198f0e..e1c42ebf95 100644 --- a/examples/testbed/2d.rs +++ b/examples/testbed/2d.rs @@ -15,7 +15,9 @@ fn main() { .add_systems(OnEnter(Scene::Bloom), bloom::setup) .add_systems(OnEnter(Scene::Text), text::setup) .add_systems(OnEnter(Scene::Sprite), sprite::setup) - .add_systems(Update, switch_scene); + .add_systems(OnEnter(Scene::Gizmos), gizmos::setup) + .add_systems(Update, switch_scene) + .add_systems(Update, gizmos::draw_gizmos.run_if(in_state(Scene::Gizmos))); #[cfg(feature = "bevy_ci_testing")] app.add_systems(Update, helpers::switch_scene_in_ci::); @@ -31,6 +33,7 @@ enum Scene { Bloom, Text, Sprite, + Gizmos, } impl Next for Scene { @@ -39,7 +42,8 @@ impl Next for Scene { Scene::Shapes => Scene::Bloom, Scene::Bloom => Scene::Text, Scene::Text => Scene::Sprite, - Scene::Sprite => Scene::Shapes, + Scene::Sprite => Scene::Gizmos, + Scene::Gizmos => Scene::Shapes, } } } @@ -265,3 +269,18 @@ mod sprite { )); } } + +mod gizmos { + use bevy::{color::palettes::css::*, prelude::*}; + + pub fn setup(mut commands: Commands) { + commands.spawn((Camera2d, StateScoped(super::Scene::Gizmos))); + } + + pub fn draw_gizmos(mut gizmos: Gizmos) { + gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::new(200.0, 200.0), RED); + gizmos + .circle_2d(Isometry2d::IDENTITY, 200.0, GREEN) + .resolution(64); + } +} diff --git a/examples/testbed/3d.rs b/examples/testbed/3d.rs index 5b35b945c5..6a07f6fae9 100644 --- a/examples/testbed/3d.rs +++ b/examples/testbed/3d.rs @@ -15,7 +15,9 @@ fn main() { .add_systems(OnEnter(Scene::Bloom), bloom::setup) .add_systems(OnEnter(Scene::Gltf), gltf::setup) .add_systems(OnEnter(Scene::Animation), animation::setup) - .add_systems(Update, switch_scene); + .add_systems(OnEnter(Scene::Gizmos), gizmos::setup) + .add_systems(Update, switch_scene) + .add_systems(Update, gizmos::draw_gizmos.run_if(in_state(Scene::Gizmos))); #[cfg(feature = "bevy_ci_testing")] app.add_systems(Update, helpers::switch_scene_in_ci::); @@ -31,6 +33,7 @@ enum Scene { Bloom, Gltf, Animation, + Gizmos, } impl Next for Scene { @@ -39,7 +42,8 @@ impl Next for Scene { Scene::Light => Scene::Bloom, Scene::Bloom => Scene::Gltf, Scene::Gltf => Scene::Animation, - Scene::Animation => Scene::Light, + Scene::Animation => Scene::Gizmos, + Scene::Gizmos => Scene::Light, } } } @@ -298,3 +302,25 @@ mod animation { } } } + +mod gizmos { + use bevy::{color::palettes::css::*, prelude::*}; + + pub fn setup(mut commands: Commands) { + commands.spawn(( + Camera3d::default(), + Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y), + StateScoped(super::Scene::Gizmos), + )); + } + + pub fn draw_gizmos(mut gizmos: Gizmos) { + gizmos.cuboid( + Transform::from_translation(Vec3::X * 2.0).with_scale(Vec3::splat(2.0)), + RED, + ); + gizmos + .sphere(Isometry3d::from_translation(Vec3::X * -2.0), 1.0, GREEN) + .resolution(30_000 / 3); + } +}