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::{ 8 F_Schlick_vec, LayerLightingInput, LightingInput, LAYER_BASE, LAYER_CLEARCOAT 11struct EnvironmentMapLight { 16struct EnvironmentMapRadiances { 17 irradiance: vec3<f32>, 25#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY 28 input: ptr<function, LightingInput>, 30 world_position: vec3<f32>, 31 found_diffuse_indirect: bool, 32) -> EnvironmentMapRadiances { 34 let perceptual_roughness = (*input).layers[layer].perceptual_roughness; 35 let N = (*input).layers[layer].N; 36 let R = (*input).layers[layer].R; 38 var radiances: EnvironmentMapRadiances; 41 var query_result = query_light_probe(world_position, false); 44 if (query_result.texture_index < 0) { 45 query_result.texture_index = light_probes.view_cubemap_index; 46 query_result.intensity = light_probes.intensity_for_view; 50 if (query_result.texture_index < 0) { 51 radiances.irradiance = vec3(0.0); 52 radiances.radiance = vec3(0.0); 57 let radiance_level = perceptual_roughness * f32(textureNumLevels( 58 bindings::specular_environment_maps[query_result.texture_index]) - 1u); 60 if (!found_diffuse_indirect) { 61 var irradiance_sample_dir = N; 64 irradiance_sample_dir = (environment_map_uniform.transform * vec4(irradiance_sample_dir, 1.0)).xyz; 66 irradiance_sample_dir.z = -irradiance_sample_dir.z; 67 radiances.irradiance = textureSampleLevel( 68 bindings::diffuse_environment_maps[query_result.texture_index], 69 bindings::environment_map_sampler, 70 irradiance_sample_dir, 71 0.0).rgb * query_result.intensity; 74 var radiance_sample_dir = R; 77 radiance_sample_dir = (environment_map_uniform.transform * vec4(radiance_sample_dir, 1.0)).xyz; 79 radiance_sample_dir.z = -radiance_sample_dir.z; 80 radiances.radiance = textureSampleLevel( 81 bindings::specular_environment_maps[query_result.texture_index], 82 bindings::environment_map_sampler, 84 radiance_level).rgb * query_result.intensity; 89#else // MULTIPLE_LIGHT_PROBES_IN_ARRAY 92 input: ptr<function, LightingInput>, 94 world_position: vec3<f32>, 95 found_diffuse_indirect: bool, 96) -> EnvironmentMapRadiances { 98 let perceptual_roughness = (*input).layers[layer].perceptual_roughness; 99 let N = (*input).layers[layer].N; 100 let R = (*input).layers[layer].R; 102 var radiances: EnvironmentMapRadiances; 104 if (light_probes.view_cubemap_index < 0) { 105 radiances.irradiance = vec3(0.0); 106 radiances.radiance = vec3(0.0); 113 let radiance_level = perceptual_roughness * f32(light_probes.smallest_specular_mip_level_for_view); 115 let intensity = light_probes.intensity_for_view; 117 if (!found_diffuse_indirect) { 118 var irradiance_sample_dir = N; 121 irradiance_sample_dir = (environment_map_uniform.transform * vec4(irradiance_sample_dir, 1.0)).xyz; 123 irradiance_sample_dir.z = -irradiance_sample_dir.z; 124 radiances.irradiance = textureSampleLevel( 125 bindings::diffuse_environment_map, 126 bindings::environment_map_sampler, 127 irradiance_sample_dir, 128 0.0).rgb * intensity; 131 var radiance_sample_dir = R; 134 radiance_sample_dir = (environment_map_uniform.transform * vec4(radiance_sample_dir, 1.0)).xyz; 136 radiance_sample_dir.z = -radiance_sample_dir.z; 137 radiances.radiance = textureSampleLevel( 138 bindings::specular_environment_map, 139 bindings::environment_map_sampler, 141 radiance_level).rgb * intensity; 146#endif // MULTIPLE_LIGHT_PROBES_IN_ARRAY 148#ifdef STANDARD_MATERIAL_CLEARCOAT 152fn environment_map_light_clearcoat( 153 out: ptr<function, EnvironmentMapLight>, 154 input: ptr<function, LightingInput>, 155 found_diffuse_indirect: bool, 158 let world_position = (*input).P; 159 let clearcoat_NdotV = (*input).layers[LAYER_CLEARCOAT].NdotV; 160 let clearcoat_strength = (*input).clearcoat_strength; 164 let clearcoat_F0 = vec3<f32>(0.04); 165 let Fc = F_Schlick_vec(clearcoat_F0, 1.0, clearcoat_NdotV) * clearcoat_strength; 166 let inv_Fc = 1.0 - Fc; 168 let clearcoat_radiances = compute_radiances( 169 input, LAYER_CLEARCOAT, world_position, found_diffuse_indirect); 174 (*out).diffuse *= inv_Fc; 175 (*out).specular = (*out).specular * inv_Fc * inv_Fc + clearcoat_radiances.radiance * Fc; 178#endif // STANDARD_MATERIAL_CLEARCOAT 180fn environment_map_light( 181 input: ptr<function, LightingInput>, 182 found_diffuse_indirect: bool, 183) -> EnvironmentMapLight { 185 let roughness = (*input).layers[LAYER_BASE].roughness; 186 let diffuse_color = (*input).diffuse_color; 187 let NdotV = (*input).layers[LAYER_BASE].NdotV; 188 let F_ab = (*input).F_ab; 189 let F0 = (*input).F0_; 190 let world_position = (*input).P; 192 var out: EnvironmentMapLight; 194 let radiances = compute_radiances(input, LAYER_BASE, world_position, found_diffuse_indirect); 195 if (all(radiances.irradiance == vec3(0.0)) && all(radiances.radiance == vec3(0.0))) { 196 out.diffuse = vec3(0.0); 197 out.specular = vec3(0.0); 204 let specular_occlusion = saturate(dot(F0, vec3(50.0 * 0.33))); 208 let Fr = max(vec3(1.0 - roughness), F0) - F0; 209 let kS = F0 + Fr * pow(1.0 - NdotV, 5.0); 210 let Ess = F_ab.x + F_ab.y; 211 let FssEss = kS * Ess * specular_occlusion; 213 let Favg = F0 + (1.0 - F0) / 21.0; 214 let Fms = FssEss * Favg / (1.0 - Ems * Favg); 215 let FmsEms = Fms * Ems; 216 let Edss = 1.0 - (FssEss + FmsEms); 217 let kD = diffuse_color * Edss; 219 if (!found_diffuse_indirect) { 220 out.diffuse = (FmsEms + kD) * radiances.irradiance; 222 out.diffuse = vec3(0.0); 225 out.specular = FssEss * radiances.radiance; 227#ifdef STANDARD_MATERIAL_CLEARCOAT 228 environment_map_light_clearcoat(&out, input, found_diffuse_indirect); 229#endif // STANDARD_MATERIAL_CLEARCOAT