mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
Add random shader utils, fix cluster_debug_visualization (#11956)
# Objective - Partially addresses https://github.com/bevyengine/bevy/issues/11470 (I'd like to add Spatiotemporal Blue Noise in the future, but that's a bit more controversial). - Fix cluster_debug_visualization which has not compiled for a while --- ## Changelog - Added random white noise shader functions to `bevy_pbr::utils` ## Migration Guide - The `bevy_pbr::utils::random1D` shader function has been replaced by the similar `bevy_pbr::utils::rand_f`.
This commit is contained in:
parent
ebdda09fc3
commit
40bfce556a
2 changed files with 42 additions and 12 deletions
|
@ -2,13 +2,13 @@
|
|||
|
||||
#import bevy_pbr::{
|
||||
mesh_view_bindings as bindings,
|
||||
utils::hsv2rgb,
|
||||
utils::{hsv2rgb, rand_f},
|
||||
}
|
||||
|
||||
// NOTE: Keep in sync with bevy_pbr/src/light.rs
|
||||
fn view_z_to_z_slice(view_z: f32, is_orthographic: bool) -> u32 {
|
||||
var z_slice: u32 = 0u;
|
||||
if (is_orthographic) {
|
||||
if is_orthographic {
|
||||
// NOTE: view_z is correct in the orthographic case
|
||||
z_slice = u32(floor((view_z - bindings::lights.cluster_factors.z) * bindings::lights.cluster_factors.w));
|
||||
} else {
|
||||
|
@ -35,7 +35,7 @@ fn fragment_cluster_index(frag_coord: vec2<f32>, view_z: f32, is_orthographic: b
|
|||
const CLUSTER_COUNT_SIZE = 9u;
|
||||
fn unpack_offset_and_counts(cluster_index: u32) -> vec3<u32> {
|
||||
#if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 3
|
||||
return bindings::cluster_offsets_and_counts.data[cluster_index].xyz;
|
||||
return bindings::cluster_offsets_and_counts.data[cluster_index].xyz;
|
||||
#else
|
||||
let offset_and_counts = bindings::cluster_offsets_and_counts.data[cluster_index >> 2u][cluster_index & ((1u << 2u) - 1u)];
|
||||
// [ 31 .. 18 | 17 .. 9 | 8 .. 0 ]
|
||||
|
@ -61,19 +61,21 @@ fn get_light_id(index: u32) -> u32 {
|
|||
}
|
||||
|
||||
fn cluster_debug_visualization(
|
||||
output_color: vec4<f32>,
|
||||
input_color: vec4<f32>,
|
||||
view_z: f32,
|
||||
is_orthographic: bool,
|
||||
offset_and_counts: vec3<u32>,
|
||||
cluster_index: u32,
|
||||
) -> vec4<f32> {
|
||||
var output_color = input_color;
|
||||
|
||||
// Cluster allocation debug (using 'over' alpha blending)
|
||||
#ifdef CLUSTERED_FORWARD_DEBUG_Z_SLICES
|
||||
// NOTE: This debug mode visualises the z-slices
|
||||
let cluster_overlay_alpha = 0.1;
|
||||
var z_slice: u32 = view_z_to_z_slice(view_z, is_orthographic);
|
||||
// A hack to make the colors alternate a bit more
|
||||
if ((z_slice & 1u) == 1u) {
|
||||
if (z_slice & 1u) == 1u {
|
||||
z_slice = z_slice + bindings::lights.cluster_dimensions.z / 2u;
|
||||
}
|
||||
let slice_color = hsv2rgb(f32(z_slice) / f32(bindings::lights.cluster_dimensions.z + 1u), 1.0, 0.5);
|
||||
|
@ -87,15 +89,14 @@ fn cluster_debug_visualization(
|
|||
// the fragment. It shows a sort of lighting complexity measure.
|
||||
let cluster_overlay_alpha = 0.1;
|
||||
let max_light_complexity_per_cluster = 64.0;
|
||||
output_color.r = (1.0 - cluster_overlay_alpha) * output_color.r
|
||||
+ cluster_overlay_alpha * smoothStep(0.0, max_light_complexity_per_cluster, f32(offset_and_counts[1] + offset_and_counts[2]));
|
||||
output_color.g = (1.0 - cluster_overlay_alpha) * output_color.g
|
||||
+ cluster_overlay_alpha * (1.0 - smoothStep(0.0, max_light_complexity_per_cluster, f32(offset_and_counts[1] + offset_and_counts[2])));
|
||||
output_color.r = (1.0 - cluster_overlay_alpha) * output_color.r + cluster_overlay_alpha * smoothStep(0.0, max_light_complexity_per_cluster, f32(offset_and_counts[1] + offset_and_counts[2]));
|
||||
output_color.g = (1.0 - cluster_overlay_alpha) * output_color.g + cluster_overlay_alpha * (1.0 - smoothStep(0.0, max_light_complexity_per_cluster, f32(offset_and_counts[1] + offset_and_counts[2])));
|
||||
#endif // CLUSTERED_FORWARD_DEBUG_CLUSTER_LIGHT_COMPLEXITY
|
||||
#ifdef CLUSTERED_FORWARD_DEBUG_CLUSTER_COHERENCY
|
||||
// NOTE: Visualizes the cluster to which the fragment belongs
|
||||
let cluster_overlay_alpha = 0.1;
|
||||
let cluster_color = hsv2rgb(random1D(f32(cluster_index)), 1.0, 0.5);
|
||||
var rng = cluster_index;
|
||||
let cluster_color = hsv2rgb(rand_f(&rng), 1.0, 0.5);
|
||||
output_color = vec4<f32>(
|
||||
(1.0 - cluster_overlay_alpha) * output_color.rgb + cluster_overlay_alpha * cluster_color,
|
||||
output_color.a
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#define_import_path bevy_pbr::utils
|
||||
|
||||
#import bevy_pbr::rgb9e5
|
||||
|
||||
const PI: f32 = 3.141592653589793;
|
||||
|
@ -17,8 +18,36 @@ fn hsv2rgb(hue: f32, saturation: f32, value: f32) -> vec3<f32> {
|
|||
return value * mix(vec3<f32>(1.0), rgb, vec3<f32>(saturation));
|
||||
}
|
||||
|
||||
fn random1D(s: f32) -> f32 {
|
||||
return fract(sin(s * 12.9898) * 43758.5453123);
|
||||
// Generates a random u32 in range [0, u32::MAX].
|
||||
//
|
||||
// `state` is a mutable reference to a u32 used as the seed.
|
||||
//
|
||||
// Values are generated via "white noise", with no correlation between values.
|
||||
// In shaders, you often want spatial and/or temporal correlation. Use a different RNG method for these use cases.
|
||||
//
|
||||
// https://www.pcg-random.org
|
||||
// https://www.reedbeta.com/blog/hash-functions-for-gpu-rendering
|
||||
fn rand_u(state: ptr<function, u32>) -> u32 {
|
||||
*state = *state * 747796405u + 2891336453u;
|
||||
let word = ((*state >> ((*state >> 28u) + 4u)) ^ *state) * 277803737u;
|
||||
return (word >> 22u) ^ word;
|
||||
}
|
||||
|
||||
// Generates a random f32 in range [0, 1.0].
|
||||
fn rand_f(state: ptr<function, u32>) -> f32 {
|
||||
*state = *state * 747796405u + 2891336453u;
|
||||
let word = ((*state >> ((*state >> 28u) + 4u)) ^ *state) * 277803737u;
|
||||
return f32((word >> 22u) ^ word) * bitcast<f32>(0x2f800004u);
|
||||
}
|
||||
|
||||
// Generates a random vec2<f32> where each value is in range [0, 1.0].
|
||||
fn rand_vec2f(state: ptr<function, u32>) -> vec2<f32> {
|
||||
return vec2(rand_f(state), rand_f(state));
|
||||
}
|
||||
|
||||
// Generates a random u32 in range [0, n).
|
||||
fn rand_range_u(n: u32, state: ptr<function, u32>) -> u32 {
|
||||
return rand_u(state) % n;
|
||||
}
|
||||
|
||||
// returns the (0-1, 0-1) position within the given viewport for the current buffer coords .
|
||||
|
|
Loading…
Reference in a new issue