diff --git a/crates/bevy_pbr/src/light_probe/environment_map.wgsl b/crates/bevy_pbr/src/light_probe/environment_map.wgsl index 0720a30dbe..1bfbdb2da0 100644 --- a/crates/bevy_pbr/src/light_probe/environment_map.wgsl +++ b/crates/bevy_pbr/src/light_probe/environment_map.wgsl @@ -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 { @@ -26,16 +24,17 @@ struct EnvironmentMapRadiances { #ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY fn compute_radiances( - input: ptr, + input: LayerLightingInput, clusterable_object_index_ranges: ptr, - layer: u32, world_position: vec3, 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; @@ -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. @@ -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. @@ -95,16 +94,17 @@ fn compute_radiances( #else // MULTIPLE_LIGHT_PROBES_IN_ARRAY fn compute_radiances( - input: ptr, + input: LayerLightingInput, clusterable_object_index_ranges: ptr, - layer: u32, world_position: vec3, 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; @@ -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. @@ -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. @@ -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, ); @@ -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, ); @@ -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#page=70 +fn radiance_sample_direction(N: vec3, R: vec3, roughness: f32) -> vec3 { + let smoothness = saturate(1.0 - roughness); + let lerp_factor = smoothness * (sqrt(smoothness) + roughness); + return mix(N, R, lerp_factor); +}