I'm writing a software ray-tracer. I implemented a BVH structure (octree, actually) and traverse algorithm, but when I use it I get missing triangles. These are the facts that I have:
- Rendering without the BVH (naively iterating over all triangles) renders correctly
- Replacing AABB test with
return truerenders correctly - Making bounding volumes ~5 times larger than they need to be renders correctly
- Otherwise, rendering with BVH of any depth renders with missing triangles, more missing triangles the deeper the BVH
- Replacing below AABB test with an actual geometry test (testing against actual triangle bounding boxes) also render missing triangles
This is the AABB test that I'm using: (derived from here: https://tavianator.com/2011/ray_box.html)
private static bool RayBoxIntersects(in Ray ray, in BoundingVolume bvh) { // return true // if I uncomment this, renders correctly float tx1 = (bvh.MinimumCoordinates.X - ray.Origin.X) * ray.Inverse.X; float tx2 = (bvh.MaximumCoordinates.X - ray.Origin.X) * ray.Inverse.X; float tmin = MathF.Min(tx1, tx2); float tmax = MathF.Max(tx1, tx2); float ty1 = (bvh.MinimumCoordinates.Y - ray.Origin.Y) * ray.Inverse.Y; float ty2 = (bvh.MaximumCoordinates.Y - ray.Origin.Y) * ray.Inverse.Y; tmin = MathF.Max(tmin, MathF.Min(ty1, ty2)); tmax = MathF.Min(tmax, MathF.Max(ty1, ty2)); float tz1 = (bvh.MinimumCoordinates.Z - ray.Origin.Z) * ray.Inverse.Z; float tz2 = (bvh.MaximumCoordinates.Z - ray.Origin.Z) * ray.Inverse.Z; tmin = MathF.Max(tmin, MathF.Min(tz1, tz2)); tmax = MathF.Min(tmax, MathF.Max(tz1, tz2)); return (tmax >= MathF.Max(0f, tmin) && tmin < float.PositiveInfinity) || tmin == float.NaN || tmax == float.NaN; } Ray.Inverse is defined as new Vector3(1f / direction.X, 1f / direction.Y, 1f / direction.Z)
What could I be doing wrong?