mirror of
https://github.com/bevyengine/bevy
synced 2024-12-24 20:13:07 +00:00
6027890a11
# 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`.
63 lines
1.8 KiB
WebGPU Shading Language
63 lines
1.8 KiB
WebGPU Shading Language
#import bevy_pbr::{
|
|
mesh_view_bindings,
|
|
forward_io::VertexOutput,
|
|
}
|
|
|
|
#import bevy_render::maths::PI
|
|
|
|
#ifdef TONEMAP_IN_SHADER
|
|
#import bevy_core_pipeline::tonemapping::tone_mapping
|
|
#endif
|
|
|
|
// Sweep across hues on y axis with value from 0.0 to +15EV across x axis
|
|
// quantized into 24 steps for both axis.
|
|
fn color_sweep(uv_input: vec2<f32>) -> vec3<f32> {
|
|
var uv = uv_input;
|
|
let steps = 24.0;
|
|
uv.y = uv.y * (1.0 + 1.0 / steps);
|
|
let ratio = 2.0;
|
|
|
|
let h = PI * 2.0 * floor(1.0 + steps * uv.y) / steps;
|
|
let L = floor(uv.x * steps * ratio) / (steps * ratio) - 0.5;
|
|
|
|
var color = vec3(0.0);
|
|
if uv.y < 1.0 {
|
|
color = cos(h + vec3(0.0, 1.0, 2.0) * PI * 2.0 / 3.0);
|
|
let maxRGB = max(color.r, max(color.g, color.b));
|
|
let minRGB = min(color.r, min(color.g, color.b));
|
|
color = exp(15.0 * L) * (color - minRGB) / (maxRGB - minRGB);
|
|
} else {
|
|
color = vec3(exp(15.0 * L));
|
|
}
|
|
return color;
|
|
}
|
|
|
|
fn hsv_to_srgb(c: vec3<f32>) -> vec3<f32> {
|
|
let K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
|
let p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
|
return c.z * mix(K.xxx, clamp(p - K.xxx, vec3(0.0), vec3(1.0)), c.y);
|
|
}
|
|
|
|
// Generates a continuous sRGB sweep.
|
|
fn continuous_hue(uv: vec2<f32>) -> vec3<f32> {
|
|
return hsv_to_srgb(vec3(uv.x, 1.0, 1.0)) * max(0.0, exp2(uv.y * 9.0) - 1.0);
|
|
}
|
|
|
|
@fragment
|
|
fn fragment(
|
|
in: VertexOutput,
|
|
) -> @location(0) vec4<f32> {
|
|
var uv = in.uv;
|
|
var out = vec3(0.0);
|
|
if uv.y > 0.5 {
|
|
uv.y = 1.0 - uv.y;
|
|
out = color_sweep(vec2(uv.x, uv.y * 2.0));
|
|
} else {
|
|
out = continuous_hue(vec2(uv.y * 2.0, uv.x));
|
|
}
|
|
var color = vec4(out, 1.0);
|
|
#ifdef TONEMAP_IN_SHADER
|
|
color = tone_mapping(color, mesh_view_bindings::view.color_grading);
|
|
#endif
|
|
return color;
|
|
}
|