1#define_import_path bevy_pbr::environment_map 3#import bevy_pbr::light_probe::query_light_probe 4#import bevy_pbr::mesh_view_bindings as bindings 5#import bevy_pbr::mesh_view_bindings::light_probes 6#import bevy_pbr::mesh_view_bindings::environment_map_uniform 7#import bevy_pbr::lighting::{F_Schlick_vec, LightingInput, LayerLightingInput, LAYER_BASE, LAYER_CLEARCOAT} 8#import bevy_pbr::clustered_forward::ClusterableObjectIndexRanges 10struct EnvironmentMapLight { 15struct EnvironmentMapRadiances { 16 irradiance: vec3<f32>, 24#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY 27 input: LayerLightingInput, 28 clusterable_object_index_ranges: ptr<function, ClusterableObjectIndexRanges>, 29 world_position: vec3<f32>, 30 found_diffuse_indirect: bool, 31) -> EnvironmentMapRadiances { 35 let perceptual_roughness = input.perceptual_roughness; 36 let roughness = input.roughness; 38 var radiances: EnvironmentMapRadiances; 41 var query_result = query_light_probe( 44 clusterable_object_index_ranges, 48 if (query_result.texture_index < 0) { 49 query_result.texture_index = light_probes.view_cubemap_index; 50 query_result.intensity = light_probes.intensity_for_view; 51 query_result.affects_lightmapped_mesh_diffuse = 52 light_probes.view_environment_map_affects_lightmapped_mesh_diffuse != 0u; 56 if (query_result.texture_index < 0) { 57 radiances.irradiance = vec3(0.0); 58 radiances.radiance = vec3(0.0); 63 let radiance_level = perceptual_roughness * f32(textureNumLevels( 64 bindings::specular_environment_maps[query_result.texture_index]) - 1u); 68 var enable_diffuse = !found_diffuse_indirect; 70 enable_diffuse = enable_diffuse && query_result.affects_lightmapped_mesh_diffuse; 74 var irradiance_sample_dir = N; 77 irradiance_sample_dir = (environment_map_uniform.transform * vec4(irradiance_sample_dir, 1.0)).xyz; 79 irradiance_sample_dir.z = -irradiance_sample_dir.z; 80 radiances.irradiance = textureSampleLevel( 81 bindings::diffuse_environment_maps[query_result.texture_index], 82 bindings::environment_map_sampler, 83 irradiance_sample_dir, 84 0.0).rgb * query_result.intensity; 87 var radiance_sample_dir = radiance_sample_direction(N, R, roughness); 90 radiance_sample_dir = (environment_map_uniform.transform * vec4(radiance_sample_dir, 1.0)).xyz; 92 radiance_sample_dir.z = -radiance_sample_dir.z; 93 radiances.radiance = textureSampleLevel( 94 bindings::specular_environment_maps[query_result.texture_index], 95 bindings::environment_map_sampler, 97 radiance_level).rgb * query_result.intensity; 102#else // MULTIPLE_LIGHT_PROBES_IN_ARRAY 105 input: LayerLightingInput, 106 clusterable_object_index_ranges: ptr<function, ClusterableObjectIndexRanges>, 107 world_position: vec3<f32>, 108 found_diffuse_indirect: bool, 109) -> EnvironmentMapRadiances { 113 let perceptual_roughness = input.perceptual_roughness; 114 let roughness = input.roughness; 116 var radiances: EnvironmentMapRadiances; 118 if (light_probes.view_cubemap_index < 0) { 119 radiances.irradiance = vec3(0.0); 120 radiances.radiance = vec3(0.0); 127 let radiance_level = perceptual_roughness * f32(light_probes.smallest_specular_mip_level_for_view); 129 let intensity = light_probes.intensity_for_view; 133 var enable_diffuse = !found_diffuse_indirect; 135 enable_diffuse = enable_diffuse && 136 light_probes.view_environment_map_affects_lightmapped_mesh_diffuse; 139 if (enable_diffuse) { 140 var irradiance_sample_dir = N; 143 irradiance_sample_dir = (environment_map_uniform.transform * vec4(irradiance_sample_dir, 1.0)).xyz; 145 irradiance_sample_dir.z = -irradiance_sample_dir.z; 146 radiances.irradiance = textureSampleLevel( 147 bindings::diffuse_environment_map, 148 bindings::environment_map_sampler, 149 irradiance_sample_dir, 150 0.0).rgb * intensity; 153 var radiance_sample_dir = radiance_sample_direction(N, R, roughness); 156 radiance_sample_dir = (environment_map_uniform.transform * vec4(radiance_sample_dir, 1.0)).xyz; 158 radiance_sample_dir.z = -radiance_sample_dir.z; 159 radiances.radiance = textureSampleLevel( 160 bindings::specular_environment_map, 161 bindings::environment_map_sampler, 163 radiance_level).rgb * intensity; 168#endif // MULTIPLE_LIGHT_PROBES_IN_ARRAY 170#ifdef STANDARD_MATERIAL_CLEARCOAT 174fn environment_map_light_clearcoat( 175 out: ptr<function, EnvironmentMapLight>, 176 input: ptr<function, LightingInput>, 177 clusterable_object_index_ranges: ptr<function, ClusterableObjectIndexRanges>, 178 found_diffuse_indirect: bool, 181 let world_position = (*input).P; 182 let clearcoat_NdotV = (*input).layers[LAYER_CLEARCOAT].NdotV; 183 let clearcoat_strength = (*input).clearcoat_strength; 187 let clearcoat_F0 = vec3<f32>(0.04); 188 let Fc = F_Schlick_vec(clearcoat_F0, 1.0, clearcoat_NdotV) * clearcoat_strength; 189 let inv_Fc = 1.0 - Fc; 191 let clearcoat_radiances = compute_radiances( 192 (*input).layers[LAYER_CLEARCOAT], 193 clusterable_object_index_ranges, 195 found_diffuse_indirect, 201 (*out).diffuse *= inv_Fc; 202 (*out).specular = (*out).specular * inv_Fc * inv_Fc + clearcoat_radiances.radiance * Fc; 205#endif // STANDARD_MATERIAL_CLEARCOAT 207fn environment_map_light( 208 input: ptr<function, LightingInput>, 209 clusterable_object_index_ranges: ptr<function, ClusterableObjectIndexRanges>, 210 found_diffuse_indirect: bool, 211) -> EnvironmentMapLight { 213 let roughness = (*input).layers[LAYER_BASE].roughness; 214 let diffuse_color = (*input).diffuse_color; 215 let NdotV = (*input).layers[LAYER_BASE].NdotV; 216 let F_ab = (*input).F_ab; 217 let F0 = (*input).F0_; 218 let world_position = (*input).P; 220 var out: EnvironmentMapLight; 222 let radiances = compute_radiances( 223 (*input).layers[LAYER_BASE], 224 clusterable_object_index_ranges, 226 found_diffuse_indirect, 229 if (all(radiances.irradiance == vec3(0.0)) && all(radiances.radiance == vec3(0.0))) { 230 out.diffuse = vec3(0.0); 231 out.specular = vec3(0.0); 238 let specular_occlusion = saturate(dot(F0, vec3(50.0 * 0.33))); 243 let Ess = F_ab.x + F_ab.y; 244 let FssEss = (F0 * Ess) * specular_occlusion; 246 let Favg = F0 + (1.0 - F0) / 21.0; 247 let Fms = FssEss * Favg / (1.0 - Ems * Favg); 248 let FmsEms = Fms * Ems; 249 let Edss = 1.0 - (FssEss + FmsEms); 250 let kD = diffuse_color * Edss; 252 if (!found_diffuse_indirect) { 253 out.diffuse = (FmsEms + kD) * radiances.irradiance; 255 out.diffuse = vec3(0.0); 258 out.specular = FssEss * radiances.radiance; 260#ifdef STANDARD_MATERIAL_CLEARCOAT 261 environment_map_light_clearcoat( 264 clusterable_object_index_ranges, 265 found_diffuse_indirect, 267#endif // STANDARD_MATERIAL_CLEARCOAT 274fn radiance_sample_direction(N: vec3<f32>, R: vec3<f32>, roughness: f32) -> vec3<f32> { 275 let smoothness = saturate(1.0 - roughness); 276 let lerp_factor = smoothness * (sqrt(smoothness) + roughness); 277 return mix(N, R, lerp_factor);