mirror of
https://github.com/bevyengine/bevy
synced 2024-11-28 07:30:23 +00:00
move wgsl color operations from bevy_pbr to bevy_render (#13209)
# 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`.
This commit is contained in:
parent
40837501b4
commit
6027890a11
14 changed files with 92 additions and 64 deletions
|
@ -1,9 +1,10 @@
|
||||||
#import bevy_pbr::{
|
#import bevy_pbr::{
|
||||||
mesh_view_bindings,
|
mesh_view_bindings,
|
||||||
forward_io::VertexOutput,
|
forward_io::VertexOutput,
|
||||||
utils::PI,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#import bevy_render::maths::PI
|
||||||
|
|
||||||
#ifdef TONEMAP_IN_SHADER
|
#ifdef TONEMAP_IN_SHADER
|
||||||
#import bevy_core_pipeline::tonemapping::tone_mapping
|
#import bevy_core_pipeline::tonemapping::tone_mapping
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#define_import_path bevy_core_pipeline::tonemapping
|
#define_import_path bevy_core_pipeline::tonemapping
|
||||||
|
|
||||||
#import bevy_render::view::ColorGrading
|
#import bevy_render::{
|
||||||
#import bevy_pbr::utils::{PI_2, hsv_to_rgb, rgb_to_hsv};
|
view::ColorGrading,
|
||||||
|
color_operations::{hsv_to_rgb, rgb_to_hsv},
|
||||||
|
maths::PI_2
|
||||||
|
}
|
||||||
|
|
||||||
// hack !! not sure what to do with this
|
// hack !! not sure what to do with this
|
||||||
#ifdef TONEMAPPING_PASS
|
#ifdef TONEMAPPING_PASS
|
||||||
|
|
|
@ -2,7 +2,12 @@
|
||||||
|
|
||||||
#import bevy_pbr::{
|
#import bevy_pbr::{
|
||||||
mesh_view_bindings as bindings,
|
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
|
// NOTE: Keep in sync with bevy_pbr/src/light.rs
|
||||||
|
|
|
@ -12,9 +12,10 @@
|
||||||
ambient,
|
ambient,
|
||||||
irradiance_volume,
|
irradiance_volume,
|
||||||
mesh_types::{MESH_FLAGS_SHADOW_RECEIVER_BIT, MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT},
|
mesh_types::{MESH_FLAGS_SHADOW_RECEIVER_BIT, MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT},
|
||||||
utils::E,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#import bevy_render::maths::E
|
||||||
|
|
||||||
#ifdef ENVIRONMENT_MAP
|
#ifdef ENVIRONMENT_MAP
|
||||||
#import bevy_pbr::environment_map
|
#import bevy_pbr::environment_map
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#define_import_path bevy_pbr::lighting
|
#define_import_path bevy_pbr::lighting
|
||||||
|
|
||||||
#import bevy_pbr::{
|
#import bevy_pbr::{
|
||||||
utils::PI,
|
|
||||||
mesh_view_types::POINT_LIGHT_FLAGS_SPOT_LIGHT_Y_NEGATIVE,
|
mesh_view_types::POINT_LIGHT_FLAGS_SPOT_LIGHT_Y_NEGATIVE,
|
||||||
mesh_view_bindings as view_bindings,
|
mesh_view_bindings as view_bindings,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#import bevy_render::maths::PI
|
||||||
|
|
||||||
// From the Filament design doc
|
// From the Filament design doc
|
||||||
// https://google.github.io/filament/Filament.html#table_symbols
|
// https://google.github.io/filament/Filament.html#table_symbols
|
||||||
// Symbol Definition
|
// Symbol Definition
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
#import bevy_pbr::{
|
#import bevy_pbr::{
|
||||||
lighting,
|
lighting,
|
||||||
prepass_utils,
|
prepass_utils,
|
||||||
utils::{PI, interleaved_gradient_noise},
|
utils::interleaved_gradient_noise,
|
||||||
utils,
|
utils,
|
||||||
mesh_view_bindings as view_bindings,
|
mesh_view_bindings as view_bindings,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#import bevy_render::maths::PI
|
||||||
|
|
||||||
#import bevy_core_pipeline::tonemapping::{
|
#import bevy_core_pipeline::tonemapping::{
|
||||||
approximate_inverse_tone_mapping
|
approximate_inverse_tone_mapping
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
#import bevy_pbr::{
|
#import bevy_pbr::{
|
||||||
mesh_view_bindings as view_bindings,
|
mesh_view_bindings as view_bindings,
|
||||||
utils::{PI, interleaved_gradient_noise},
|
utils::interleaved_gradient_noise,
|
||||||
utils,
|
utils,
|
||||||
}
|
}
|
||||||
#import bevy_render::maths::orthonormalize
|
#import bevy_render::maths::{orthonormalize, PI}
|
||||||
|
|
||||||
// Do the lookup, using HW 2x2 PCF and comparison
|
// Do the lookup, using HW 2x2 PCF and comparison
|
||||||
fn sample_shadow_map_hardware(light_local: vec2<f32>, depth: f32, array_index: i32) -> f32 {
|
fn sample_shadow_map_hardware(light_local: vec2<f32>, depth: f32, array_index: i32) -> f32 {
|
||||||
|
|
|
@ -3,10 +3,14 @@
|
||||||
#import bevy_pbr::{
|
#import bevy_pbr::{
|
||||||
mesh_view_types::POINT_LIGHT_FLAGS_SPOT_LIGHT_Y_NEGATIVE,
|
mesh_view_types::POINT_LIGHT_FLAGS_SPOT_LIGHT_Y_NEGATIVE,
|
||||||
mesh_view_bindings as view_bindings,
|
mesh_view_bindings as view_bindings,
|
||||||
utils::{hsv_to_rgb, PI_2},
|
|
||||||
shadow_sampling::{SPOT_SHADOW_TEXEL_SIZE, sample_shadow_cubemap, sample_shadow_map}
|
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);
|
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 {
|
fn fetch_point_shadow(light_id: u32, frag_position: vec4<f32>, surface_normal: vec3<f32>) -> f32 {
|
||||||
|
|
|
@ -2,55 +2,6 @@
|
||||||
|
|
||||||
#import bevy_pbr::rgb9e5
|
#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].
|
// Generates a random u32 in range [0, u32::MAX].
|
||||||
//
|
//
|
||||||
// `state` is a mutable reference to a u32 used as the seed.
|
// `state` is a mutable reference to a u32 used as the seed.
|
||||||
|
|
|
@ -5,13 +5,12 @@
|
||||||
// Source code heavily based on XeGTAO v1.30 from Intel
|
// Source code heavily based on XeGTAO v1.30 from Intel
|
||||||
// https://github.com/GameTechDev/XeGTAO/blob/0d177ce06bfa642f64d8af4de1197ad1bcb862d4/Source/Rendering/Shaders/XeGTAO.hlsli
|
// https://github.com/GameTechDev/XeGTAO/blob/0d177ce06bfa642f64d8af4de1197ad1bcb862d4/Source/Rendering/Shaders/XeGTAO.hlsli
|
||||||
|
|
||||||
#import bevy_pbr::{
|
#import bevy_pbr::gtao_utils::fast_acos
|
||||||
gtao_utils::fast_acos,
|
|
||||||
utils::{PI, HALF_PI},
|
|
||||||
}
|
|
||||||
#import bevy_render::{
|
#import bevy_render::{
|
||||||
view::View,
|
view::View,
|
||||||
globals::Globals,
|
globals::Globals,
|
||||||
|
maths::{PI, HALF_PI},
|
||||||
}
|
}
|
||||||
|
|
||||||
@group(0) @binding(0) var preprocessed_depth: texture_2d<f32>;
|
@group(0) @binding(0) var preprocessed_depth: texture_2d<f32>;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#define_import_path bevy_pbr::gtao_utils
|
#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
|
// 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
|
// https://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf#page=78
|
||||||
|
|
47
crates/bevy_render/src/color_operations.wgsl
Normal file
47
crates/bevy_render/src/color_operations.wgsl
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -236,6 +236,8 @@ pub struct RenderApp;
|
||||||
pub const INSTANCE_INDEX_SHADER_HANDLE: Handle<Shader> =
|
pub const INSTANCE_INDEX_SHADER_HANDLE: Handle<Shader> =
|
||||||
Handle::weak_from_u128(10313207077636615845);
|
Handle::weak_from_u128(10313207077636615845);
|
||||||
pub const MATHS_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(10665356303104593376);
|
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 {
|
impl Plugin for RenderPlugin {
|
||||||
/// Initializes the renderer, sets up the [`RenderSet`] and creates the rendering sub-app.
|
/// Initializes the renderer, sets up the [`RenderSet`] and creates the rendering sub-app.
|
||||||
|
@ -359,6 +361,12 @@ impl Plugin for RenderPlugin {
|
||||||
|
|
||||||
fn finish(&self, app: &mut App) {
|
fn finish(&self, app: &mut App) {
|
||||||
load_internal_asset!(app, MATHS_SHADER_HANDLE, "maths.wgsl", Shader::from_wgsl);
|
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) =
|
if let Some(future_renderer_resources) =
|
||||||
app.world_mut().remove_resource::<FutureRendererResources>()
|
app.world_mut().remove_resource::<FutureRendererResources>()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
#define_import_path bevy_render::maths
|
#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> {
|
fn affine2_to_square(affine: mat3x2<f32>) -> mat3x3<f32> {
|
||||||
return mat3x3<f32>(
|
return mat3x3<f32>(
|
||||||
vec3<f32>(affine[0].xy, 0.0),
|
vec3<f32>(affine[0].xy, 0.0),
|
||||||
|
|
Loading…
Reference in a new issue