Skip to content

Commit

Permalink
Use frostbite's specular sampling direction for environment map light
Browse files Browse the repository at this point in the history
  • Loading branch information
JMS55 committed Dec 8, 2024
1 parent 0707c07 commit 2702247
Showing 1 changed file with 29 additions and 23 deletions.
52 changes: 29 additions & 23 deletions crates/bevy_pbr/src/light_probe/environment_map.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
#import bevy_pbr::mesh_view_bindings as bindings
#import bevy_pbr::mesh_view_bindings::light_probes
#import bevy_pbr::mesh_view_bindings::environment_map_uniform
#import bevy_pbr::lighting::{
F_Schlick_vec, LayerLightingInput, LightingInput, LAYER_BASE, LAYER_CLEARCOAT
}
#import bevy_pbr::lighting::{F_Schlick_vec, LightingInput, LayerLightingInput, LAYER_BASE, LAYER_CLEARCOAT}
#import bevy_pbr::clustered_forward::ClusterableObjectIndexRanges

struct EnvironmentMapLight {
Expand All @@ -26,16 +24,17 @@ struct EnvironmentMapRadiances {
#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY

fn compute_radiances(
input: ptr<function, LightingInput>,
input: LayerLightingInput,
clusterable_object_index_ranges: ptr<function, ClusterableObjectIndexRanges>,
layer: u32,
world_position: vec3<f32>,
found_diffuse_indirect: bool,
) -> EnvironmentMapRadiances {
// Unpack.
let perceptual_roughness = (*input).layers[layer].perceptual_roughness;
let N = (*input).layers[layer].N;
let R = (*input).layers[layer].R;
let N = input.N;
let R = input.R;
let NdotV = input.NdotV;
let perceptual_roughness = input.perceptual_roughness;
let roughness = input.roughness;

var radiances: EnvironmentMapRadiances;

Expand Down Expand Up @@ -65,7 +64,7 @@ fn compute_radiances(

if (!found_diffuse_indirect) {
var irradiance_sample_dir = N;
// Rotating the world space ray direction by the environment light map transform matrix, it is
// Rotating the world space ray direction by the environment light map transform matrix, it is
// equivalent to rotating the diffuse environment cubemap itself.
irradiance_sample_dir = (environment_map_uniform.transform * vec4(irradiance_sample_dir, 1.0)).xyz;
// Cube maps are left-handed so we negate the z coordinate.
Expand All @@ -77,8 +76,8 @@ fn compute_radiances(
0.0).rgb * query_result.intensity;
}

var radiance_sample_dir = R;
// Rotating the world space ray direction by the environment light map transform matrix, it is
var radiance_sample_dir = radiance_sample_direction(N, R, roughness);
// Rotating the world space ray direction by the environment light map transform matrix, it is
// equivalent to rotating the specular environment cubemap itself.
radiance_sample_dir = (environment_map_uniform.transform * vec4(radiance_sample_dir, 1.0)).xyz;
// Cube maps are left-handed so we negate the z coordinate.
Expand All @@ -95,16 +94,17 @@ fn compute_radiances(
#else // MULTIPLE_LIGHT_PROBES_IN_ARRAY

fn compute_radiances(
input: ptr<function, LightingInput>,
input: LayerLightingInput,
clusterable_object_index_ranges: ptr<function, ClusterableObjectIndexRanges>,
layer: u32,
world_position: vec3<f32>,
found_diffuse_indirect: bool,
) -> EnvironmentMapRadiances {
// Unpack.
let perceptual_roughness = (*input).layers[layer].perceptual_roughness;
let N = (*input).layers[layer].N;
let R = (*input).layers[layer].R;
let N = input.N;
let R = input.R;
let NdotV = input.NdotV;
let perceptual_roughness = input.perceptual_roughness;
let roughness = input.roughness;

var radiances: EnvironmentMapRadiances;

Expand All @@ -123,7 +123,7 @@ fn compute_radiances(

if (!found_diffuse_indirect) {
var irradiance_sample_dir = N;
// Rotating the world space ray direction by the environment light map transform matrix, it is
// Rotating the world space ray direction by the environment light map transform matrix, it is
// equivalent to rotating the diffuse environment cubemap itself.
irradiance_sample_dir = (environment_map_uniform.transform * vec4(irradiance_sample_dir, 1.0)).xyz;
// Cube maps are left-handed so we negate the z coordinate.
Expand All @@ -135,8 +135,8 @@ fn compute_radiances(
0.0).rgb * intensity;
}

var radiance_sample_dir = R;
// Rotating the world space ray direction by the environment light map transform matrix, it is
var radiance_sample_dir = radiance_sample_direction(N, R, roughness);
// Rotating the world space ray direction by the environment light map transform matrix, it is
// equivalent to rotating the specular environment cubemap itself.
radiance_sample_dir = (environment_map_uniform.transform * vec4(radiance_sample_dir, 1.0)).xyz;
// Cube maps are left-handed so we negate the z coordinate.
Expand Down Expand Up @@ -174,9 +174,8 @@ fn environment_map_light_clearcoat(
let inv_Fc = 1.0 - Fc;

let clearcoat_radiances = compute_radiances(
input,
(*input).layers[LAYER_CLEARCOAT],
clusterable_object_index_ranges,
LAYER_CLEARCOAT,
world_position,
found_diffuse_indirect,
);
Expand Down Expand Up @@ -206,9 +205,8 @@ fn environment_map_light(
var out: EnvironmentMapLight;

let radiances = compute_radiances(
input,
(*input).layers[LAYER_BASE],
clusterable_object_index_ranges,
LAYER_BASE,
world_position,
found_diffuse_indirect,
);
Expand Down Expand Up @@ -256,3 +254,11 @@ fn environment_map_light(

return out;
}

// "Moving Frostbite to Physically Based Rendering 3.0", listing 22
// https://seblagarde.wordpress.com/wp-content/uploads/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
fn radiance_sample_direction(N: vec3<f32>, R: vec3<f32>, roughness: f32) -> vec3<f32> {
let smoothness = saturate(1.0 - roughness);
let lerp_factor = smoothness * sqrt((smoothness) + roughness);
return mix(N, R, lerp_factor);
}

0 comments on commit 2702247

Please sign in to comment.