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 true
renders 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?