Skip to content

Commit

Permalink
move wgsl color operations from bevy_pbr to bevy_render (#13209)
Browse files Browse the repository at this point in the history
# Objective

`bevy_pbr/utils.wgsl` shader file contains mathematical constants and
color conversion functions. Both of those should be accessible without
enabling `bevy_pbr` feature. For example, tonemapping can be done in non
pbr scenario, and it uses color conversion functions.

Fixes #13207

## Solution

* Move mathematical constants (such as PI, E) from
`bevy_pbr/src/render/utils.wgsl` into `bevy_render/src/maths.wgsl`
* Move color conversion functions from `bevy_pbr/src/render/utils.wgsl`
into new file `bevy_render/src/color_operations.wgsl`

## Testing
Ran multiple examples, checked they are working:
* tonemapping
* color_grading
* 3d_scene
* animated_material
* deferred_rendering
* 3d_shapes
* fog
* irradiance_volumes
* meshlet
* parallax_mapping
* pbr
* reflection_probes
* shadow_biases
* 2d_gizmos
* light_gizmos
---

## Changelog
* Moved mathematical constants (such as PI, E) from
`bevy_pbr/src/render/utils.wgsl` into `bevy_render/src/maths.wgsl`
* Moved color conversion functions from `bevy_pbr/src/render/utils.wgsl`
into new file `bevy_render/src/color_operations.wgsl`

## Migration Guide
In user's shader code replace usage of mathematical constants from
`bevy_pbr::utils` to the usage of the same constants from
`bevy_render::maths`.
  • Loading branch information
arcashka authored May 4, 2024
1 parent 4083750 commit 6027890
Show file tree
Hide file tree
Showing 14 changed files with 92 additions and 64 deletions.
3 changes: 2 additions & 1 deletion assets/shaders/tonemapping_test_patterns.wgsl
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#import bevy_pbr::{
mesh_view_bindings,
forward_io::VertexOutput,
utils::PI,
}

#import bevy_render::maths::PI

#ifdef TONEMAP_IN_SHADER
#import bevy_core_pipeline::tonemapping::tone_mapping
#endif
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#define_import_path bevy_core_pipeline::tonemapping

#import bevy_render::view::ColorGrading
#import bevy_pbr::utils::{PI_2, hsv_to_rgb, rgb_to_hsv};
#import bevy_render::{
view::ColorGrading,
color_operations::{hsv_to_rgb, rgb_to_hsv},
maths::PI_2
}

// hack !! not sure what to do with this
#ifdef TONEMAPPING_PASS
Expand Down
7 changes: 6 additions & 1 deletion crates/bevy_pbr/src/render/clustered_forward.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

#import bevy_pbr::{
mesh_view_bindings as bindings,
utils::{PI_2, hsv_to_rgb, rand_f},
utils::rand_f,
}

#import bevy_render::{
color_operations::hsv_to_rgb,
maths::PI_2,
}

// NOTE: Keep in sync with bevy_pbr/src/light.rs
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_pbr/src/render/pbr_functions.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
ambient,
irradiance_volume,
mesh_types::{MESH_FLAGS_SHADOW_RECEIVER_BIT, MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT},
utils::E,
}

#import bevy_render::maths::E

#ifdef ENVIRONMENT_MAP
#import bevy_pbr::environment_map
#endif
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_pbr/src/render/pbr_lighting.wgsl
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#define_import_path bevy_pbr::lighting

#import bevy_pbr::{
utils::PI,
mesh_view_types::POINT_LIGHT_FLAGS_SPOT_LIGHT_Y_NEGATIVE,
mesh_view_bindings as view_bindings,
}

#import bevy_render::maths::PI

// From the Filament design doc
// https://google.github.io/filament/Filament.html#table_symbols
// Symbol Definition
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_pbr/src/render/pbr_transmission.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
#import bevy_pbr::{
lighting,
prepass_utils,
utils::{PI, interleaved_gradient_noise},
utils::interleaved_gradient_noise,
utils,
mesh_view_bindings as view_bindings,
};

#import bevy_render::maths::PI

#import bevy_core_pipeline::tonemapping::{
approximate_inverse_tone_mapping
};
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/render/shadow_sampling.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

#import bevy_pbr::{
mesh_view_bindings as view_bindings,
utils::{PI, interleaved_gradient_noise},
utils::interleaved_gradient_noise,
utils,
}
#import bevy_render::maths::orthonormalize
#import bevy_render::maths::{orthonormalize, PI}

// Do the lookup, using HW 2x2 PCF and comparison
fn sample_shadow_map_hardware(light_local: vec2<f32>, depth: f32, array_index: i32) -> f32 {
Expand Down
6 changes: 5 additions & 1 deletion crates/bevy_pbr/src/render/shadows.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
#import bevy_pbr::{
mesh_view_types::POINT_LIGHT_FLAGS_SPOT_LIGHT_Y_NEGATIVE,
mesh_view_bindings as view_bindings,
utils::{hsv_to_rgb, PI_2},
shadow_sampling::{SPOT_SHADOW_TEXEL_SIZE, sample_shadow_cubemap, sample_shadow_map}
}

#import bevy_render::{
color_operations::hsv_to_rgb,
maths::PI_2
}

const flip_z: vec3<f32> = vec3<f32>(1.0, 1.0, -1.0);

fn fetch_point_shadow(light_id: u32, frag_position: vec4<f32>, surface_normal: vec3<f32>) -> f32 {
Expand Down
49 changes: 0 additions & 49 deletions crates/bevy_pbr/src/render/utils.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,6 @@

#import bevy_pbr::rgb9e5

const PI: f32 = 3.141592653589793; // π
const PI_2: f32 = 6.283185307179586; // 2π
const HALF_PI: f32 = 1.57079632679; // π/2
const FRAC_PI_3: f32 = 1.0471975512; // π/3
const E: f32 = 2.718281828459045; // exp(1)

// Converts HSV to RGB.
//
// Input: H ∈ [0, 2π), S ∈ [0, 1], V ∈ [0, 1].
// Output: R ∈ [0, 1], G ∈ [0, 1], B ∈ [0, 1].
//
// <https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB_alternative>
fn hsv_to_rgb(hsv: vec3<f32>) -> vec3<f32> {
let n = vec3(5.0, 3.0, 1.0);
let k = (n + hsv.x / FRAC_PI_3) % 6.0;
return hsv.z - hsv.z * hsv.y * max(vec3(0.0), min(k, min(4.0 - k, vec3(1.0))));
}

// Converts RGB to HSV.
//
// Input: R ∈ [0, 1], G ∈ [0, 1], B ∈ [0, 1].
// Output: H ∈ [0, 2π), S ∈ [0, 1], V ∈ [0, 1].
//
// <https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB>
fn rgb_to_hsv(rgb: vec3<f32>) -> vec3<f32> {
let x_max = max(rgb.r, max(rgb.g, rgb.b)); // i.e. V
let x_min = min(rgb.r, min(rgb.g, rgb.b));
let c = x_max - x_min; // chroma

var swizzle = vec3<f32>(0.0);
if (x_max == rgb.r) {
swizzle = vec3(rgb.gb, 0.0);
} else if (x_max == rgb.g) {
swizzle = vec3(rgb.br, 2.0);
} else {
swizzle = vec3(rgb.rg, 4.0);
}

let h = FRAC_PI_3 * (((swizzle.x - swizzle.y) / c + swizzle.z) % 6.0);

// Avoid division by zero.
var s = 0.0;
if (x_max > 0.0) {
s = c / x_max;
}

return vec3(h, s, x_max);
}

// Generates a random u32 in range [0, u32::MAX].
//
// `state` is a mutable reference to a u32 used as the seed.
Expand Down
7 changes: 3 additions & 4 deletions crates/bevy_pbr/src/ssao/gtao.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@
// Source code heavily based on XeGTAO v1.30 from Intel
// https://github.com/GameTechDev/XeGTAO/blob/0d177ce06bfa642f64d8af4de1197ad1bcb862d4/Source/Rendering/Shaders/XeGTAO.hlsli

#import bevy_pbr::{
gtao_utils::fast_acos,
utils::{PI, HALF_PI},
}
#import bevy_pbr::gtao_utils::fast_acos

#import bevy_render::{
view::View,
globals::Globals,
maths::{PI, HALF_PI},
}

@group(0) @binding(0) var preprocessed_depth: texture_2d<f32>;
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/ssao/gtao_utils.wgsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#define_import_path bevy_pbr::gtao_utils

#import bevy_pbr::utils::{PI, HALF_PI}
#import bevy_render::maths::{PI, HALF_PI}

// Approximates single-bounce ambient occlusion to multi-bounce ambient occlusion
// https://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf#page=78
Expand Down
47 changes: 47 additions & 0 deletions crates/bevy_render/src/color_operations.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#define_import_path bevy_render::color_operations

#import bevy_render::maths::FRAC_PI_3

// Converts HSV to RGB.
//
// Input: H ∈ [0, 2π), S ∈ [0, 1], V ∈ [0, 1].
// Output: R ∈ [0, 1], G ∈ [0, 1], B ∈ [0, 1].
//
// <https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB_alternative>
fn hsv_to_rgb(hsv: vec3<f32>) -> vec3<f32> {
let n = vec3(5.0, 3.0, 1.0);
let k = (n + hsv.x / FRAC_PI_3) % 6.0;
return hsv.z - hsv.z * hsv.y * max(vec3(0.0), min(k, min(4.0 - k, vec3(1.0))));
}

// Converts RGB to HSV.
//
// Input: R ∈ [0, 1], G ∈ [0, 1], B ∈ [0, 1].
// Output: H ∈ [0, 2π), S ∈ [0, 1], V ∈ [0, 1].
//
// <https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB>
fn rgb_to_hsv(rgb: vec3<f32>) -> vec3<f32> {
let x_max = max(rgb.r, max(rgb.g, rgb.b)); // i.e. V
let x_min = min(rgb.r, min(rgb.g, rgb.b));
let c = x_max - x_min; // chroma

var swizzle = vec3<f32>(0.0);
if (x_max == rgb.r) {
swizzle = vec3(rgb.gb, 0.0);
} else if (x_max == rgb.g) {
swizzle = vec3(rgb.br, 2.0);
} else {
swizzle = vec3(rgb.rg, 4.0);
}

let h = FRAC_PI_3 * (((swizzle.x - swizzle.y) / c + swizzle.z) % 6.0);

// Avoid division by zero.
var s = 0.0;
if (x_max > 0.0) {
s = c / x_max;
}

return vec3(h, s, x_max);
}

8 changes: 8 additions & 0 deletions crates/bevy_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ pub struct RenderApp;
pub const INSTANCE_INDEX_SHADER_HANDLE: Handle<Shader> =
Handle::weak_from_u128(10313207077636615845);
pub const MATHS_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(10665356303104593376);
pub const COLOR_OPERATIONS_SHADER_HANDLE: Handle<Shader> =
Handle::weak_from_u128(1844674407370955161);

impl Plugin for RenderPlugin {
/// Initializes the renderer, sets up the [`RenderSet`] and creates the rendering sub-app.
Expand Down Expand Up @@ -359,6 +361,12 @@ impl Plugin for RenderPlugin {

fn finish(&self, app: &mut App) {
load_internal_asset!(app, MATHS_SHADER_HANDLE, "maths.wgsl", Shader::from_wgsl);
load_internal_asset!(
app,
COLOR_OPERATIONS_SHADER_HANDLE,
"color_operations.wgsl",
Shader::from_wgsl
);
if let Some(future_renderer_resources) =
app.world_mut().remove_resource::<FutureRendererResources>()
{
Expand Down
6 changes: 6 additions & 0 deletions crates/bevy_render/src/maths.wgsl
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#define_import_path bevy_render::maths

const PI: f32 = 3.141592653589793; // π
const PI_2: f32 = 6.283185307179586; // 2π
const HALF_PI: f32 = 1.57079632679; // π/2
const FRAC_PI_3: f32 = 1.0471975512; // π/3
const E: f32 = 2.718281828459045; // exp(1)

fn affine2_to_square(affine: mat3x2<f32>) -> mat3x3<f32> {
return mat3x3<f32>(
vec3<f32>(affine[0].xy, 0.0),
Expand Down

0 comments on commit 6027890

Please sign in to comment.