Fallback to (specular) transmitted environment light when there's no transmitted background
This commit is contained in:
parent
294a677b20
commit
5bfe6bb342
@ -330,27 +330,34 @@ fn pbr(
|
||||
let environment_light = environment_map_light(perceptual_roughness, roughness, diffuse_color, NdotV, f_ab, in.N, R, F0);
|
||||
indirect_light += (environment_light.diffuse * occlusion) + environment_light.specular;
|
||||
|
||||
if diffuse_transmission > 0.0 {
|
||||
// NOTE: We use the diffuse transmissive color, the second Lambertian lobe's calculated
|
||||
// world position, inverted normal and view vectors, and the following simplified
|
||||
// values for a fully diffuse transmitted light contribution approximation:
|
||||
// we'll use the specular component of the transmitted environment
|
||||
// light in the call to `transmissive_light()` below
|
||||
var transmitted_environment_light_specular = vec3<f32>(0.0);
|
||||
|
||||
if diffuse_transmission > 0.0 || transmission > 0.0 {
|
||||
// NOTE: We use the diffuse transmissive color, inverted normal and view vectors,
|
||||
// and the following simplified values for the transmitted environment light contribution
|
||||
// approximation:
|
||||
//
|
||||
// perceptual_roughness = 1.0;
|
||||
// roughness = 1.0;
|
||||
// NdotV = 1.0;
|
||||
// f_ab = vec2<f32>(0.1)
|
||||
// R = vec3<f32>(0.0) // doesn't really matter
|
||||
// F0 = vec3<f32>(0.0)
|
||||
// R = -refract(in.V, -in.N, 1.0 / ior)
|
||||
// F0 = vec3<f32>(0.16)
|
||||
// occlusion = 1.0
|
||||
let environment_light = environment_map_light(1.0, 1.0, diffuse_transmissive_color, 1.0, vec2<f32>(0.1), -in.N, vec3<f32>(0.0), vec3<f32>(0.0));
|
||||
transmitted_light += environment_light.diffuse;
|
||||
let transmitted_environment_light = environment_map_light(perceptual_roughness, roughness, diffuse_transmissive_color, 1.0, vec2<f32>(0.1), -in.N, -refract(in.V, -in.N, 1.0 / ior), vec3<f32>(0.16));
|
||||
transmitted_light += transmitted_environment_light.diffuse;
|
||||
transmitted_environment_light_specular = transmitted_environment_light.specular;
|
||||
}
|
||||
#else
|
||||
// If there's no environment map light, there's no transmitted environment
|
||||
// light specular component, so we can just hardcode it to zero.
|
||||
let transmitted_environment_light_specular = vec3<f32>(0.0);
|
||||
#endif
|
||||
|
||||
let emissive_light = emissive.rgb * output_color.a;
|
||||
|
||||
if transmission > 0.0 {
|
||||
transmitted_light += transmissive_light(in.world_position, in.frag_coord.xyz, in.N, in.V, ior, thickness, perceptual_roughness, transmissive_color).rgb;
|
||||
transmitted_light += transmissive_light(in.world_position, in.frag_coord.xyz, in.N, in.V, ior, thickness, perceptual_roughness, transmissive_color, transmitted_environment_light_specular).rgb;
|
||||
}
|
||||
|
||||
// Total light
|
||||
|
||||
@ -281,7 +281,7 @@ fn directional_light(light_id: u32, roughness: f32, NdotV: f32, normal: vec3<f32
|
||||
return (specular_light + diffuse) * (*light).color.rgb * NoL;
|
||||
}
|
||||
|
||||
fn transmissive_light(world_position: vec4<f32>, frag_coord: vec3<f32>, N: vec3<f32>, V: vec3<f32>, ior: f32, thickness: f32, perceptual_roughness: f32, transmissive_color: vec3<f32>) -> vec3<f32> {
|
||||
fn transmissive_light(world_position: vec4<f32>, frag_coord: vec3<f32>, N: vec3<f32>, V: vec3<f32>, ior: f32, thickness: f32, perceptual_roughness: f32, transmissive_color: vec3<f32>, transmitted_environment_light_specular: vec3<f32>) -> vec3<f32> {
|
||||
// Calculate distance, used to scale roughness transmission blur
|
||||
let distance = length(view.world_position - world_position.xyz);
|
||||
|
||||
@ -308,12 +308,12 @@ fn transmissive_light(world_position: vec4<f32>, frag_coord: vec3<f32>, N: vec3<
|
||||
// Fetch background color
|
||||
let background_color = fetch_transmissive_background(offset_position, frag_coord, perceptual_roughness, distance);
|
||||
|
||||
// Calculate final color by applying transmissive color to background
|
||||
// Calculate final color by applying transmissive color to a mix of background color and transmitted specular environment light
|
||||
// TODO: Add support for attenuationColor and attenuationDistance
|
||||
return transmissive_color * background_color;
|
||||
return transmissive_color * mix(transmitted_environment_light_specular, background_color.rgb, background_color.a);
|
||||
}
|
||||
|
||||
fn fetch_transmissive_background(offset_position: vec2<f32>, frag_coord: vec3<f32>, perceptual_roughness: f32, distance: f32) -> vec3<f32> {
|
||||
fn fetch_transmissive_background(offset_position: vec2<f32>, frag_coord: vec3<f32>, perceptual_roughness: f32, distance: f32) -> vec4<f32> {
|
||||
// Calculate view aspect ratio, used to scale offset so that it's proportionate
|
||||
let aspect = view.viewport.z / view.viewport.w;
|
||||
|
||||
@ -331,7 +331,7 @@ fn fetch_transmissive_background(offset_position: vec2<f32>, frag_coord: vec3<f3
|
||||
// Number of taps scale with blur intensity
|
||||
// Minimum: 1, Maximum: 9
|
||||
let num_taps = i32(max(blur_intensity * 300.0, 8.0)) + 1;
|
||||
var result = vec3<f32>(0.0, 0.0, 0.0);
|
||||
var result = vec4<f32>(0.0);
|
||||
for (var i: i32 = 0; i < num_taps; i = i + 1) {
|
||||
// Magic numbers have been empirically chosen to produce blurry results that look “smooth”
|
||||
let dither = screen_space_dither(frag_coord.xy + vec2<f32>(f32(i) * 4773.0, f32(i) * 1472.0));
|
||||
@ -343,7 +343,7 @@ fn fetch_transmissive_background(offset_position: vec2<f32>, frag_coord: vec3<f3
|
||||
view_transmission_texture,
|
||||
view_transmission_sampler,
|
||||
offset_position + dither_offset,
|
||||
).rgb;
|
||||
);
|
||||
}
|
||||
|
||||
result /= f32(num_taps);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user