import bevy_pbr::render::mesh_view_bindings::view;
import bevy_pbr::render::mesh_view_bindings::depth_prepass_texture;
import bevy_pbr::render::mesh_view_bindings::normal_prepass_texture;
import bevy_pbr::render::mesh_view_bindings::motion_vector_prepass_texture;
import bevy_pbr::render::mesh_view_bindings::deferred_prepass_texture;
import bevy_pbr::render::view_transformations::depth_ndc_to_view_z;
import bevy_pbr::deferred::types::unpack_24bit_normal;
import bevy_pbr::deferred::types::unpack_unorm4x8_;
import bevy_pbr::deferred::types::unpack_unorm3x4_plus_unorm_20_;
import bevy_pbr::render::rgb9e5::rgb9e5_to_vec3_;
import bevy_render::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;
@if(DEBUG_DEPTH_PYRAMID) {
@group(1) @binding(3) var depth_pyramid_texture: texture_2d<f32>;
@group(1) @binding(4) var depth_pyramid_sampler: sampler;
}
@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);
@if(DEBUG_DEPTH) {
@if(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);
}
}
@if(DEBUG_NORMAL) {
@if(NORMAL_PREPASS) {
let normal_sample = textureLoad(normal_prepass_texture, vec2<i32>(frag_coord.xy), 0);
output_color = vec4(normal_sample.xyz, 1.0);
}
@else {
@if(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);
}
}
}
@if(DEBUG_MOTION_VECTORS) {
@if(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);
}
}
@if(DEBUG_DEFERRED) {
@if(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);
}
}
@if(DEBUG_DEFERRED_BASE_COLOR) {
@if(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);
}
}
@if(DEBUG_DEFERRED_EMISSIVE) {
@if(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);
}
}
@if(DEBUG_DEFERRED_METALLIC_ROUGHNESS) {
@if(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);
}
}
@if(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);
}
let alpha = output_color.a * config.opacity;
return vec4(mix(background.rgb, output_color.rgb, alpha), 1.0);
}