diff --git a/src/traversal/intersection.impala b/src/traversal/intersection.impala index 0dd1769..2a938f7 100644 --- a/src/traversal/intersection.impala +++ b/src/traversal/intersection.impala @@ -142,7 +142,7 @@ fn @bbox_half_area(a: BBox) -> f32 { ext.x * (ext.y + ext.z) + ext.y * ext.z } -fn @intersect_ray_tri(math: Intrinsics, backface_culling: bool, ray: Ray, tri: Tri) -> Option[(f32, f32, f32)] { +fn @intersect_ray_tri_cpu(math: Intrinsics, backface_culling: bool, ray: Ray, tri: Tri) -> Option[(f32, f32, f32)] { let c = vec3_sub(tri.v0, ray.org); let r = vec3_cross(ray.dir, c); let det = vec3_dot(tri.n, ray.dir); @@ -172,6 +172,34 @@ fn @intersect_ray_tri(math: Intrinsics, backface_culling: bool, ray: Ray, tri: T } } +fn @intersect_ray_tri_gpu(math: Intrinsics, backface_culling: bool, ray: Ray, tri: Tri) -> Option[(f32, f32, f32)] { + let c = vec3_sub(tri.v0, ray.org); + let r = vec3_cross(ray.dir, c); + let det = vec3_dot(tri.n, ray.dir); + let abs_det = math.fabsf(det); + + let u = prodsign(vec3_dot(r, tri.e2), det); + let mut mask = u >= 0; + + let v = prodsign(vec3_dot(r, tri.e1), det); + mask &= v >= 0; + mask &= u + v <= abs_det; + + if likely(!mask) { return(Option[(f32, f32, f32)]::None) } + + let t = prodsign(vec3_dot(c, tri.n), det); + mask &= if backface_culling { det < 0 } else { abs_det != 0 }; + mask &= t >= abs_det * ray.tmin; + mask &= t <= abs_det * ray.tmax; + + if mask { + let inv_det = 1 / abs_det; + make_option(t * inv_det, u * inv_det, v * inv_det) + } else { + Option[(f32, f32, f32)]::None + } +} + fn @intersect_ray_box(min_max: MinMax, ordered: bool, ray: Ray, bbox: BBox) -> (f32, f32) { let t0 = vec3_add(vec3_mul(ray.inv_dir, bbox.min), ray.inv_org); let t1 = vec3_add(vec3_mul(ray.inv_dir, bbox.max), ray.inv_org); diff --git a/src/traversal/mapping_cpu.impala b/src/traversal/mapping_cpu.impala index c11da16..c1e55a8 100644 --- a/src/traversal/mapping_cpu.impala +++ b/src/traversal/mapping_cpu.impala @@ -30,7 +30,7 @@ fn @make_cpu_tri4(tris: &[Tri4]) -> fn (i32) -> Prim { let e2 = make_vec3(tri_ptr.e2(0)(i), tri_ptr.e2(1)(i), tri_ptr.e2(2)(i)); let n = make_vec3(tri_ptr.n (0)(i), tri_ptr.n (1)(i), tri_ptr.n (2)(i)); let tri = make_tri(v0, e1, e2, n); - match intersect_ray_tri(math, false /*backface_culling*/, ray, tri) { + match intersect_ray_tri_cpu(math, false /*backface_culling*/, ray, tri) { Option[(f32, f32, f32)]::Some(t, u, v) => { let prim_id = tri_ptr.prim_id(i) & 0x7FFFFFFF; let geom_id = tri_ptr.geom_id(i); diff --git a/src/traversal/mapping_gpu.impala b/src/traversal/mapping_gpu.impala index bd4acb8..d913250 100644 --- a/src/traversal/mapping_gpu.impala +++ b/src/traversal/mapping_gpu.impala @@ -56,7 +56,7 @@ fn @make_gpu_bvh2_tri1(nodes: &[Node2], tris: &[Tri1], is_nvvm: bool) -> Bvh { let e2 = make_vec3(tri2(0), tri2(1), tri2(2)); let n = vec3_cross(e1, e2); let tri = make_tri(v0, e1, e2, n); - match intersect_ray_tri(math, false /*backface_culling*/, ray, tri) { + match intersect_ray_tri_gpu(math, false /*backface_culling*/, ray, tri) { Option[(f32, f32, f32)]::Some((t, u, v)) => { make_option(make_hit(geom_id, prim_id & 0x7FFFFFFF, t, make_vec2(u, v))) },