Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ common_api = [
"bevy_anti_alias",
"bevy_gltf",
"bevy_pbr",
"bevy_render_debug",
"bevy_post_process",
"gltf_animation",
]
Expand Down Expand Up @@ -323,6 +324,9 @@ bevy_gltf = ["bevy_internal/bevy_gltf"]
# Adds PBR rendering
bevy_pbr = ["bevy_internal/bevy_pbr"]

# Provides debug visualization for the PBR render pipeline
bevy_render_debug = ["bevy_internal/bevy_render_debug"]

# Provides picking functionality
bevy_picking = ["bevy_internal/bevy_picking"]

Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_internal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ bevy_pbr = [
"bevy_core_pipeline",
"bevy_gizmos_render?/bevy_pbr",
]
bevy_render_debug = ["dep:bevy_render_debug", "bevy_pbr"]
bevy_sprite_render = [
"dep:bevy_sprite_render",
"bevy_sprite",
Expand Down Expand Up @@ -507,6 +508,7 @@ bevy_input_focus = { path = "../bevy_input_focus", optional = true, version = "0
"bevy_reflect",
] }
bevy_pbr = { path = "../bevy_pbr", optional = true, version = "0.18.0-dev" }
bevy_render_debug = { path = "../bevy_render_debug", optional = true, version = "0.18.0-dev" }
bevy_picking = { path = "../bevy_picking", optional = true, version = "0.18.0-dev" }
bevy_remote = { path = "../bevy_remote", optional = true, version = "0.18.0-dev" }
bevy_render = { path = "../bevy_render", optional = true, version = "0.18.0-dev" }
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_internal/src/default_plugins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ plugin_group! {
bevy_ui_render:::UiRenderPlugin,
#[cfg(feature = "bevy_pbr")]
bevy_pbr:::PbrPlugin,
#[cfg(feature = "bevy_render_debug")]
bevy_render_debug:::RenderDebugOverlayPlugin,
// NOTE: Load this after renderer initialization so that it knows about the supported
// compressed texture formats.
#[cfg(feature = "bevy_gltf")]
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_internal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ pub use bevy_reflect as reflect;
pub use bevy_remote as remote;
#[cfg(feature = "bevy_render")]
pub use bevy_render as render;
#[cfg(feature = "bevy_render_debug")]
pub use bevy_render_debug as render_debug;
#[cfg(feature = "bevy_scene")]
pub use bevy_scene as scene;
#[cfg(feature = "bevy_shader")]
Expand Down
26 changes: 26 additions & 0 deletions crates/bevy_render_debug/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "bevy_render_debug"
version = "0.18.0-dev"
edition = "2024"
description = "Adds debug visualization to Bevy Engine"
homepage = "https://bevy.org"
repository = "https://github.com/bevyengine/bevy"
license = "MIT OR Apache-2.0"
keywords = ["bevy"]

[dependencies]
bevy_app = { path = "../bevy_app", version = "0.18.0-dev" }
bevy_asset = { path = "../bevy_asset", version = "0.18.0-dev" }
bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.18.0-dev" }
bevy_ecs = { path = "../bevy_ecs", version = "0.18.0-dev" }
bevy_image = { path = "../bevy_image", version = "0.18.0-dev" }
bevy_input = { path = "../bevy_input", version = "0.18.0-dev" }
bevy_log = { path = "../bevy_log", version = "0.18.0-dev" }
bevy_pbr = { path = "../bevy_pbr", version = "0.18.0-dev" }
bevy_reflect = { path = "../bevy_reflect", version = "0.18.0-dev" }
bevy_render = { path = "../bevy_render", version = "0.18.0-dev" }
bevy_shader = { path = "../bevy_shader", version = "0.18.0-dev" }
bevy_camera = { path = "../bevy_camera", version = "0.18.0-dev" }

[lints]
workspace = true
117 changes: 117 additions & 0 deletions crates/bevy_render_debug/src/debug_overlay.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#import bevy_pbr::mesh_view_bindings::view
#import bevy_pbr::mesh_view_bindings::depth_prepass_texture
#import bevy_pbr::mesh_view_bindings::normal_prepass_texture
#import bevy_pbr::mesh_view_bindings::motion_vector_prepass_texture
#import bevy_pbr::mesh_view_bindings::deferred_prepass_texture
#import bevy_pbr::view_transformations::depth_ndc_to_view_z
#import bevy_pbr::pbr_deferred_types::unpack_24bit_normal
#import bevy_pbr::pbr_deferred_types::unpack_unorm4x8_
#import bevy_pbr::pbr_deferred_types::unpack_unorm3x4_plus_unorm_20_
#import bevy_pbr::rgb9e5::rgb9e5_to_vec3_
#import bevy_pbr::utils::octahedral_decode

struct DebugBufferConfig {
opacity: f32,
mip_level: u32,
}

@group(1) @binding(0) var<uniform> config: DebugBufferConfig;
@group(1) @binding(1) var background_texture: texture_2d<f32>;
@group(1) @binding(2) var background_sampler: sampler;

#ifdef DEBUG_DEPTH_PYRAMID
@group(1) @binding(3) var depth_pyramid_texture: texture_2d<f32>;
@group(1) @binding(4) var depth_pyramid_sampler: sampler;
#endif

@fragment
fn fragment(@builtin(position) frag_coord: vec4<f32>) -> @location(0) vec4<f32> {
let uv = frag_coord.xy / view.viewport.zw;
let background = textureSampleLevel(background_texture, background_sampler, uv, 0.0);
var output_color: vec4<f32> = vec4(0.0);

#ifdef DEBUG_DEPTH
#ifdef DEPTH_PREPASS
let depth = textureLoad(depth_prepass_texture, vec2<i32>(frag_coord.xy), 0);
output_color = vec4(vec3(depth), 1.0);
#else
output_color = vec4(1.0, 0.0, 1.0, 1.0);
#endif
#endif

#ifdef DEBUG_NORMAL
#ifdef NORMAL_PREPASS
let normal_sample = textureLoad(normal_prepass_texture, vec2<i32>(frag_coord.xy), 0);
output_color = vec4(normal_sample.xyz, 1.0);
#else
#ifdef DEFERRED_PREPASS
let deferred = textureLoad(deferred_prepass_texture, vec2<i32>(frag_coord.xy), 0);
let normal = octahedral_decode(unpack_24bit_normal(deferred.a));
output_color = vec4(normal * 0.5 + 0.5, 1.0);
#else
output_color = vec4(1.0, 0.0, 1.0, 1.0);
#endif
#endif
#endif

#ifdef DEBUG_MOTION_VECTORS
#ifdef MOTION_VECTOR_PREPASS
let motion_vector = textureLoad(motion_vector_prepass_texture, vec2<i32>(frag_coord.xy), 0).rg;
// These motion vectors are stored in a format where 1.0 represents full-screen movement.
// We use a power curve to amplify small movements while keeping them centered.
let mapped_motion = sign(motion_vector) * pow(abs(motion_vector), vec2(0.2)) * 0.5 + 0.5;
output_color = vec4(mapped_motion, 0.5, 1.0);
#else
output_color = vec4(1.0, 0.0, 1.0, 1.0);
#endif
#endif

#ifdef DEBUG_DEFERRED
#ifdef DEFERRED_PREPASS
let deferred = textureLoad(deferred_prepass_texture, vec2<i32>(frag_coord.xy), 0);
output_color = vec4(vec3(f32(deferred.x) / 255.0, f32(deferred.y) / 255.0, f32(deferred.z) / 255.0), 1.0);
#else
output_color = vec4(1.0, 0.0, 1.0, 1.0);
#endif
#endif

#ifdef DEBUG_DEFERRED_BASE_COLOR
#ifdef DEFERRED_PREPASS
let deferred = textureLoad(deferred_prepass_texture, vec2<i32>(frag_coord.xy), 0);
let base_rough = unpack_unorm4x8_(deferred.x);
output_color = vec4(pow(base_rough.rgb, vec3(2.2)), 1.0);
#else
output_color = vec4(1.0, 0.0, 1.0, 1.0);
#endif
#endif

#ifdef DEBUG_DEFERRED_EMISSIVE
#ifdef DEFERRED_PREPASS
let deferred = textureLoad(deferred_prepass_texture, vec2<i32>(frag_coord.xy), 0);
let emissive = rgb9e5_to_vec3_(deferred.y);
output_color = vec4(emissive, 1.0);
#else
output_color = vec4(1.0, 0.0, 1.0, 1.0);
#endif
#endif

#ifdef DEBUG_DEFERRED_METALLIC_ROUGHNESS
#ifdef DEFERRED_PREPASS
let deferred = textureLoad(deferred_prepass_texture, vec2<i32>(frag_coord.xy), 0);
let base_rough = unpack_unorm4x8_(deferred.x);
let props = unpack_unorm4x8_(deferred.z);
// R: Reflectance, G: Metallic, B: Occlusion, A: Perceptual Roughness
output_color = vec4(props.r, props.g, props.b, base_rough.a);
#else
output_color = vec4(1.0, 0.0, 1.0, 1.0);
#endif
#endif

#ifdef DEBUG_DEPTH_PYRAMID
let depth_pyramid = textureSampleLevel(depth_pyramid_texture, depth_pyramid_sampler, uv, f32(config.mip_level)).r;
output_color = vec4(vec3(depth_pyramid), 1.0);
#endif

let alpha = output_color.a * config.opacity;
return vec4(mix(background.rgb, output_color.rgb, alpha), 1.0);
}
Loading