From 5063fa420392455f7926f1ba3e65612f79a0b066 Mon Sep 17 00:00:00 2001 From: Sébastien Crozet Date: Thu, 28 Apr 2022 13:19:58 +0200 Subject: Testbed: switch to bevy 0.7 --- src_testbed/lines/debuglines.wgsl | 49 +++++ src_testbed/lines/debuglines2d.wgsl | 31 ++++ src_testbed/lines/mod.rs | 358 ++++++++++++++++++++++++++++++++++++ src_testbed/lines/render_dim.rs | 335 +++++++++++++++++++++++++++++++++ 4 files changed, 773 insertions(+) create mode 100644 src_testbed/lines/debuglines.wgsl create mode 100644 src_testbed/lines/debuglines2d.wgsl create mode 100644 src_testbed/lines/mod.rs create mode 100644 src_testbed/lines/render_dim.rs (limited to 'src_testbed/lines') diff --git a/src_testbed/lines/debuglines.wgsl b/src_testbed/lines/debuglines.wgsl new file mode 100644 index 0000000..0987839 --- /dev/null +++ b/src_testbed/lines/debuglines.wgsl @@ -0,0 +1,49 @@ +// 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; + [[location(1)]] color: u32; +}; + +struct VertexOutput { + [[builtin(position)]] clip_position: vec4; + [[location(0)]] color: vec4; +}; + +struct FragmentOutput { + [[builtin(frag_depth)]] depth: f32; + [[location(0)]] color: vec4; +}; + +[[stage(vertex)]] +fn vertex(vertex: Vertex) -> VertexOutput { + var out: VertexOutput; + out.clip_position = view.view_proj * vec4(vertex.pos, 1.0); + //out.color = vertex.color; + // https://github.com/bevyengine/bevy/blob/328c26d02c50de0bc77f0d24a376f43ba89517b1/examples/2d/mesh2d_manual.rs#L234 + out.color = vec4((vec4(vertex.color) >> vec4(8u, 8u, 16u, 24u)) & vec4(255u)) / 255.0; + + 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 new file mode 100644 index 0000000..9316531 --- /dev/null +++ b/src_testbed/lines/debuglines2d.wgsl @@ -0,0 +1,31 @@ +#import bevy_sprite::mesh2d_view_bind_group +[[group(0), binding(0)]] +var view: View; + +struct Vertex { + //[[location(0)]] color: vec4; + [[location(0)]] place: vec3; + [[location(1)]] color: u32; +}; + +struct VertexOutput { + [[builtin(position)]] clip_position: vec4; + [[location(0)]] color: vec4; +}; + +[[stage(vertex)]] +fn vertex(vertex: Vertex) -> VertexOutput { + var out: VertexOutput; + out.clip_position = view.view_proj * vec4(vertex.place, 1.0); + // What is this craziness? + out.color = vec4((vec4(vertex.color) >> vec4(0u, 8u, 16u, 24u)) & vec4(255u)) / 255.0; + //out.color = vertex.color; + //out.color = vec4(1.0, 0.0, 0.0, 1.0); + + return out; +} + +[[stage(fragment)]] +fn fragment(in: VertexOutput) -> [[location(0)]] vec4 { + return in.color; +} diff --git a/src_testbed/lines/mod.rs b/src_testbed/lines/mod.rs new file mode 100644 index 0000000..c80c5df --- /dev/null +++ b/src_testbed/lines/mod.rs @@ -0,0 +1,358 @@ +use bevy::{ + asset::{Assets, HandleUntyped}, + pbr::{NotShadowCaster, NotShadowReceiver}, + prelude::*, + reflect::TypeUuid, + render::{ + mesh::{/*Indices,*/ Mesh, VertexAttributeValues}, + render_phase::AddRenderCommand, + render_resource::PrimitiveTopology, + render_resource::Shader, + }, +}; + +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 crate::lines::render_dim::r3d::{queue, DebugLinePipeline, DrawDebugLines}; + pub(crate) use bevy::core_pipeline::Opaque3d as Phase; + use bevy::{asset::Handle, render::mesh::Mesh}; + + pub(crate) type MeshHandle = Handle; + pub(crate) fn from_handle(from: &MeshHandle) -> &Handle { + from + } + pub(crate) fn into_handle(from: Handle) -> 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 crate::lines::render_dim::r2d::{queue, DebugLinePipeline, DrawDebugLines}; + pub(crate) use bevy::core_pipeline::Transparent2d as Phase; + use bevy::{asset::Handle, render::mesh::Mesh, sprite::Mesh2dHandle}; + + pub(crate) type MeshHandle = Mesh2dHandle; + pub(crate) fn from_handle(from: &MeshHandle) -> &Handle { + &from.0 + } + pub(crate) fn into_handle(from: Handle) -> 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); + +pub(crate) struct DebugLinesConfig { + depth_test: bool, +} + +/// Bevy plugin, for initializing stuff. +/// +/// # Usage +/// +/// ``` +/// 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)`]. +/// ``` +/// 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 } + } +} + +impl Plugin for DebugLinesPlugin { + fn build(&self, app: &mut App) { + use bevy::render::{render_resource::SpecializedMeshPipelines, RenderApp, RenderStage}; + let mut shaders = app.world.get_resource_mut::>().unwrap(); + shaders.set_untracked( + DEBUG_LINES_SHADER_HANDLE, + Shader::from_wgsl(dim::SHADER_FILE), + ); + app.init_resource::(); + app.add_startup_system(setup) + .add_system_to_stage(CoreStage::PostUpdate, update.label("draw_lines")); + app.sub_app_mut(RenderApp) + .add_render_command::() + .insert_resource(DebugLinesConfig { + depth_test: self.depth_test, + }) + .init_resource::() + .init_resource::>() + .add_system_to_stage(RenderStage::Extract, extract) + .add_system_to_stage(RenderStage::Queue, dim::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; + +fn setup(mut cmds: Commands, mut meshes: ResMut>) { + // 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( + Mesh::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_bundle(( + dim::into_handle(meshes.add(mesh)), + NotShadowCaster, + NotShadowReceiver, + Transform::default(), + GlobalTransform::default(), + Visibility::default(), + ComputedVisibility::default(), + DebugLinesMesh(i), + )); + } +} + +fn update( + debug_line_meshes: Query<(&dim::MeshHandle, &DebugLinesMesh)>, + time: Res