Skip to content

Commit 9183d42

Browse files
committed
Avoid ray self-intersection with robust offsetRay function
1 parent 61a7adf commit 9183d42

File tree

2 files changed

+27
-8
lines changed

2 files changed

+27
-8
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ An experimental pathtracer, implemented using WebGPU via the [Dawn](https://dawn
1212
- [Ray Tracing: The Rest of Your Life](https://raytracing.github.io/books/RayTracingTheRestOfYourLife.html)
1313
- Cosine-weighted hemisphere sampling method
1414
- [scratchapixel/moller-trumbore-ray-triangle-intersection](https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/moller-trumbore-ray-triangle-intersection.html)
15-
- _The Reference Path Tracer, Ray Tracing Gems II_ and associated code sample [boksajak/referencePT](https://github.com/boksajak/referencePT/)
15+
- _The Reference Path Tracer_, _Ray Tracing Gems II_ and associated code sample [boksajak/referencePT](https://github.com/boksajak/referencePT/)
1616
- Rng initialization
1717
- [Crash Course in BRDF implementation](https://boksajak.github.io/files/CrashCourseBRDF.pdf)
1818
- BRDF interface
1919
- Lambertian BRDF, `sampleLambertian`, `evalLambertian`
2020
- [Building an Orthonormal Basis, Revisited](https://www.jcgt.org/published/0006/01/01/paper-lowres.pdf)
2121
- Robust orthonormal axis, implemented in the `pixarOnb` function
22+
- _A Fast and Robust Method for Avoiding Self-Intersection_, _Ray Tracing Gems_
23+
- Method for the `offsetRay` function, for preventing ray self-intersections.
2224
- [ACES Filmic Tone Mapping Curve](https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/)
2325
- filmic tonemapping function
2426

src/pt/raytracer.wgsl

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -317,22 +317,18 @@ fn rayIntersectBvh(ray: Ray, rayTMax: f32, hit: ptr<function, Intersection>) ->
317317
var trihit: TriangleHit;
318318
if rayIntersectTriangle(ray, triangle, tmax, &trihit) {
319319
tmax = trihit.t;
320+
didIntersect = true;
320321

321322
let b = trihit.b;
322-
323-
let p = trihit.p;
324-
325323
let triangleIdx = node.trianglesOffset + idx;
326324
let vert = vertexAttributes[triangleIdx];
327325

326+
let p = trihit.p;
328327
let n = b[0] * vert.n0 + b[1] * vert.n1 + b[2] * vert.n2;
329-
330328
let uv = b[0] * vert.uv0 + b[1] * vert.uv1 + b[2] * vert.uv2;
331-
332329
let textureDescriptorIdx = vertexAttributes[triangleIdx].textureDescriptorIdx;
333330

334331
*hit = Intersection(p, n, uv, textureDescriptorIdx);
335-
didIntersect = true;
336332
}
337333
}
338334
if toVisitOffset == 0u {
@@ -445,14 +441,35 @@ fn rayIntersectTriangle(ray: Ray, tri: Positions, tmax: f32, hit: ptr<function,
445441
// e2 = v2 - v0
446442
// -> p = v0 + u * e1 + v * e2
447443
let p = tri.p0 + u * e1 + v * e2;
444+
let n = normalize(cross(e1, e2));
448445
let b = vec3f(1f - u - v, u, v);
449-
*hit = TriangleHit(p, b, t);
446+
*hit = TriangleHit(offsetRay(p, n), b, t);
450447
return true;
451448
} else {
452449
return false;
453450
}
454451
}
455452

453+
const ORIGIN = 1f / 32f;
454+
const FLOAT_SCALE = 1f / 65536f;
455+
const INT_SCALE = 256f;
456+
457+
fn offsetRay(p: vec3f, n: vec3f) -> vec3f {
458+
// Source: A Fast and Robust Method for Avoiding Self-Intersection, Ray Tracing Gems
459+
let offset = vec3i(i32(INT_SCALE * n.x), i32(INT_SCALE * n.y), i32(INT_SCALE * n.z));
460+
// Offset added straight into the mantissa bits to ensure the offset is scale-invariant,
461+
// except for when close to the origin, where we use FLOAT_SCALE as a small epsilon.
462+
let po = vec3f(
463+
bitcast<f32>(bitcast<i32>(p.x) + select(offset.x, -offset.x, (p.x < 0))),
464+
bitcast<f32>(bitcast<i32>(p.y) + select(offset.y, -offset.y, (p.y < 0))),
465+
bitcast<f32>(bitcast<i32>(p.z) + select(offset.z, -offset.z, (p.z < 0)))
466+
);
467+
468+
return vec3f(select(po.x, p.x + FLOAT_SCALE * n.x, (abs(p.x) < ORIGIN)),
469+
select(po.y, p.y + FLOAT_SCALE * n.y, (abs(p.y) < ORIGIN)),
470+
select(po.z, p.z + FLOAT_SCALE * n.z, (abs(p.z) < ORIGIN)));
471+
}
472+
456473
struct TextureDescriptor {
457474
width: u32,
458475
height: u32,

0 commit comments

Comments
 (0)