3import bevy_core_pipeline::fullscreen_vertex_shader::FullscreenVertexOutput; 7 pbr_lighting as lighting, 8 pbr_lighting::{LAYER_BASE, LAYER_CLEARCOAT}, 12 depth_prepass_texture, 13 deferred_prepass_texture, 18 view_transformations::{ 24 position_world_to_ndc, 25 position_world_to_view, 29 functions::pbr_input_from_deferred_gbuffer, 30 types as pbr_deferred_types, 32 prepass::utils as prepass_utils, 34 depth_ray_march_from_cs, 35 depth_ray_march_march, 36 depth_ray_march_new_from_depth, 37 depth_ray_march_to_ws_dir, 42 maths::orthonormalize, 45@if(ENVIRONMENT_MAP) import package::light_probe::environment_map; 48@group(2) @binding(0) var color_texture: texture_2d<f32>; 51@group(2) @binding(1) var color_sampler: sampler; 55@group(2) @binding(4) var stbn_texture: texture_2d_array<f32>; 59 value_over_pdf: vec3<f32>, 62fn sample_specular_brdf(wo: vec3<f32>, roughness: f32, F0: vec3<f32>, urand: vec2<f32>, N: vec3<f32>) -> BrdfSample { 63 var brdf_sample: BrdfSample; 66 let wi = lighting::sample_visible_ggx(urand, roughness, N, wo); 67 let H = normalize(wo + wi); 68 let NdotL = max(dot(N, wi), 0.0001); 69 let NdotV = max(dot(N, wo), 0.0001); 70 let VdotH = max(dot(wo, H), 0.0001); 72 let F = lighting::F_Schlick_vec(F0, 1.0, VdotH); 75 let a2 = roughness * roughness; 76 let lambdaV = NdotL * sqrt((NdotV - a2 * NdotV) * NdotV + a2); 77 let lambdaL = NdotV * sqrt((NdotL - a2 * NdotL) * NdotL + a2); 80 brdf_sample.value_over_pdf = F * (NdotV * NdotL + lambdaV) / (lambdaV + lambdaL); 102fn evaluate_ssr(R_world: vec3<f32>, P_world: vec3<f32>, jitter: f32) -> vec4<f32> { 103 let depth_size = vec2<f32>(textureDimensions(depth_prepass_texture)); 105 var raymarch = depth_ray_march_new_from_depth(depth_size); 106 depth_ray_march_from_cs(&raymarch, position_world_to_ndc(P_world)); 107 depth_ray_march_to_ws_dir(&raymarch, normalize(R_world)); 108 raymarch.linear_steps = ssr_settings.linear_steps; 109 raymarch.bisection_steps = ssr_settings.bisection_steps; 110 raymarch.use_secant = ssr_settings.use_secant != 0u; 111 raymarch.depth_thickness_linear_z = ssr_settings.thickness; 112 raymarch.jitter = jitter; 113 raymarch.march_behind_surfaces = false; 115 let raymarch_result = depth_ray_march_march(&raymarch); 116 if (raymarch_result.hit) { 118 textureSampleLevel(color_texture, color_sampler, raymarch_result.hit_uv, 0.0).rgb, 123 return vec4(0.0, 0.0, 0.0, 1.0); 127fn fragment(in: FullscreenVertexOutput) -> @location(0) vec4<f32> { 129 var frag_coord = in.position; 130 frag_coord.z = prepass_utils::prepass_depth(in.position, 0u); 133 let fragment = textureLoad(color_texture, vec2<i32>(frag_coord.xy), 0); 134 let gbuffer = textureLoad(deferred_prepass_texture, vec2<i32>(frag_coord.xy), 0); 135 let pbr_input = pbr_input_from_deferred_gbuffer(frag_coord, gbuffer); 138 let perceptual_roughness = pbr_input.material.perceptual_roughness; 141 if (ssr_settings.min_perceptual_roughness >= ssr_settings.min_perceptual_roughness_fully_active) { 142 min_fade = step(ssr_settings.min_perceptual_roughness, perceptual_roughness); 144 min_fade = smoothstep( 145 ssr_settings.min_perceptual_roughness, 146 ssr_settings.min_perceptual_roughness_fully_active, 152 if (ssr_settings.max_perceptual_roughness_starts_to_fade >= ssr_settings.max_perceptual_roughness) { 153 max_fade = step(perceptual_roughness, ssr_settings.max_perceptual_roughness); 155 max_fade = 1.0 - smoothstep( 156 ssr_settings.max_perceptual_roughness_starts_to_fade, 157 ssr_settings.max_perceptual_roughness, 162 var fade = saturate(min_fade) * saturate(max_fade); 164 let ndc_position = frag_coord_to_ndc(vec4(in.position.xy, frag_coord.z, 1.0)); 165 let uv = ndc_to_uv(ndc_position.xy); 166 let dist = min(uv, vec2(1.0) - uv); 167 var fade_xy: vec2<f32>; 168 if (ssr_settings.edge_fadeout_no_longer_active >= ssr_settings.edge_fadeout_fully_active) { 169 fade_xy = step(vec2(ssr_settings.edge_fadeout_no_longer_active), dist); 171 fade_xy = smoothstep( 172 vec2(ssr_settings.edge_fadeout_no_longer_active), 173 vec2(ssr_settings.edge_fadeout_fully_active), 177 fade *= fade_xy.x * fade_xy.y; 180 var specular_occlusion = pbr_input.specular_occlusion; 181 let world_position = pbr_input.world_position.xyz; 186 let tangent_to_world = orthonormalize(N); 188 let roughness = lighting::perceptualRoughnessToRoughness(perceptual_roughness); 189 let F0 = pbr_functions::calculate_F0(pbr_input.material.base_color.rgb, pbr_input.material.metallic, pbr_input.material.reflectance); 194 let stbn_dims = textureDimensions(stbn_texture); 195 var urand: vec2<f32>; 196 var raymarch_jitter: f32; 197 if (all(stbn_dims > vec2(1u))) { 198 let stbn_layers = textureNumLayers(stbn_texture); 199 let stbn_noise = textureLoad( 201 vec2<u32>(in.position.xy) % stbn_dims, 202 i32(globals.frame_count % u32(stbn_layers)), 205 urand = stbn_noise.xy; 207 raymarch_jitter = stbn_noise.z; 213 var state = (u32(in.position.x) * 2131358057u) ^ 214 (u32(in.position.y) * 3416869721u) ^ 215 (globals.frame_count * 1199786941u); 216 urand = utils::rand_vec2f(&state); 217 raymarch_jitter = utils::rand_f(&state); 221 let N_tangent = vec3(0.0, 0.0, 1.0); 222 let V_tangent = V * tangent_to_world; 224 let brdf_sample = sample_specular_brdf(V_tangent, roughness, F0, urand, N_tangent); 225 let R_stochastic = tangent_to_world * brdf_sample.wi; 226 let brdf_sample_value_over_pdf = brdf_sample.value_over_pdf; 229 let ssr_specular = evaluate_ssr(R_stochastic, world_position, raymarch_jitter); 230 var indirect_light = (ssr_specular.rgb * brdf_sample_value_over_pdf) * fade; 237@if(ENVIRONMENT_MAP) { 239 let base_color = pbr_input.material.base_color.rgb; 240 let metallic = pbr_input.material.metallic; 241 let reflectance = pbr_input.material.reflectance; 242 let specular_transmission = pbr_input.material.specular_transmission; 243 let diffuse_transmission = pbr_input.material.diffuse_transmission; 247 @if(STANDARD_MATERIAL_CLEARCOAT) 248 let clearcoat = pbr_input.material.clearcoat; 249 @if(STANDARD_MATERIAL_CLEARCOAT) 250 let clearcoat_perceptual_roughness = pbr_input.material.clearcoat_perceptual_roughness; 251 @if(STANDARD_MATERIAL_CLEARCOAT) 252 let clearcoat_roughness = lighting::perceptualRoughnessToRoughness(clearcoat_perceptual_roughness); 253 @if(STANDARD_MATERIAL_CLEARCOAT) 254 let clearcoat_N = pbr_input.clearcoat_N; 255 @if(STANDARD_MATERIAL_CLEARCOAT) 256 let clearcoat_NdotV = max(dot(clearcoat_N, pbr_input.V), 0.0001); 257 @if(STANDARD_MATERIAL_CLEARCOAT) 258 let clearcoat_R = reflect(-pbr_input.V, clearcoat_N); 261 let env_roughness = lighting::perceptualRoughnessToRoughness(perceptual_roughness); 262 let diffuse_color = pbr_functions::calculate_diffuse_color( 265 specular_transmission, 268 let NdotV = max(dot(N, V), 0.0001); 269 let F_ab = lighting::F_AB(perceptual_roughness, NdotV); 270 let F0_dielectric = pbr_functions::calculate_F0_dielectric(reflectance); 274 let R = reflect(-V, N); 277 var lighting_input: lighting::LightingInput; 278 lighting_input.layers[LAYER_BASE].NdotV = NdotV; 279 lighting_input.layers[LAYER_BASE].N = N; 280 lighting_input.layers[LAYER_BASE].R = R; 281 lighting_input.layers[LAYER_BASE].perceptual_roughness = perceptual_roughness; 282 lighting_input.layers[LAYER_BASE].roughness = env_roughness; 283 lighting_input.P = world_position.xyz; 284 lighting_input.V = V; 285 lighting_input.diffuse_color = diffuse_color; 286 lighting_input.metallic = metallic; 287 lighting_input.F0_dielectric = F0_dielectric; 288 lighting_input.F0_metallic = base_color; 289 lighting_input.F_ab = F_ab; 290 @if(STANDARD_MATERIAL_CLEARCOAT) { 291 lighting_input.layers[LAYER_CLEARCOAT].NdotV = clearcoat_NdotV; 292 lighting_input.layers[LAYER_CLEARCOAT].N = clearcoat_N; 293 lighting_input.layers[LAYER_CLEARCOAT].R = clearcoat_R; 294 lighting_input.layers[LAYER_CLEARCOAT].perceptual_roughness = clearcoat_perceptual_roughness; 295 lighting_input.layers[LAYER_CLEARCOAT].roughness = clearcoat_roughness; 296 lighting_input.clearcoat_strength = clearcoat; 301 let cluster_index = clustered_forward::view_fragment_cluster_index( 302 frag_coord.xy, frag_coord.z, false); 303 var clusterable_object_index_ranges = 304 clustered_forward::unpack_clusterable_object_index_ranges(cluster_index); 311 let environment_light = environment_map::environment_map_light( 312 &lighting_input, &clusterable_object_index_ranges, true); 317 indirect_light += (view.exposure * environment_light.specular * specular_occlusion) * (1.0 - (1.0 - ssr_specular.a) * fade); 321 return vec4(fragment.rgb + indirect_light, fragment.a);