Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
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 @@ -252,6 +252,7 @@ common_api = [
"bevy_anti_alias",
"bevy_gltf",
"bevy_pbr",
"bevy_render_debug",
"bevy_post_process",
"gltf_animation",
]
Expand Down Expand Up @@ -318,6 +319,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