Improve layering in the solari BRDF#24243
Conversation
| let specular_weight = 1.0 - diffuse_weight; | ||
| let rho = lobe_reflectances(F0, ray_hit.material, NdotV); | ||
| let specular_weight = luminance(rho.rho_spec) / luminance(rho.rho_spec + rho.rho_diff); | ||
| let diffuse_weight = 1 - specular_weight; |
There was a problem hiding this comment.
| let diffuse_weight = 1 - specular_weight; | |
| let diffuse_weight = 1.0 - specular_weight; |
| @@ -98,10 +98,9 @@ fn pathtrace(@builtin(global_invocation_id) global_id: vec3<u32>) { | |||
| fn brdf_pdf(wo: vec3<f32>, wi: vec3<f32>, ray_hit: ResolvedRayHitFull) -> f32 { | |||
There was a problem hiding this comment.
Please move brdf_pdf into brdf.wgsl
| let LdotH = dot(wi, H); | ||
| let NdotV = dot(world_normal, wo); | ||
| if NdotL < 0.0001 || NdotH < 0.0001 || LdotH < 0.0001 || NdotV < 0.0001 { return vec3(0.0); } | ||
|
|
There was a problem hiding this comment.
Add back the newline please!
| let specular_weight = 1.0 - diffuse_weight; | ||
| let rho = lobe_reflectances(F0, material, NdotV); | ||
| let specular_weight = luminance(rho.rho_spec) / luminance(rho.rho_spec + rho.rho_diff); | ||
| let diffuse_weight = 1 - specular_weight; |
There was a problem hiding this comment.
| let diffuse_weight = 1 - specular_weight; | |
| let diffuse_weight = 1.0 - specular_weight; |
| // Hemispherical reflectance of each lobe | ||
| fn lobe_reflectances(F0: vec3<f32>, material: ResolvedMaterial, NdotV: f32) -> LobeReflectances { | ||
| let F_ab = F_AB(material.perceptual_roughness, NdotV); | ||
| let ms_factor = 1.0 / (F_ab.x + F_ab.y) - 1.0; |
There was a problem hiding this comment.
| let ms_factor = 1.0 / (F_ab.x + F_ab.y) - 1.0; | |
| let multi_scattering_factor = 1.0 / (F_ab.x + F_ab.y) - 1.0; |
| struct LobeReflectances { | ||
| rho_spec: vec3<f32>, | ||
| rho_diff: vec3<f32>, | ||
| } |
There was a problem hiding this comment.
| struct LobeReflectances { | |
| rho_spec: vec3<f32>, | |
| rho_diff: vec3<f32>, | |
| } | |
| struct LobeReflectances { | |
| specular: vec3<f32>, | |
| diffuse: vec3<f32>, | |
| } |
|
|
||
| return diffuse_color * layering * NdotL; | ||
| let rho = lobe_reflectances(F0, material, NdotV); | ||
| return rho.rho_diff / PI * NdotL; |
There was a problem hiding this comment.
Why is PI here, and not part of rho_diffuse?
| return rho.rho_diff / PI * NdotL; | ||
| } | ||
|
|
||
| fn evaluate_specular_brdf(wo: vec3<f32>, wi: vec3<f32>, world_normal: vec3<f32>, material: ResolvedMaterial) -> vec3<f32> { |
There was a problem hiding this comment.
Does anything in evaluate_specular_brdf need to change, similar to how evaluate_diffuse_brdf relies on rho_diffuse?
|
|
||
| // Mirror specular is a delta function | ||
| if material.roughness <= MIRROR_ROUGHNESS_THRESHOLD { | ||
| return EvaluateAndSampleBrdfResult(wi, rho.rho_spec / specular_weight, 1.0); |
There was a problem hiding this comment.
Didn't we return INF for the PDF before for mirrors? I'm trying to remember how to handle mirrors, it's hurting my brain...
| let diffuse_weight = mix(df, 0.0, ray_hit.material.metallic); | ||
| let specular_weight = 1.0 - diffuse_weight; | ||
| let rho = lobe_reflectances(F0, ray_hit.material, NdotV); | ||
| let specular_weight = luminance(rho.rho_spec) / luminance(rho.rho_spec + rho.rho_diff); |
There was a problem hiding this comment.
What if the denominator is 0, because you have a pure black material?
|
Btw would love to know the code you used for the white furnace test for solari - I lost mine. |
Objective
Improve the solari BRDF. Split off from #23818.
Solution
The layering approach used in the current brdf to distribute energy between the specular and diffuse lobes doesn't work, for reasons I honestly don't quite understand.
The suggested changes are roughly inspired by OpenPBR's equation 42. We're not using EON though, so this uses Filament's multiscattering correction instead of equation 39.
This formulation has the downside of breaking reciprocity. As far as I can tell the path tracer is unidirectional, so this shouldn't cause issues.
Showcase
White furnace
Main:

This PR:

PICA PICA pathtraced
Main:

This PR:
