diff options
| -rw-r--r-- | crates/rapier_testbed2d-f64/Cargo.toml | 4 | ||||
| -rw-r--r-- | crates/rapier_testbed2d/Cargo.toml | 4 | ||||
| -rw-r--r-- | crates/rapier_testbed3d-f64/Cargo.toml | 4 | ||||
| -rw-r--r-- | crates/rapier_testbed3d/Cargo.toml | 4 | ||||
| -rw-r--r-- | src_testbed/debug_render.rs | 19 | ||||
| -rw-r--r-- | src_testbed/lib.rs | 2 | ||||
| -rw-r--r-- | src_testbed/lines/debuglines.wgsl | 53 | ||||
| -rw-r--r-- | src_testbed/lines/debuglines2d.wgsl | 32 | ||||
| -rw-r--r-- | src_testbed/lines/mod.rs | 389 | ||||
| -rw-r--r-- | src_testbed/lines/render_dim.rs | 340 | ||||
| -rw-r--r-- | src_testbed/testbed.rs | 6 |
11 files changed, 19 insertions, 838 deletions
diff --git a/crates/rapier_testbed2d-f64/Cargo.toml b/crates/rapier_testbed2d-f64/Cargo.toml index 7f0efb4..d906869 100644 --- a/crates/rapier_testbed2d-f64/Cargo.toml +++ b/crates/rapier_testbed2d-f64/Cargo.toml @@ -49,11 +49,11 @@ bevy_sprite = "0.11" # Dependencies for native only. [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -bevy = {version = "0.11", default-features = false, features = ["bevy_winit", "x11"]} +bevy = {version = "0.11", default-features = false, features = ["bevy_asset", "bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} # Dependencies for WASM only. [target.'cfg(target_arch = "wasm32")'.dependencies] -bevy = {version = "0.11", default-features = false, features = ["bevy_winit"]} +bevy = {version = "0.11", default-features = false, features = ["bevy_asset", "bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} #bevy_webgl2 = "0.5" [dependencies.rapier] diff --git a/crates/rapier_testbed2d/Cargo.toml b/crates/rapier_testbed2d/Cargo.toml index d891760..8bf8b26 100644 --- a/crates/rapier_testbed2d/Cargo.toml +++ b/crates/rapier_testbed2d/Cargo.toml @@ -49,11 +49,11 @@ bevy_sprite = "0.11" # Dependencies for native only. [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -bevy = {version = "0.11", default-features = false, features = ["bevy_winit", "x11"]} +bevy = {version = "0.11", default-features = false, features = ["bevy_sprite", "bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} # Dependencies for WASM only. [target.'cfg(target_arch = "wasm32")'.dependencies] -bevy = {version = "0.11", default-features = false, features = ["bevy_winit",]} +bevy = {version = "0.11", default-features = false, features = ["bevy_sprite", "bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} #bevy_webgl2 = "0.5" [dependencies.rapier] diff --git a/crates/rapier_testbed3d-f64/Cargo.toml b/crates/rapier_testbed3d-f64/Cargo.toml index ddfc890..0bfeefa 100644 --- a/crates/rapier_testbed3d-f64/Cargo.toml +++ b/crates/rapier_testbed3d-f64/Cargo.toml @@ -48,11 +48,11 @@ bevy_sprite = "0.11" # Dependencies for native only. [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -bevy = {version = "0.11", default-features = false, features = ["bevy_winit", "x11"]} +bevy = {version = "0.11", default-features = false, features = ["bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} # Dependencies for WASM only. [target.'cfg(target_arch = "wasm32")'.dependencies] -bevy = {version = "0.11", default-features = false, features = ["bevy_winit"]} +bevy = {version = "0.11", default-features = false, features = ["bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} #bevy_webgl2 = "0.5" [dependencies.rapier] diff --git a/crates/rapier_testbed3d/Cargo.toml b/crates/rapier_testbed3d/Cargo.toml index b44b075..eed41c9 100644 --- a/crates/rapier_testbed3d/Cargo.toml +++ b/crates/rapier_testbed3d/Cargo.toml @@ -52,11 +52,11 @@ bevy_sprite = "0.11" # Dependencies for native only. [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -bevy = {version = "0.11", default-features = false, features = ["bevy_winit", "x11"]} +bevy = {version = "0.11", default-features = false, features = ["bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} # Dependencies for WASM only. [target.'cfg(target_arch = "wasm32")'.dependencies] -bevy = {version = "0.11", default-features = false, features = ["bevy_winit"]} +bevy = {version = "0.11", default-features = false, features = ["bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} #bevy_webgl2 = "0.5" [dependencies.rapier] diff --git a/src_testbed/debug_render.rs b/src_testbed/debug_render.rs index 979d8ec..8e588db 100644 --- a/src_testbed/debug_render.rs +++ b/src_testbed/debug_render.rs @@ -1,5 +1,5 @@ use crate::harness::Harness; -use crate::lines::DebugLines; +use bevy::gizmos::gizmos::Gizmos; use bevy::prelude::*; use rapier::math::{Point, Real}; use rapier::pipeline::{ @@ -22,10 +22,7 @@ impl Default for RapierDebugRenderPlugin { } impl Plugin for RapierDebugRenderPlugin { fn build(&self, app: &mut App) { - app.add_plugins(crate::lines::DebugLinesPlugin::with_depth_test( - self.depth_test, - )) - .insert_resource(DebugRenderPipelineResource(DebugRenderPipeline::new( + app.insert_resource(DebugRenderPipelineResource(DebugRenderPipeline::new( Default::default(), !DebugRenderMode::RIGID_BODY_AXES & !DebugRenderMode::COLLIDER_AABBS, ))) @@ -34,25 +31,23 @@ impl Plugin for RapierDebugRenderPlugin { } struct BevyLinesRenderBackend<'a> { - lines: &'a mut DebugLines, + gizmos: Gizmos<'a>, } impl<'a> DebugRenderBackend for BevyLinesRenderBackend<'a> { #[cfg(feature = "dim2")] fn draw_line(&mut self, _: DebugRenderObject, a: Point<Real>, b: Point<Real>, color: [f32; 4]) { - self.lines.line_colored( + self.gizmos.line( [a.x as f32, a.y as f32, 1.0e-8 as f32].into(), [b.x as f32, b.y as f32, 1.0e-8 as f32].into(), - 0.0, Color::hsla(color[0], color[1], color[2], color[3]), ) } #[cfg(feature = "dim3")] fn draw_line(&mut self, _: DebugRenderObject, a: Point<Real>, b: Point<Real>, color: [f32; 4]) { - self.lines.line_colored( + self.gizmos.line( [a.x as f32, a.y as f32, a.z as f32].into(), [b.x as f32, b.y as f32, b.z as f32].into(), - 0.0, Color::hsla(color[0], color[1], color[2], color[3]), ) } @@ -61,9 +56,9 @@ impl<'a> DebugRenderBackend for BevyLinesRenderBackend<'a> { fn debug_render_scene( mut pipeline: ResMut<DebugRenderPipelineResource>, harness: NonSend<Harness>, - mut lines: ResMut<DebugLines>, + gizmos: Gizmos, ) { - let mut backend = BevyLinesRenderBackend { lines: &mut *lines }; + let mut backend = BevyLinesRenderBackend { gizmos }; pipeline.0.render( &mut backend, &harness.physics.bodies, diff --git a/src_testbed/lib.rs b/src_testbed/lib.rs index 3c87453..3702866 100644 --- a/src_testbed/lib.rs +++ b/src_testbed/lib.rs @@ -22,7 +22,7 @@ mod camera3d; mod debug_render; mod graphics; pub mod harness; -mod lines; +// mod lines; pub mod objects; pub mod physics; #[cfg(all(feature = "dim3", feature = "other-backends"))] diff --git a/src_testbed/lines/debuglines.wgsl b/src_testbed/lines/debuglines.wgsl deleted file mode 100644 index 364d9ac..0000000 --- a/src_testbed/lines/debuglines.wgsl +++ /dev/null @@ -1,53 +0,0 @@ -// This should work, but it's bugged right now so we have to use 2 shaders: https://github.com/bevyengine/bevy/issues/4011 -#ifdef LINES_3D - #import bevy_pbr::mesh_view_bind_group - //#import bevy_pbr::mesh_struct -#else - //#import bevy_sprite::mesh2d_view_bind_group -#endif - -struct Vertex { - [[location(0)]] pos: vec3<f32>; - [[location(1)]] color: u32; -}; - -struct VertexOutput { - [[builtin(position)]] clip_position: vec4<f32>; - [[location(0)]] color: vec4<f32>; -}; - -struct FragmentOutput { - [[builtin(frag_depth)]] depth: f32; - [[location(0)]] color: vec4<f32>; -}; - -[[stage(vertex)]] -fn vertex(vertex: Vertex) -> VertexOutput { - var out: VertexOutput; - out.clip_position = view.view_proj * vec4<f32>(vertex.pos, 1.0); - // https://github.com/bevyengine/bevy/blob/328c26d02c50de0bc77f0d24a376f43ba89517b1/examples/2d/mesh2d_manual.rs#L234 - // ... except the above doesn't seem to work in 3d. Not sure what's going on there. - var r = f32(vertex.color & 255u) / 255.0; - var g = f32(vertex.color >> 8u & 255u) / 255.0; - var b = f32(vertex.color >> 16u & 255u) / 255.0; - var a = f32(vertex.color >> 24u & 255u) / 255.0; - out.color = vec4<f32>(r, g, b, a); - - return out; -} - -[[stage(fragment)]] -fn fragment(in: VertexOutput) -> FragmentOutput { - var out: FragmentOutput; - -// This should be #ifdef DEPTH_TEST_ENABLED && LINES_3D, but the -// preprocessor doesn't support that yet. -// Luckily, DEPTH_TEST_ENABLED isn't set in 2d anyway. -#ifdef DEPTH_TEST_ENABLED - out.depth = in.clip_position.z; -#else - out.depth = 1.0; -#endif - out.color = in.color; - return out; -} diff --git a/src_testbed/lines/debuglines2d.wgsl b/src_testbed/lines/debuglines2d.wgsl deleted file mode 100644 index b722d8a..0000000 --- a/src_testbed/lines/debuglines2d.wgsl +++ /dev/null @@ -1,32 +0,0 @@ -#import bevy_sprite::mesh2d_view_bind_group -[[group(0), binding(0)]] -var<uniform> view: View; - -struct Vertex { - //[[location(0)]] color: vec4<f32>; - [[location(0)]] place: vec3<f32>; - [[location(1)]] color: u32; -}; - -struct VertexOutput { - [[builtin(position)]] clip_position: vec4<f32>; - [[location(0)]] color: vec4<f32>; -}; - -[[stage(vertex)]] -fn vertex(vertex: Vertex) -> VertexOutput { - var out: VertexOutput; - out.clip_position = view.view_proj * vec4<f32>(vertex.place, 1.0); - var r = f32(vertex.color & 255u) / 255.0; - var g = f32(vertex.color >> 8u & 255u) / 255.0; - var b = f32(vertex.color >> 16u & 255u) / 255.0; - var a = f32(vertex.color >> 24u & 255u) / 255.0; - out.color = vec4<f32>(r, g, b, a); - - return out; -} - -[[stage(fragment)]] -fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> { - return in.color; -} diff --git a/src_testbed/lines/mod.rs b/src_testbed/lines/mod.rs deleted file mode 100644 index c68b86e..0000000 --- a/src_testbed/lines/mod.rs +++ /dev/null @@ -1,389 +0,0 @@ -#![allow(warnings)] -use bevy::render::mesh::MeshVertexAttribute; -use bevy::render::render_resource::VertexFormat; -use bevy::render::view::NoFrustumCulling; -use bevy::render::MainWorld; -/** - * - * NOTE: this module and its submodules are only temporary. It is a copy-paste of the bevy-debug-lines - * crate: https://github.com/Toqozz/bevy_debug_lines (MIT license) - * It has been partially updated to work with bevy 0.7, but hasn’t been released yet. - * So, in the mean time, we are keeping a version here that we will replace by the - * upstream dependency once: - * 1. The version compatible with bevy 0.7 is released to crates.io. - * 2. We find a way to make the 2D version work with our examples. The problem - * only happens when running our own examples because cargo’s unification of - * features will enable the `3d` feature of `bevy_debug_lines` when running - * a `2d` example. - * - */ -use bevy::{ - asset::{Assets, HandleUntyped}, - prelude::*, - reflect::TypeUuid, - render::{ - mesh::{/*Indices,*/ Mesh, VertexAttributeValues}, - render_phase::AddRenderCommand, - render_resource::PrimitiveTopology, - render_resource::Shader, - RenderSet, - }, -}; -use bevy_pbr::{NotShadowCaster, NotShadowReceiver}; - -mod render_dim; - -// This module exists to "isolate" the `#[cfg]` attributes to this part of the -// code. Otherwise, we would pollute the code with a lot of feature -// gates-specific code. -#[cfg(feature = "dim3")] -mod dim { - pub(crate) use super::render_dim::r3d::{queue, DebugLinePipeline, DrawDebugLines}; - use bevy::{asset::Handle, render::mesh::Mesh}; - pub(crate) use bevy_core_pipeline::core_3d::Opaque3d as Phase; - - pub(crate) type MeshHandle = Handle<Mesh>; - pub(crate) fn from_handle(from: &MeshHandle) -> &Handle<Mesh> { - from - } - pub(crate) fn into_handle(from: Handle<Mesh>) -> MeshHandle { - from - } - pub(crate) const SHADER_FILE: &str = include_str!("debuglines.wgsl"); - pub(crate) const DIMMENSION: &str = "3d"; -} -#[cfg(feature = "dim2")] -mod dim { - pub(crate) use super::render_dim::r2d::{queue, DebugLinePipeline, DrawDebugLines}; - use bevy::{asset::Handle, render::mesh::Mesh}; - pub(crate) use bevy_core_pipeline::core_2d::Transparent2d as Phase; - use bevy_sprite::Mesh2dHandle; - - pub(crate) type MeshHandle = Mesh2dHandle; - pub(crate) fn from_handle(from: &MeshHandle) -> &Handle<Mesh> { - &from.0 - } - pub(crate) fn into_handle(from: Handle<Mesh>) -> MeshHandle { - Mesh2dHandle(from) - } - pub(crate) const SHADER_FILE: &str = include_str!("debuglines2d.wgsl"); - pub(crate) const DIMMENSION: &str = "2d"; -} - -// See debuglines.wgsl for explanation on 2 shaders. -//pub(crate) const SHADER_FILE: &str = include_str!("debuglines.wgsl"); -pub(crate) const DEBUG_LINES_SHADER_HANDLE: HandleUntyped = - HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 17477439189930443325); - -#[derive(Resource)] -pub(crate) struct DebugLinesConfig { - depth_test: bool, -} - -/// Bevy plugin, for initializing stuff. -/// -/// # Usage -/// -/// ```.ignore -/// use bevy::prelude::*; -/// use bevy_prototype_debug_lines::*; -/// -/// App::new() -/// .add_plugins(DefaultPlugins) -/// .add_plugin(DebugLinesPlugin::default()) -/// .run(); -/// ``` -/// -/// Alternatively, you can initialize the plugin with depth testing, so that -/// debug lines cut through geometry. To do this, use [`DebugLinesPlugin::with_depth_test(true)`]. -/// ```.ignore -/// use bevy::prelude::*; -/// use bevy_prototype_debug_lines::*; -/// -/// App::new() -/// .add_plugins(DefaultPlugins) -/// .add_plugin(DebugLinesPlugin::with_depth_test(true)) -/// .run(); -/// ``` -#[derive(Debug, Default, Clone)] -pub struct DebugLinesPlugin { - depth_test: bool, -} - -impl DebugLinesPlugin { - /// Controls whether debug lines should be drawn with depth testing enabled - /// or disabled. - /// - /// # Arguments - /// - /// * `val` - True if lines should intersect with other geometry, or false - /// if lines should always draw on top be drawn on top (the default). - pub fn with_depth_test(val: bool) -> Self { - Self { depth_test: val } - } -} -use bevy::render::render_phase::DrawFunctions; -use bevy::render::Render; -impl Plugin for DebugLinesPlugin { - fn build(&self, app: &mut App) { - use bevy::render::{render_resource::SpecializedMeshPipelines, RenderApp}; - let mut shaders = app.world.get_resource_mut::<Assets<Shader>>().unwrap(); - shaders.set_untracked( - DEBUG_LINES_SHADER_HANDLE, - Shader::from_wgsl(dim::SHADER_FILE, file!()), - ); - app.init_resource::<DebugLines>(); - - app.init_resource::<DrawFunctions<dim::Phase>>(); - - app.add_systems(Startup, setup) - .add_systems(PostUpdate, update); - - app.sub_app_mut(RenderApp) - .init_resource::<DrawFunctions<dim::Phase>>() - .add_render_command::<dim::Phase, dim::DrawDebugLines>() - .insert_resource(DebugLinesConfig { - depth_test: self.depth_test, - }) - .init_resource::<dim::DebugLinePipeline>() - .init_resource::<SpecializedMeshPipelines<dim::DebugLinePipeline>>() - .add_systems(Render, extract.in_set(RenderSet::ExtractCommands)) - .add_systems(Render, dim::queue.in_set(RenderSet::Queue)); - - info!("Loaded {} debug lines plugin.", dim::DIMMENSION); - } -} - -// Number of meshes to separate line buffers into. -// We don't really do culling currently but this is a gateway to that. -const MESH_COUNT: usize = 4; -// Maximum number of points for each individual mesh. -const MAX_POINTS_PER_MESH: usize = 2_usize.pow(16); -const _MAX_LINES_PER_MESH: usize = MAX_POINTS_PER_MESH / 2; -/// Maximum number of points. -pub const MAX_POINTS: usize = MAX_POINTS_PER_MESH * MESH_COUNT; -/// Maximum number of unique lines to draw at once. -pub const MAX_LINES: usize = MAX_POINTS / 2; - -const ATTRIBUTE_COLOR: MeshVertexAttribute = - MeshVertexAttribute::new("Vertex_Color", 1, VertexFormat::Uint32); - -fn setup(mut cmds: Commands, mut meshes: ResMut<Assets<Mesh>>) { - // Spawn a bunch of meshes to use for lines. - for i in 0..MESH_COUNT { - // Create a new mesh with the number of vertices we need. - let mut mesh = Mesh::new(PrimitiveTopology::LineList); - mesh.insert_attribute( - Mesh::ATTRIBUTE_POSITION, - VertexAttributeValues::Float32x3(Vec::with_capacity(MAX_POINTS_PER_MESH)), - ); - mesh.insert_attribute( - ATTRIBUTE_COLOR, - VertexAttributeValues::Uint32(Vec::with_capacity(MAX_POINTS_PER_MESH)), - ); - // https://github.com/Toqozz/bevy_debug_lines/issues/16 - //mesh.set_indices(Some(Indices::U16(Vec::with_capacity(MAX_POINTS_PER_MESH)))); - - cmds.spawn(( - dim::into_handle(meshes.add(mesh)), - NotShadowCaster, - NotShadowReceiver, - NoFrustumCulling, - Transform::default(), - GlobalTransform::default(), - Visibility::default(), - ComputedVisibility::default(), - DebugLinesMesh(i), - )); - } -} - -fn update( - debug_line_meshes: Query<(&dim::MeshHandle, &DebugLinesMesh)>, - time: Res<Time>, - mut meshes: ResMut<Assets<Mesh>>, - mut lines: ResMut<DebugLines>, -) { - // For each debug line mesh, fill its buffers with the relevant positions/colors chunks. - for (mesh_handle, debug_lines_idx) in debug_line_meshes.iter() { - let mesh = meshes.get_mut(dim::from_handle(mesh_handle)).unwrap(); - use VertexAttributeValues::{Float32x3, Uint32}; - if let Some(Float32x3(vbuffer)) = mesh.attribute_mut(Mesh::ATTRIBUTE_POSITION) { - vbuffer.clear(); - if let Some(new_content) = lines - .positions - .chunks(MAX_POINTS_PER_MESH) - .nth(debug_lines_idx.0) - { - vbuffer.extend(new_content); - } - } - - if let Some(Uint32(cbuffer)) = mesh.attribute_mut(ATTRIBUTE_COLOR) { - cbuffer.clear(); - if let Some(new_content) = lines - .colors - .chunks(MAX_POINTS_PER_MESH) - .nth(debug_lines_idx.0) - { - cbuffer.extend(new_content); - } - } - - /* - // https://github.com/Toqozz/bevy_debug_lines/issues/16 - if let Some(Indices::U16(indices)) = mesh.indices_mut() { - indices.clear(); - if let Some(new_content) = lines.durations.chunks(_MAX_LINES_PER_MESH).nth(debug_lines_idx.0) { - indices.extend( - new_content.iter().enumerate().map(|(i, _)| i as u16).flat_map(|i| [i * 2, i*2 + 1]) - ); - } - } - */ - } - - // Processes stuff like getting rid of expired lines and stuff. - lines.update(time.delta_seconds()); -} - -/// Move the DebugLinesMesh marker Component to the render context. -fn extract(mut commands: Commands, query: Query<Entity, With<DebugLinesMesh>>, _: Res<MainWorld>) { - for entity in query.iter() { - commands.get_or_spawn(entity).insert(RenderDebugLinesMesh); - } -} - -#[derive(Component)] -pub(crate) struct DebugLinesMesh(usize); - -#[derive(Component)] -pub(crate) struct RenderDebugLinesMesh; - -/// Bevy resource providing facilities to draw lines. -/// -/// # Usage -/// ```.ignore -/// use bevy::prelude::*; -/// use bevy_prototype_debug_lines::*; -/// -/// // Draws 3 horizontal lines, which disappear after 1 frame. -/// fn some_system(mut lines: ResMut<DebugLines>) { -/// lines.line(Vec3::new(-1.0, 1.0, 0.0), Vec3::new(1.0, 1.0, 0.0), 0.0); -/// lines.line_colored( -/// Vec3::new(-1.0, 0.0, 0.0), -/// Vec3::new(1.0, 0.0, 0.0), -/// 0.0, -/// Color::WHITE -/// ); -/// lines.line_gradient( -/// Vec3::new(-1.0, -1.0, 0.0), -/// Vec3::new(1.0, -1.0, 0.0), -/// 0.0, -/// Color::WHITE, Color::PINK -/// ); -/// } -/// ``` -#[derive(Default, Resource)] -pub struct DebugLines { - pub positions: Vec<[f32; 3]>, - //pub colors: Vec<[f32; 4]>, - pub colors: Vec<u32>, - pub durations: Vec<f32>, -} - -impl DebugLines { - /// Draw a line in world space, or update an existing line - /// - /// # Arguments - /// - /// * `start` - The start of the line in world space - /// * `end` - The end of the line in world space - /// * `duration` - Duration (in seconds) that the line should show for -- a value of - /// zero will show the line for 1 frame. - pub fn line(&mut self, start: Vec3, end: Vec3, duration: f32) { - self.line_colored(start, end, duration, Color::WHITE); - } - - /// Draw a line in world space with a specified color, or update an existing line - /// - /// # Arguments - /// - /// * `start` - The start of the line in world space - /// * `end` - The end of the line in world space - /// * `duration` - Duration (in seconds) that the line should show for -- a value of - /// zero will show the line for 1 frame. - /// * `color` - Line color - pub fn line_colored(&mut self, start: Vec3, end: Vec3, duration: f32, color: Color) { - self.line_gradient(start, end, duration, color, color); - } - - /// Draw a line in world space with a specified gradient color, or update an existing line - /// - /// # Arguments - /// - /// * `start` - The start of the line in world space - /// * `end` - The end of the line in world space - /// * `duration` - Duration (in seconds) that the line should show for -- a value of - /// zero will show the line for 1 frame. - /// * `start_color` - Line color - /// * `end_color` - Line color - pub fn line_gradient( - &mut self, - start: Vec3, - end: Vec3, - duration: f32, - start_color: Color, - end_color: Color, - ) { - if self.positions.len() >= MAX_POINTS { - return; - } - - self.positions.push(start.into()); - self.positions.push(end.into()); - //self.colors.push(start_color.into()); - //self.colors.push(end_color.into()); - self.colors.push(start_color.as_rgba_u32()); - self.colors.push(end_color.as_rgba_u32()); - self.durations.push(duration); - } - - // Returns the indices of the start and end positions of the nth line. - // The indices can also be used to access color data. - fn nth(&self, idx: usize) -> (usize, usize) { - let i = idx * 2; - (i, i + 1) - } - - // Prepare [`ImmediateLinesStorage`] and [`RetainedLinesStorage`] for next - // frame. - // This clears the immediate mod buffers and tells the retained mode - // buffers to recompute expired lines list. - fn update(&mut self, dt: f32) { - // TODO: an actual line counter wouldn't hurt. - let mut i = 0; - let mut len = self.durations.len(); - while i != len { - self.durations[i] -= dt; - // <= instead of < is fine here because this is always called AFTER sending the - // data to the mesh, so we're guaranteed at least a frame here. - if self.durations[i] <= 0.0 { - let (cur_s, cur_e) = self.nth(i); - let (last_s, last_e) = self.nth(len - 1); - self.positions.swap(cur_s, last_s); - self.positions.swap(cur_e, last_e); - self.colors.swap(cur_s, last_s); - self.colors.swap(cur_e, last_e); - self.durations.swap(i, len - 1); - len -= 1; - } else { - i += 1; - } - } - - self.positions.truncate(len * 2); - self.colors.truncate(len * 2); - self.durations.truncate(len); - } -} diff --git a/src_testbed/lines/render_dim.rs b/src_testbed/lines/render_dim.rs deleted file mode 100644 index f339cdb..0000000 --- a/src_testbed/lines/render_dim.rs +++ /dev/null @@ -1,340 +0,0 @@ -pub mod r3d { - use bevy_core_pipeline::core_3d::Opaque3d; - use bevy_pbr::{ - DrawMesh, MeshPipeline, MeshPipelineKey, MeshUniform, SetMeshBindGroup, - SetMeshViewBindGroup, - }; - - use bevy::{ - prelude::*, - render::{ - mesh::MeshVertexBufferLayout, - render_asset::RenderAssets, - render_phase::{DrawFunctions, RenderPhase, SetItemPipeline}, - render_resource::{ - BlendState, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState, - DepthStencilState, FragmentState, FrontFace, MultisampleState, PipelineCache, - PolygonMode, PrimitiveState, PrimitiveTopology, RenderPipelineDescriptor, - SpecializedMeshPipeline, SpecializedMeshPipelineError, SpecializedMeshPipelines, - StencilFaceState, StencilState, TextureFormat, VertexAttribute, VertexBufferLayout, - VertexFormat, VertexState, VertexStepMode, - }, - texture::BevyDefault, - view::{ExtractedView, Msaa}, - }, - utils::Hashed, - }; - - use crate::lines::{DebugLinesConfig, RenderDebugLinesMesh, DEBUG_LINES_SHADER_HANDLE}; - - #[derive(Resource)] - pub(crate) struct DebugLinePipeline { - mesh_pipeline: MeshPipeline, - shader: Handle<Shader>, - //always_in_front: bool, - } - impl FromWorld for DebugLinePipeline { - fn from_world(render_world: &mut World) -> Self { - //let config = render_world.get_resource::<DebugLinesConfig>().unwrap(); - DebugLinePipeline { - mesh_pipeline: render_world.get_resource::<MeshPipeline>().unwrap().clone(), - shader: DEBUG_LINES_SHADER_HANDLE.typed(), - //always_in_front: config.always_in_front, - } - } - } - - impl SpecializedMeshPipeline for DebugLinePipeline { - type Key = (bool, MeshPipelineKey); - - fn specialize( - &self, - (depth_test, key): Self::Key, - layout: &MeshVertexBufferLayout, - ) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> { - //use VertexFormat::{Float32x3, Float32x4}; - - let mut shader_defs = Vec::new(); - shader_defs.push("LINES_3D".to_string().into()); - if depth_test { - shader_defs.push("DEPTH_TEST_ENABLED".to_string().into()); - } - - let vertex_buffer_layout = layout.get_layout(&[ - Mesh::ATTRIBUTE_POSITION.at_shader_location(0), - Mesh::ATTRIBUTE_COLOR.at_shader_location(1), - ])?; - let (label, blend, depth_write_enabled); - if key.contains(MeshPipelineKey::BLEND_ALPHA) { - label = "transparent_mesh_pipeline".into(); - blend = Some(BlendState::ALPHA_BLENDING); - // For the transparent pass, fragments that are closer will be alpha - // blended but their depth is not written to the depth buffer. - depth_write_enabled = false; - } else { - label = "opaque_mesh_pipeline".into(); - blend = Some(BlendState::REPLACE); - // For the opaque and alpha mask passes, fragments that are closer - // will replace the current fragment value in the output and the depth is - // written to the depth buffer. - depth_write_enabled = true; - } - - Ok(RenderPipelineDescriptor { - vertex: VertexState { - shader: self.shader.clone_weak(), - entry_point: "vertex".into(), - shader_defs: shader_defs.clone(), - buffers: vec![vertex_buffer_layout], - }, - fragment: Some(FragmentState { - shader: self.shader.clone_weak(), - shader_defs, - entry_point: "fragment".into(), - targets: vec![Some(ColorTargetState { - format: TextureFormat::bevy_default(), - blend, - write_mask: ColorWrites::ALL, - })], - }), - layout: vec![self.mesh_pipeline.view_layout.clone()], - primitive: PrimitiveState { - front_face: FrontFace::Ccw, - cull_mode: None, - unclipped_depth: false, - polygon_mode: PolygonMode::Fill, - conservative: false, - topology: PrimitiveTopology::LineList, - strip_index_format: None, - }, - depth_stencil: Some(DepthStencilState { - format: TextureFormat::Depth32Float, - depth_write_enabled, - depth_compare: CompareFunction::Greater, - stencil: StencilState { - front: StencilFaceState::IGNORE, - back: StencilFaceState::IGNORE, - read_mask: 0, - write_mask: 0, - }, - bias: DepthBiasState { - constant: 0, - slope_scale: 0.0, - clamp: 0.0, - }, - }), - multisample: MultisampleState { - count: key.msaa_samples(), - mask: !0, - alpha_to_coverage_enabled: false, - }, - label: Some(label), - push_constant_ranges: vec![], - }) - } - } - - pub(crate) fn queue( - opaque_3d_draw_functions: Res<DrawFunctions<Opaque3d>>, - debug_line_pipeline: Res<DebugLinePipeline>, - mut pipelines: ResMut<SpecializedMeshPipelines<DebugLinePipeline>>, - mut pipeline_cache: ResMut<PipelineCache>, - render_meshes: Res<RenderAssets<Mesh>>, - msaa: Res<Msaa>, - material_meshes: Query<(Entity, &MeshUniform, &Handle<Mesh>), With<RenderDebugLinesMesh>>, - config: Res<DebugLinesConfig>, - mut views: Query<(&ExtractedView, &mut RenderPhase<Opaque3d>)>, - ) { - let draw_custom = opaque_3d_draw_functions - .read() - .get_id::<DrawDebugLines>() - .unwrap(); - let key = MeshPipelineKey::from_msaa_samples(msaa.samples()); - for (view, mut transparent_phase) in views.iter_mut() { - let view_matrix = view.transform.compute_matrix(); - let view_row_2 = view_matrix.row(2); - for (entity, mesh_uniform, mesh_handle) in material_meshes.iter() { - if let Some(mesh) = render_meshes.get(mesh_handle) { - let pipeline = pipelines - .specialize( - &mut pipeline_cache, - &debug_line_pipeline, - (config.depth_test, key), - &mesh.layout, - ) - .unwrap(); - transparent_phase.add(Opaque3d { - entity, - pipeline, - draw_function: draw_custom, - distance: view_row_2.dot(mesh_uniform.transform.col(3)), - }); - } - } - } - } - - pub(crate) type DrawDebugLines = ( - SetItemPipeline, - SetMeshViewBindGroup<0>, - SetMeshBindGroup<1>, - DrawMesh, - ); -} - -pub mod r2d { - use bevy::{ - asset::Handle, - prelude::*, - render::{ - mesh::MeshVertexBufferLayout, - render_asset::RenderAssets, - render_phase::{DrawFunctions, RenderPhase, SetItemPipeline}, - render_resource::{ - BlendState, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState, - DepthStencilState, FragmentState, FrontFace, MultisampleState, PipelineCache, - PolygonMode, PrimitiveState, PrimitiveTopology, RenderPipelineDescriptor, Shader, - SpecializedMeshPipeline, SpecializedMeshPipelineError, SpecializedMeshPipelines, - StencilFaceState, StencilState, TextureFormat, VertexAttribute, VertexBufferLayout, - VertexFormat, VertexState, VertexStepMode, - }, - texture::BevyDefault, - view::{Msaa, VisibleEntities}, - }, - utils::FloatOrd, - }; - use bevy_core_pipeline::core_2d::Transparent2d; - use bevy_sprite::{ - DrawMesh2d, Mesh2dHandle, Mesh2dPipeline, Mesh2dPipelineKey, Mesh2dUniform, - SetMesh2dBindGroup, SetMesh2dViewBindGroup, - }; - - use crate::lines::{RenderDebugLinesMesh, DEBUG_LINES_SHADER_HANDLE}; - - #[derive(Resource)] - pub(crate) struct DebugLinePipeline { - mesh_pipeline: Mesh2dPipeline, - shader: Handle<Shader>, - } - impl FromWorld for DebugLinePipeline { - fn from_world(render_world: &mut World) -> Self { - DebugLinePipeline { - mesh_pipeline: render_world - .get_resource::<Mesh2dPipeline>() - .unwrap() - .clone(), - shader: DEBUG_LINES_SHADER_HANDLE.typed(), - } - } - } - - impl SpecializedMeshPipeline for DebugLinePipeline { - type Key = Mesh2dPipelineKey; - - fn specialize( - &self, - key: Self::Key, - layout: &MeshVertexBufferLayout, - ) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> { - /* - let mut shader_defs = Vec::new(); - shader_defs.push("LINES_3D".to_string()); - if depth_test { - shader_defs.push("DEPTH_TEST_ENABLED".to_string()); - } - */ - - let vertex_buffer_layout = layout.get_layout(& |
