don't use bevy_pbr for base bevy_gizmos plugin (#17581)
# Objective This PR enables `bevy_gizmos` to be used without `bevy_pbr`, for user who want to create their custom mesh rendering logic. It can also be useful for user who just want to use bevy for drawing lines (why not). This work is part of a bigger effort to make the bevy rendering pipeline more modular. I would like to contribute an exemple to render custom meshes without `bevy_pbr`. Something like [this](https://github.com/rambip/plant-mesh/blob/main/src/shader/mod.rs) ## Solution Now, `bevy_pbr` is an optional dependency, and used only to debug lights. I query the `ViewUniforms` manually, instead of using `bevy_pbr` to get the heavy `MeshViewLayout` ## Testing I'm not used to testing with bevy at all, but I was able to use successfully in my project. It might break for some different mesh pipelines, but I don't think so. --- ## Showcase  So nice ... ## Migration Guide I don't think there is any breaking change # Remaining work Before merging it, it would be useful to: - rewrite the `pipeline_2d.rs` logic to remove the `bevy_sprite` depedency too - move `view.rs` to `bevy_render`, so that it can be used in a more modular way. ~~- include the most recent changes from 0.16~~ --------- Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
This commit is contained in:
parent
cdef139710
commit
b574599444
@ -16,7 +16,6 @@ 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" }
|
||||
|
@ -2,10 +2,7 @@
|
||||
|
||||
pub use bevy_gizmos_macros::GizmoConfigGroup;
|
||||
|
||||
#[cfg(all(
|
||||
feature = "bevy_render",
|
||||
any(feature = "bevy_pbr", feature = "bevy_sprite")
|
||||
))]
|
||||
#[cfg(feature = "bevy_render")]
|
||||
use {crate::GizmoAsset, bevy_asset::Handle, bevy_ecs::component::Component};
|
||||
|
||||
use bevy_ecs::{reflect::ReflectResource, resource::Resource};
|
||||
@ -238,10 +235,7 @@ impl Default for GizmoLineConfig {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "bevy_render",
|
||||
any(feature = "bevy_pbr", feature = "bevy_sprite")
|
||||
))]
|
||||
#[cfg(feature = "bevy_render")]
|
||||
#[derive(Component)]
|
||||
pub(crate) struct GizmoMeshConfig {
|
||||
pub line_perspective: bool,
|
||||
|
@ -26,10 +26,8 @@ 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,
|
||||
}
|
||||
|
||||
@ -46,13 +44,16 @@ 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(all(feature = "bevy_sprite", feature = "bevy_render"))]
|
||||
#[cfg(feature = "bevy_render")]
|
||||
mod pipeline_2d;
|
||||
#[cfg(all(feature = "bevy_pbr", feature = "bevy_render"))]
|
||||
|
||||
#[cfg(feature = "bevy_render")]
|
||||
mod pipeline_3d;
|
||||
|
||||
/// The gizmos prelude.
|
||||
@ -85,13 +86,12 @@ use bevy_ecs::{
|
||||
schedule::{IntoSystemConfigs, SystemSet},
|
||||
system::{Res, ResMut},
|
||||
};
|
||||
use bevy_math::{Vec3, Vec4};
|
||||
use bevy_math::Vec4;
|
||||
use bevy_reflect::TypePath;
|
||||
#[cfg(feature = "bevy_render")]
|
||||
use view::OnlyViewLayout;
|
||||
|
||||
#[cfg(all(
|
||||
feature = "bevy_render",
|
||||
any(feature = "bevy_pbr", feature = "bevy_sprite")
|
||||
))]
|
||||
#[cfg(feature = "bevy_render")]
|
||||
use crate::config::GizmoMeshConfig;
|
||||
|
||||
use crate::{config::ErasedGizmoConfigGroup, gizmos::GizmoBuffer};
|
||||
@ -125,10 +125,7 @@ use {
|
||||
bytemuck::cast_slice,
|
||||
};
|
||||
|
||||
#[cfg(all(
|
||||
feature = "bevy_render",
|
||||
any(feature = "bevy_pbr", feature = "bevy_sprite"),
|
||||
))]
|
||||
#[cfg(feature = "bevy_render")]
|
||||
use bevy_render::render_resource::{VertexAttribute, VertexBufferLayout, VertexStepMode};
|
||||
use bevy_time::Fixed;
|
||||
use bevy_utils::TypeIdMap;
|
||||
@ -146,9 +143,10 @@ const LINE_SHADER_HANDLE: Handle<Shader> = weak_handle!("15dc5869-ad30-4664-b35a
|
||||
const LINE_JOINT_SHADER_HANDLE: Handle<Shader> =
|
||||
weak_handle!("7b5bdda5-df81-4711-a6cf-e587700de6f2");
|
||||
|
||||
/// A [`Plugin`] that provides an immediate mode drawing api for visual debugging.
|
||||
/// A [`Plugin`] for the [`RenderApp`] that provides an immediate mode drawing api for visual debugging.
|
||||
///
|
||||
/// Requires to be loaded after [`PbrPlugin`](bevy_pbr::PbrPlugin) or [`SpritePlugin`](bevy_sprite::SpritePlugin).
|
||||
/// Additionally, it can support debugging light when the `bevy_pbr` feature is enabled,
|
||||
/// see [`LightGizmoPlugin`]
|
||||
#[derive(Default)]
|
||||
pub struct GizmoPlugin;
|
||||
|
||||
@ -189,19 +187,8 @@ impl Plugin for GizmoPlugin {
|
||||
);
|
||||
|
||||
render_app.add_systems(ExtractSchedule, (extract_gizmo_data, extract_linegizmos));
|
||||
|
||||
#[cfg(feature = "bevy_sprite")]
|
||||
if app.is_plugin_added::<bevy_sprite::SpritePlugin>() {
|
||||
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::<bevy_pbr::PbrPlugin>() {
|
||||
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?");
|
||||
}
|
||||
app.add_plugins(pipeline_3d::LineGizmo3dPlugin)
|
||||
.add_plugins(pipeline_2d::LineGizmo2dPlugin);
|
||||
} else {
|
||||
tracing::warn!("bevy_render feature is enabled but RenderApp was not detected. Are you sure you loaded GizmoPlugin after RenderPlugin?");
|
||||
}
|
||||
@ -222,7 +209,9 @@ impl Plugin for GizmoPlugin {
|
||||
),
|
||||
);
|
||||
|
||||
render_app.insert_resource(LineGizmoUniformBindgroupLayout {
|
||||
render_app
|
||||
.init_resource::<OnlyViewLayout>()
|
||||
.insert_resource(LineGizmoUniformBindgroupLayout {
|
||||
layout: line_layout,
|
||||
});
|
||||
}
|
||||
@ -474,7 +463,6 @@ 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,
|
||||
@ -503,7 +491,7 @@ struct LineGizmoUniform {
|
||||
line_scale: f32,
|
||||
/// WebGL2 structs must be 16 byte aligned.
|
||||
#[cfg(feature = "webgl")]
|
||||
_padding: Vec3,
|
||||
_padding: bevy_math::Vec3,
|
||||
}
|
||||
|
||||
/// A collection of gizmos.
|
||||
@ -634,7 +622,7 @@ impl<const I: usize, P: PhaseItem> RenderCommand<P> for SetLineGizmoBindGroup<I>
|
||||
#[inline]
|
||||
fn render<'w>(
|
||||
_item: &P,
|
||||
_view: ROQueryItem<'w, Self::ViewQuery>,
|
||||
_views: ROQueryItem<'w, Self::ViewQuery>,
|
||||
uniform_index: Option<ROQueryItem<'w, Self::ItemQuery>>,
|
||||
bind_group: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
@ -653,10 +641,7 @@ impl<const I: usize, P: PhaseItem> RenderCommand<P> for SetLineGizmoBindGroup<I>
|
||||
|
||||
#[cfg(feature = "bevy_render")]
|
||||
struct DrawLineGizmo<const STRIP: bool>;
|
||||
#[cfg(all(
|
||||
feature = "bevy_render",
|
||||
any(feature = "bevy_pbr", feature = "bevy_sprite")
|
||||
))]
|
||||
#[cfg(feature = "bevy_render")]
|
||||
impl<P: PhaseItem, const STRIP: bool> RenderCommand<P> for DrawLineGizmo<STRIP> {
|
||||
type Param = SRes<RenderAssets<GpuLineGizmo>>;
|
||||
type ViewQuery = ();
|
||||
@ -716,10 +701,7 @@ impl<P: PhaseItem, const STRIP: bool> RenderCommand<P> for DrawLineGizmo<STRIP>
|
||||
|
||||
#[cfg(feature = "bevy_render")]
|
||||
struct DrawLineJointGizmo;
|
||||
#[cfg(all(
|
||||
feature = "bevy_render",
|
||||
any(feature = "bevy_pbr", feature = "bevy_sprite")
|
||||
))]
|
||||
#[cfg(feature = "bevy_render")]
|
||||
impl<P: PhaseItem> RenderCommand<P> for DrawLineJointGizmo {
|
||||
type Param = SRes<RenderAssets<GpuLineGizmo>>;
|
||||
type ViewQuery = ();
|
||||
@ -789,10 +771,7 @@ impl<P: PhaseItem> RenderCommand<P> for DrawLineJointGizmo {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "bevy_render",
|
||||
any(feature = "bevy_pbr", feature = "bevy_sprite")
|
||||
))]
|
||||
#[cfg(feature = "bevy_render")]
|
||||
fn line_gizmo_vertex_buffer_layouts(strip: bool) -> Vec<VertexBufferLayout> {
|
||||
use VertexFormat::*;
|
||||
let mut position_layout = VertexBufferLayout {
|
||||
@ -847,10 +826,7 @@ fn line_gizmo_vertex_buffer_layouts(strip: bool) -> Vec<VertexBufferLayout> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "bevy_render",
|
||||
any(feature = "bevy_pbr", feature = "bevy_sprite")
|
||||
))]
|
||||
#[cfg(feature = "bevy_render")]
|
||||
fn line_joint_gizmo_vertex_buffer_layouts() -> Vec<VertexBufferLayout> {
|
||||
use VertexFormat::*;
|
||||
let mut position_layout = VertexBufferLayout {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::view::{OnlyViewLayout, SetViewBindGroup};
|
||||
use crate::{
|
||||
config::{GizmoLineJoint, GizmoLineStyle, GizmoMeshConfig},
|
||||
line_gizmo_vertex_buffer_layouts, line_joint_gizmo_vertex_buffer_layouts, DrawLineGizmo,
|
||||
@ -10,7 +11,7 @@ use bevy_core_pipeline::core_2d::{Transparent2d, CORE_2D_DEPTH_FORMAT};
|
||||
use bevy_ecs::{
|
||||
prelude::Entity,
|
||||
resource::Resource,
|
||||
schedule::{IntoSystemConfigs, IntoSystemSetConfigs},
|
||||
schedule::IntoSystemConfigs,
|
||||
system::{Query, Res, ResMut},
|
||||
world::{FromWorld, World},
|
||||
};
|
||||
@ -25,9 +26,8 @@ use bevy_render::{
|
||||
},
|
||||
render_resource::*,
|
||||
view::{ExtractedView, Msaa, RenderLayers, ViewTarget},
|
||||
Render, RenderApp, RenderSet,
|
||||
Render, RenderApp,
|
||||
};
|
||||
use bevy_sprite::{Mesh2dPipeline, Mesh2dPipelineKey, SetMesh2dViewBindGroup};
|
||||
use tracing::error;
|
||||
|
||||
pub struct LineGizmo2dPlugin;
|
||||
@ -44,15 +44,6 @@ impl Plugin for LineGizmo2dPlugin {
|
||||
.add_render_command::<Transparent2d, DrawLineJointGizmo2d>()
|
||||
.init_resource::<SpecializedRenderPipelines<LineGizmoPipeline>>()
|
||||
.init_resource::<SpecializedRenderPipelines<LineJointGizmoPipeline>>()
|
||||
.configure_sets(
|
||||
Render,
|
||||
GizmoRenderSystem::QueueLineGizmos2d
|
||||
.in_set(RenderSet::Queue)
|
||||
.ambiguous_with(bevy_sprite::queue_sprites)
|
||||
.ambiguous_with(
|
||||
bevy_sprite::queue_material2d_meshes::<bevy_sprite::ColorMaterial>,
|
||||
),
|
||||
)
|
||||
.add_systems(
|
||||
Render,
|
||||
(queue_line_gizmos_2d, queue_line_joint_gizmos_2d)
|
||||
@ -73,14 +64,15 @@ impl Plugin for LineGizmo2dPlugin {
|
||||
|
||||
#[derive(Clone, Resource)]
|
||||
struct LineGizmoPipeline {
|
||||
mesh_pipeline: Mesh2dPipeline,
|
||||
view_layout: BindGroupLayout,
|
||||
uniform_layout: BindGroupLayout,
|
||||
}
|
||||
|
||||
impl FromWorld for LineGizmoPipeline {
|
||||
fn from_world(render_world: &mut World) -> Self {
|
||||
let view_layout = render_world.resource::<OnlyViewLayout>().0.clone();
|
||||
LineGizmoPipeline {
|
||||
mesh_pipeline: render_world.resource::<Mesh2dPipeline>().clone(),
|
||||
view_layout,
|
||||
uniform_layout: render_world
|
||||
.resource::<LineGizmoUniformBindgroupLayout>()
|
||||
.layout
|
||||
@ -91,7 +83,8 @@ impl FromWorld for LineGizmoPipeline {
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
struct LineGizmoPipelineKey {
|
||||
mesh_key: Mesh2dPipelineKey,
|
||||
hdr: bool,
|
||||
msaa: Msaa,
|
||||
strip: bool,
|
||||
line_style: GizmoLineStyle,
|
||||
}
|
||||
@ -100,7 +93,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline {
|
||||
type Key = LineGizmoPipelineKey;
|
||||
|
||||
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
|
||||
let format = if key.mesh_key.contains(Mesh2dPipelineKey::HDR) {
|
||||
let format = if key.hdr {
|
||||
ViewTarget::TEXTURE_FORMAT_HDR
|
||||
} else {
|
||||
TextureFormat::bevy_default()
|
||||
@ -111,10 +104,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline {
|
||||
"SIXTEEN_BYTE_ALIGNMENT".into(),
|
||||
];
|
||||
|
||||
let layout = vec![
|
||||
self.mesh_pipeline.view_layout.clone(),
|
||||
self.uniform_layout.clone(),
|
||||
];
|
||||
let layout = vec![self.view_layout.clone(), self.uniform_layout.clone()];
|
||||
|
||||
let fragment_entry_point = match key.line_style {
|
||||
GizmoLineStyle::Solid => "fragment_solid",
|
||||
@ -158,7 +148,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline {
|
||||
},
|
||||
}),
|
||||
multisample: MultisampleState {
|
||||
count: key.mesh_key.msaa_samples(),
|
||||
count: key.msaa.samples(),
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
@ -171,14 +161,15 @@ impl SpecializedRenderPipeline for LineGizmoPipeline {
|
||||
|
||||
#[derive(Clone, Resource)]
|
||||
struct LineJointGizmoPipeline {
|
||||
mesh_pipeline: Mesh2dPipeline,
|
||||
view_layout: BindGroupLayout,
|
||||
uniform_layout: BindGroupLayout,
|
||||
}
|
||||
|
||||
impl FromWorld for LineJointGizmoPipeline {
|
||||
fn from_world(render_world: &mut World) -> Self {
|
||||
let view_layout = render_world.resource::<OnlyViewLayout>().0.clone();
|
||||
LineJointGizmoPipeline {
|
||||
mesh_pipeline: render_world.resource::<Mesh2dPipeline>().clone(),
|
||||
view_layout,
|
||||
uniform_layout: render_world
|
||||
.resource::<LineGizmoUniformBindgroupLayout>()
|
||||
.layout
|
||||
@ -189,7 +180,8 @@ impl FromWorld for LineJointGizmoPipeline {
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
struct LineJointGizmoPipelineKey {
|
||||
mesh_key: Mesh2dPipelineKey,
|
||||
hdr: bool,
|
||||
msaa: Msaa,
|
||||
joints: GizmoLineJoint,
|
||||
}
|
||||
|
||||
@ -197,7 +189,7 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline {
|
||||
type Key = LineJointGizmoPipelineKey;
|
||||
|
||||
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
|
||||
let format = if key.mesh_key.contains(Mesh2dPipelineKey::HDR) {
|
||||
let format = if key.hdr {
|
||||
ViewTarget::TEXTURE_FORMAT_HDR
|
||||
} else {
|
||||
TextureFormat::bevy_default()
|
||||
@ -208,10 +200,7 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline {
|
||||
"SIXTEEN_BYTE_ALIGNMENT".into(),
|
||||
];
|
||||
|
||||
let layout = vec![
|
||||
self.mesh_pipeline.view_layout.clone(),
|
||||
self.uniform_layout.clone(),
|
||||
];
|
||||
let layout = vec![self.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.");
|
||||
@ -259,7 +248,7 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline {
|
||||
},
|
||||
}),
|
||||
multisample: MultisampleState {
|
||||
count: key.mesh_key.msaa_samples(),
|
||||
count: key.msaa.samples(),
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
@ -272,19 +261,19 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline {
|
||||
|
||||
type DrawLineGizmo2d = (
|
||||
SetItemPipeline,
|
||||
SetMesh2dViewBindGroup<0>,
|
||||
SetViewBindGroup<0>,
|
||||
SetLineGizmoBindGroup<1>,
|
||||
DrawLineGizmo<false>,
|
||||
);
|
||||
type DrawLineGizmo2dStrip = (
|
||||
SetItemPipeline,
|
||||
SetMesh2dViewBindGroup<0>,
|
||||
SetViewBindGroup<0>,
|
||||
SetLineGizmoBindGroup<1>,
|
||||
DrawLineGizmo<true>,
|
||||
);
|
||||
type DrawLineJointGizmo2d = (
|
||||
SetItemPipeline,
|
||||
SetMesh2dViewBindGroup<0>,
|
||||
SetViewBindGroup<0>,
|
||||
SetLineGizmoBindGroup<1>,
|
||||
DrawLineJointGizmo,
|
||||
);
|
||||
@ -311,9 +300,6 @@ 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) {
|
||||
@ -329,7 +315,8 @@ fn queue_line_gizmos_2d(
|
||||
&pipeline_cache,
|
||||
&pipeline,
|
||||
LineGizmoPipelineKey {
|
||||
mesh_key,
|
||||
msaa: *msaa,
|
||||
hdr: view.hdr,
|
||||
strip: false,
|
||||
line_style: config.line_style,
|
||||
},
|
||||
@ -350,7 +337,8 @@ fn queue_line_gizmos_2d(
|
||||
&pipeline_cache,
|
||||
&pipeline,
|
||||
LineGizmoPipelineKey {
|
||||
mesh_key,
|
||||
msaa: *msaa,
|
||||
hdr: view.hdr,
|
||||
strip: true,
|
||||
line_style: config.line_style,
|
||||
},
|
||||
@ -389,9 +377,6 @@ 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) {
|
||||
@ -410,7 +395,8 @@ fn queue_line_joint_gizmos_2d(
|
||||
&pipeline_cache,
|
||||
&pipeline,
|
||||
LineJointGizmoPipelineKey {
|
||||
mesh_key,
|
||||
msaa: *msaa,
|
||||
hdr: view.hdr,
|
||||
joints: config.line_joints,
|
||||
},
|
||||
);
|
||||
|
@ -1,26 +1,22 @@
|
||||
use crate::{
|
||||
config::{GizmoLineJoint, GizmoLineStyle, GizmoMeshConfig},
|
||||
line_gizmo_vertex_buffer_layouts, line_joint_gizmo_vertex_buffer_layouts, DrawLineGizmo,
|
||||
DrawLineJointGizmo, GizmoRenderSystem, GpuLineGizmo, LineGizmoUniformBindgroupLayout,
|
||||
SetLineGizmoBindGroup, LINE_JOINT_SHADER_HANDLE, LINE_SHADER_HANDLE,
|
||||
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,
|
||||
};
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_core_pipeline::{
|
||||
core_3d::{Transparent3d, CORE_3D_DEPTH_FORMAT},
|
||||
oit::OrderIndependentTransparencySettings,
|
||||
prepass::{DeferredPrepass, DepthPrepass, MotionVectorPrepass, NormalPrepass},
|
||||
};
|
||||
use bevy_core_pipeline::core_3d::{Transparent3d, CORE_3D_DEPTH_FORMAT};
|
||||
use bevy_ecs::schedule::IntoSystemConfigs;
|
||||
|
||||
use bevy_ecs::{
|
||||
prelude::Entity,
|
||||
query::Has,
|
||||
resource::Resource,
|
||||
schedule::{IntoSystemConfigs, IntoSystemSetConfigs},
|
||||
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},
|
||||
@ -33,7 +29,6 @@ use bevy_render::{
|
||||
Render, RenderApp, RenderSet,
|
||||
};
|
||||
use tracing::error;
|
||||
|
||||
pub struct LineGizmo3dPlugin;
|
||||
impl Plugin for LineGizmo3dPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
@ -47,15 +42,13 @@ impl Plugin for LineGizmo3dPlugin {
|
||||
.add_render_command::<Transparent3d, DrawLineJointGizmo3d>()
|
||||
.init_resource::<SpecializedRenderPipelines<LineGizmoPipeline>>()
|
||||
.init_resource::<SpecializedRenderPipelines<LineJointGizmoPipeline>>()
|
||||
.configure_sets(
|
||||
Render,
|
||||
GizmoRenderSystem::QueueLineGizmos3d
|
||||
.in_set(RenderSet::Queue)
|
||||
.ambiguous_with(bevy_pbr::queue_material_meshes::<bevy_pbr::StandardMaterial>),
|
||||
)
|
||||
.add_systems(
|
||||
Render,
|
||||
(queue_line_gizmos_3d, queue_line_joint_gizmos_3d)
|
||||
(
|
||||
queue_line_gizmos_3d,
|
||||
queue_line_joint_gizmos_3d,
|
||||
prepare_view_bind_groups.in_set(RenderSet::Prepare),
|
||||
)
|
||||
.in_set(GizmoRenderSystem::QueueLineGizmos3d)
|
||||
.after(prepare_assets::<GpuLineGizmo>),
|
||||
);
|
||||
@ -72,15 +65,17 @@ impl Plugin for LineGizmo3dPlugin {
|
||||
}
|
||||
|
||||
#[derive(Clone, Resource)]
|
||||
struct LineGizmoPipeline {
|
||||
mesh_pipeline: MeshPipeline,
|
||||
pub(crate) struct LineGizmoPipeline {
|
||||
view_layout: BindGroupLayout,
|
||||
uniform_layout: BindGroupLayout,
|
||||
}
|
||||
|
||||
impl FromWorld for LineGizmoPipeline {
|
||||
fn from_world(render_world: &mut World) -> Self {
|
||||
let view_layout = render_world.resource::<OnlyViewLayout>().0.clone();
|
||||
|
||||
LineGizmoPipeline {
|
||||
mesh_pipeline: render_world.resource::<MeshPipeline>().clone(),
|
||||
view_layout,
|
||||
uniform_layout: render_world
|
||||
.resource::<LineGizmoUniformBindgroupLayout>()
|
||||
.layout
|
||||
@ -90,8 +85,9 @@ impl FromWorld for LineGizmoPipeline {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
struct LineGizmoPipelineKey {
|
||||
view_key: MeshPipelineKey,
|
||||
pub(crate) struct LineGizmoPipelineKey {
|
||||
msaa: Msaa,
|
||||
hdr: bool,
|
||||
strip: bool,
|
||||
perspective: bool,
|
||||
line_style: GizmoLineStyle,
|
||||
@ -110,18 +106,13 @@ impl SpecializedRenderPipeline for LineGizmoPipeline {
|
||||
shader_defs.push("PERSPECTIVE".into());
|
||||
}
|
||||
|
||||
let format = if key.view_key.contains(MeshPipelineKey::HDR) {
|
||||
let format = if key.hdr {
|
||||
ViewTarget::TEXTURE_FORMAT_HDR
|
||||
} else {
|
||||
TextureFormat::bevy_default()
|
||||
};
|
||||
|
||||
let view_layout = self
|
||||
.mesh_pipeline
|
||||
.get_view_layout(key.view_key.into())
|
||||
.clone();
|
||||
|
||||
let layout = vec![view_layout, self.uniform_layout.clone()];
|
||||
let layout = vec![self.view_layout.clone(), self.uniform_layout.clone()];
|
||||
|
||||
let fragment_entry_point = match key.line_style {
|
||||
GizmoLineStyle::Solid => "fragment_solid",
|
||||
@ -156,7 +147,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline {
|
||||
bias: DepthBiasState::default(),
|
||||
}),
|
||||
multisample: MultisampleState {
|
||||
count: key.view_key.msaa_samples(),
|
||||
count: key.msaa.samples(),
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
@ -169,14 +160,16 @@ impl SpecializedRenderPipeline for LineGizmoPipeline {
|
||||
|
||||
#[derive(Clone, Resource)]
|
||||
struct LineJointGizmoPipeline {
|
||||
mesh_pipeline: MeshPipeline,
|
||||
view_layout: BindGroupLayout,
|
||||
uniform_layout: BindGroupLayout,
|
||||
}
|
||||
|
||||
impl FromWorld for LineJointGizmoPipeline {
|
||||
fn from_world(render_world: &mut World) -> Self {
|
||||
let view_layout = render_world.resource::<OnlyViewLayout>().0.clone();
|
||||
|
||||
LineJointGizmoPipeline {
|
||||
mesh_pipeline: render_world.resource::<MeshPipeline>().clone(),
|
||||
view_layout,
|
||||
uniform_layout: render_world
|
||||
.resource::<LineGizmoUniformBindgroupLayout>()
|
||||
.layout
|
||||
@ -187,7 +180,8 @@ impl FromWorld for LineJointGizmoPipeline {
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
struct LineJointGizmoPipelineKey {
|
||||
view_key: MeshPipelineKey,
|
||||
msaa: Msaa,
|
||||
hdr: bool,
|
||||
perspective: bool,
|
||||
joints: GizmoLineJoint,
|
||||
}
|
||||
@ -205,18 +199,13 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline {
|
||||
shader_defs.push("PERSPECTIVE".into());
|
||||
}
|
||||
|
||||
let format = if key.view_key.contains(MeshPipelineKey::HDR) {
|
||||
let format = if key.hdr {
|
||||
ViewTarget::TEXTURE_FORMAT_HDR
|
||||
} else {
|
||||
TextureFormat::bevy_default()
|
||||
};
|
||||
|
||||
let view_layout = self
|
||||
.mesh_pipeline
|
||||
.get_view_layout(key.view_key.into())
|
||||
.clone();
|
||||
|
||||
let layout = vec![view_layout, self.uniform_layout.clone()];
|
||||
let layout = vec![self.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.");
|
||||
@ -255,7 +244,7 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline {
|
||||
bias: DepthBiasState::default(),
|
||||
}),
|
||||
multisample: MultisampleState {
|
||||
count: key.view_key.msaa_samples(),
|
||||
count: key.msaa.samples(),
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
@ -268,19 +257,19 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline {
|
||||
|
||||
type DrawLineGizmo3d = (
|
||||
SetItemPipeline,
|
||||
SetMeshViewBindGroup<0>,
|
||||
SetViewBindGroup<0>,
|
||||
SetLineGizmoBindGroup<1>,
|
||||
DrawLineGizmo<false>,
|
||||
);
|
||||
type DrawLineGizmo3dStrip = (
|
||||
SetItemPipeline,
|
||||
SetMeshViewBindGroup<0>,
|
||||
SetViewBindGroup<0>,
|
||||
SetLineGizmoBindGroup<1>,
|
||||
DrawLineGizmo<true>,
|
||||
);
|
||||
type DrawLineJointGizmo3d = (
|
||||
SetItemPipeline,
|
||||
SetMeshViewBindGroup<0>,
|
||||
SetViewBindGroup<0>,
|
||||
SetLineGizmoBindGroup<1>,
|
||||
DrawLineJointGizmo,
|
||||
);
|
||||
@ -293,18 +282,7 @@ fn queue_line_gizmos_3d(
|
||||
line_gizmos: Query<(Entity, &MainEntity, &GizmoMeshConfig)>,
|
||||
line_gizmo_assets: Res<RenderAssets<GpuLineGizmo>>,
|
||||
mut transparent_render_phases: ResMut<ViewSortedRenderPhases<Transparent3d>>,
|
||||
views: Query<(
|
||||
&ExtractedView,
|
||||
&Msaa,
|
||||
Option<&RenderLayers>,
|
||||
(
|
||||
Has<NormalPrepass>,
|
||||
Has<DepthPrepass>,
|
||||
Has<MotionVectorPrepass>,
|
||||
Has<DeferredPrepass>,
|
||||
Has<OrderIndependentTransparencySettings>,
|
||||
),
|
||||
)>,
|
||||
views: Query<(&ExtractedView, &Msaa, Option<&RenderLayers>)>,
|
||||
) {
|
||||
let draw_function = draw_functions.read().get_id::<DrawLineGizmo3d>().unwrap();
|
||||
let draw_function_strip = draw_functions
|
||||
@ -312,13 +290,7 @@ fn queue_line_gizmos_3d(
|
||||
.get_id::<DrawLineGizmo3dStrip>()
|
||||
.unwrap();
|
||||
|
||||
for (
|
||||
view,
|
||||
msaa,
|
||||
render_layers,
|
||||
(normal_prepass, depth_prepass, motion_vector_prepass, deferred_prepass, oit),
|
||||
) in &views
|
||||
{
|
||||
for (view, msaa, render_layers) in &views {
|
||||
let Some(transparent_phase) = transparent_render_phases.get_mut(&view.retained_view_entity)
|
||||
else {
|
||||
continue;
|
||||
@ -326,29 +298,6 @@ 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;
|
||||
@ -363,7 +312,8 @@ fn queue_line_gizmos_3d(
|
||||
&pipeline_cache,
|
||||
&pipeline,
|
||||
LineGizmoPipelineKey {
|
||||
view_key,
|
||||
msaa: *msaa,
|
||||
hdr: view.hdr,
|
||||
strip: false,
|
||||
perspective: config.line_perspective,
|
||||
line_style: config.line_style,
|
||||
@ -385,7 +335,8 @@ fn queue_line_gizmos_3d(
|
||||
&pipeline_cache,
|
||||
&pipeline,
|
||||
LineGizmoPipelineKey {
|
||||
view_key,
|
||||
msaa: *msaa,
|
||||
hdr: view.hdr,
|
||||
strip: true,
|
||||
perspective: config.line_perspective,
|
||||
line_style: config.line_style,
|
||||
@ -413,30 +364,14 @@ fn queue_line_joint_gizmos_3d(
|
||||
line_gizmos: Query<(Entity, &MainEntity, &GizmoMeshConfig)>,
|
||||
line_gizmo_assets: Res<RenderAssets<GpuLineGizmo>>,
|
||||
mut transparent_render_phases: ResMut<ViewSortedRenderPhases<Transparent3d>>,
|
||||
views: Query<(
|
||||
&ExtractedView,
|
||||
&Msaa,
|
||||
Option<&RenderLayers>,
|
||||
(
|
||||
Has<NormalPrepass>,
|
||||
Has<DepthPrepass>,
|
||||
Has<MotionVectorPrepass>,
|
||||
Has<DeferredPrepass>,
|
||||
),
|
||||
)>,
|
||||
mut views: Query<(&ExtractedView, &Msaa, Option<&RenderLayers>)>,
|
||||
) {
|
||||
let draw_function = draw_functions
|
||||
.read()
|
||||
.get_id::<DrawLineJointGizmo3d>()
|
||||
.unwrap();
|
||||
|
||||
for (
|
||||
view,
|
||||
msaa,
|
||||
render_layers,
|
||||
(normal_prepass, depth_prepass, motion_vector_prepass, deferred_prepass),
|
||||
) in &views
|
||||
{
|
||||
for (view, msaa, render_layers) in &mut views {
|
||||
let Some(transparent_phase) = transparent_render_phases.get_mut(&view.retained_view_entity)
|
||||
else {
|
||||
continue;
|
||||
@ -444,25 +379,6 @@ 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;
|
||||
@ -480,7 +396,8 @@ fn queue_line_joint_gizmos_3d(
|
||||
&pipeline_cache,
|
||||
&pipeline,
|
||||
LineJointGizmoPipelineKey {
|
||||
view_key,
|
||||
msaa: *msaa,
|
||||
hdr: view.hdr,
|
||||
perspective: config.line_perspective,
|
||||
joints: config.line_joints,
|
||||
},
|
||||
|
@ -143,7 +143,6 @@ 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,
|
||||
|
90
crates/bevy_gizmos/src/view.rs
Normal file
90
crates/bevy_gizmos/src/view.rs
Normal file
@ -0,0 +1,90 @@
|
||||
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::<RenderDevice>();
|
||||
|
||||
let view_layout =
|
||||
render_device.create_bind_group_layout("mesh_view_layout", &view_layout_entries());
|
||||
|
||||
Self(view_layout)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct SetViewBindGroup<const I: usize>;
|
||||
|
||||
impl<const I: usize, P: PhaseItem> RenderCommand<P> for SetViewBindGroup<I> {
|
||||
type Param = ();
|
||||
|
||||
type ViewQuery = Read<ViewBindGroup>;
|
||||
|
||||
type ItemQuery = ();
|
||||
|
||||
fn render<'w>(
|
||||
_: &P,
|
||||
view: bevy_ecs::query::ROQueryItem<'w, Self::ViewQuery>,
|
||||
_: Option<bevy_ecs::query::ROQueryItem<'w, Self::ItemQuery>>,
|
||||
_: 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<RenderDevice>,
|
||||
view_uniforms: Res<ViewUniforms>,
|
||||
layout: Res<OnlyViewLayout>,
|
||||
views: Query<Entity, With<ExtractedView>>,
|
||||
) {
|
||||
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<BindGroupLayoutEntry> {
|
||||
DynamicBindGroupLayoutEntries::new_with_indices(
|
||||
ShaderStages::FRAGMENT,
|
||||
((
|
||||
0,
|
||||
uniform_buffer::<ViewUniform>(true).visibility(ShaderStages::VERTEX_FRAGMENT),
|
||||
),),
|
||||
)
|
||||
.to_vec()
|
||||
}
|
@ -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_sprite", "bevy_image"]
|
||||
bevy_sprite = ["dep:bevy_sprite", "bevy_gizmos", "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"]
|
||||
|
Loading…
Reference in New Issue
Block a user