Skip to content

Commit 26bdc3b

Browse files
authored
Use a local TBN in the solari BRDF (#23948)
# Objective BRDF fixes for solari. Split off from #23818. ## Solution Use a local TBN instead of mikktspace, which was producing seams on the spheres used for the white furnace test. ## Testing On main: <img width="1920" height="1013" alt="1_main_F_AB" src="https://github.com/user-attachments/assets/c05acf43-faa1-4128-9cdc-807ed2364518" /> This PR: <img width="1920" height="1013" alt="2_proper_tbn" src="https://github.com/user-attachments/assets/7230e9d9-02ec-4435-8d74-1b7b7a314e27" />
1 parent 8d52bcc commit 26bdc3b

3 files changed

Lines changed: 9 additions & 10 deletions

File tree

crates/bevy_solari/src/pathtracer/pathtracer.wgsl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
enable wgpu_ray_query;
22

33
#import bevy_core_pipeline::tonemapping::tonemapping_luminance as luminance
4-
#import bevy_pbr::pbr_functions::{calculate_tbn_mikktspace, calculate_F0}
4+
#import bevy_pbr::pbr_functions::calculate_F0
55
#import bevy_pbr::utils::{rand_f, rand_vec2f}
6-
#import bevy_render::maths::PI
6+
#import bevy_render::maths::{PI, orthonormalize}
77
#import bevy_render::view::View
88
#import bevy_solari::brdf::{evaluate_brdf, evaluate_and_sample_brdf, fresnel}
99
#import bevy_solari::sampling::{sample_random_light, random_emissive_light_pdf, ggx_vndf_pdf, power_heuristic}
@@ -71,7 +71,7 @@ fn pathtrace(@builtin(global_invocation_id) global_id: vec3<u32>) {
7171
}
7272

7373
// Sample new ray direction from the material BRDF for next bounce and apply BRDF
74-
let next_bounce = evaluate_and_sample_brdf(wo, ray_hit.world_normal, ray_hit.world_tangent, ray_hit.material, &rng);
74+
let next_bounce = evaluate_and_sample_brdf(wo, ray_hit.world_normal, ray_hit.material, &rng);
7575
if next_bounce.pdf == 0.0 { break; }
7676
ray_direction = next_bounce.wi;
7777
ray_origin = ray_hit.world_position + (ray_hit.geometric_world_normal * RAY_T_MIN);
@@ -103,7 +103,7 @@ fn brdf_pdf(wo: vec3<f32>, wi: vec3<f32>, ray_hit: ResolvedRayHitFull) -> f32 {
103103
let diffuse_weight = mix(df, 0.0, ray_hit.material.metallic);
104104
let specular_weight = 1.0 - diffuse_weight;
105105

106-
let TBN = calculate_tbn_mikktspace(ray_hit.world_normal, ray_hit.world_tangent);
106+
let TBN = orthonormalize(ray_hit.world_normal);
107107
let T = TBN[0];
108108
let B = TBN[1];
109109
let N = TBN[2];

crates/bevy_solari/src/realtime/specular_gi.wgsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ enable wgpu_ray_query;
33
#define_import_path bevy_solari::specular_gi
44

55
#import bevy_core_pipeline::tonemapping::tonemapping_luminance as luminance
6-
#import bevy_pbr::pbr_functions::{calculate_tbn_mikktspace, calculate_diffuse_color, calculate_F0}
6+
#import bevy_pbr::pbr_functions::{calculate_diffuse_color, calculate_F0}
77
#import bevy_pbr::utils::rand_f
88
#import bevy_render::maths::{orthonormalize, PI}
99
#import bevy_render::view::View
@@ -100,7 +100,7 @@ fn trace_glossy_path(pixel_id: vec2<u32>, primary_surface: ResolvedGPixel, initi
100100
if ray.kind == RAY_QUERY_INTERSECTION_NONE { break; }
101101
let ray_hit = resolve_ray_hit_full(ray);
102102

103-
let TBN = calculate_tbn_mikktspace(ray_hit.world_normal, ray_hit.world_tangent);
103+
let TBN = orthonormalize(ray_hit.world_normal);
104104
let T = TBN[0];
105105
let B = TBN[1];
106106
let N = TBN[2];

crates/bevy_solari/src/scene/brdf.wgsl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ enable wgpu_ray_query;
44

55
#import bevy_core_pipeline::tonemapping::tonemapping_luminance as luminance
66
#import bevy_pbr::lighting::{D_GGX, V_SmithGGXCorrelated, specular_multiscatter}
7-
#import bevy_pbr::pbr_functions::{calculate_tbn_mikktspace, calculate_diffuse_color, calculate_F0}
7+
#import bevy_pbr::pbr_functions::{calculate_diffuse_color, calculate_F0}
88
#import bevy_pbr::utils::{rand_f, sample_cosine_hemisphere}
9-
#import bevy_render::maths::PI
9+
#import bevy_render::maths::{PI, orthonormalize}
1010
#import bevy_solari::sampling::{sample_ggx_vndf, ggx_vndf_pdf, ggx_vndf_sample_invalid}
1111
#import bevy_solari::scene_bindings::{ResolvedMaterial, MIRROR_ROUGHNESS_THRESHOLD, brdf_dfg_lut, brdf_dfg_lut_sampler}
1212

@@ -19,7 +19,6 @@ struct EvaluateAndSampleBrdfResult {
1919
fn evaluate_and_sample_brdf(
2020
wo: vec3<f32>,
2121
world_normal: vec3<f32>,
22-
world_tangent: vec4<f32>,
2322
material: ResolvedMaterial,
2423
rng: ptr<function, u32>,
2524
) -> EvaluateAndSampleBrdfResult {
@@ -31,7 +30,7 @@ fn evaluate_and_sample_brdf(
3130
let diffuse_weight = mix(df, 0.0, material.metallic);
3231
let specular_weight = 1.0 - diffuse_weight;
3332

34-
let TBN = calculate_tbn_mikktspace(world_normal, world_tangent);
33+
let TBN = orthonormalize(world_normal);
3534
let T = TBN[0];
3635
let B = TBN[1];
3736
let N = TBN[2];

0 commit comments

Comments
 (0)