• Keine Ergebnisse gefunden

Figure 2.14: Example scene with 16 primitives for two iterations (left and right image) of BVH construction with the object median split strategy. This strategy focuses solely on splitting a set of primitives into two halves w.r.t. the primitive AABB centroid coordinates in the dimension with the largest extent. The green line depicts a symbolic splitting plane which is positioned such that the set is partitioned into two halves. As resulting BVHs are balanced by construction they have minimal height.

are introduced in the next section, an alternative faster implementation is possible. It first sorts the primitives in each dimension in separate arrays before construction. During construction these arrays are kept sorted in each recursion step, which can be done in linear time. This improves the complexity toO(nlogn)at the cost of higher memory con-sumption. While the construction is still simple and reasonably fast the tree again does not adapt to the geometry. For uniform geometry distributions this strategy has no real benefit over the spatial median split as the resulting hierarchies are essentially the same.

For non-uniformly distributed geometry though this approach can expose higher trace performance as their balancedness causes them to be of minimum height. This does not make balancedness a magic bullet. The only reason this is an advantage is that spatial me-dian splits expose an unthoughtful unbalancedness which unnecessarily increases height.

As we will see in Section2.5state-of-the-art construction with the surface area heuristic deliberately introduces unbalancedness in the tree where it is considered beneficial.

2.3 kd-Trees

In contrast to BVHs, which partition sets of objects, a kd-tree is a binary tree, which parti-tions space using split planes. kd-trees restrict split planes to be parallel to the coordinate axes planes. The more generalbinary space partitioningtree (BSP) allows arbitrarily ori-ented split planes. Each inner kd-tree node stores a split plane, which partitions space into two half-spaces. Primitives which straddle the split plane are split themselves. Instead of actually splitting primitives only references to primitives are kept which are duplicated on a split. InR3 a kd-tree split plane can be defined by a distanced∈Rand the coordinate axisa∈ {x,y,z}the plane intersects and is perpendicular to. In the context of ray tracing a kd-tree also stores a tight AABB for the complete scene geometry. As the split planes are axes parallel this gives every node in the tree an implicit AABB, which can be computed by intersecting the scene AABB with all half-spaces of the ancestors of the node. In case of a BSP tree its arbitrarily oriented split planes result in general convex polyhedra as the implicit bounding volumes of nodes. The union of all node bounds in the same tree level is the scene bounds. The pairwise intersection of node bounds on the same level is disjoint.

As a result there is no overlap in a kd-tree.

1a 1b

3

2a2b 4b4a 5a

5b5c 6a 6b

7

|

| {1a, 2a} {1b, 4a}

| {2b, 3} {4b}

{5a, 6a} |

{5b}

{5c, 6b} {7}

Figure 2.15: Example kd-tree for a scene with seven input triangles. A spatial median construction strategy is applied, where the maximum allowed number of primitives in a leaf is set to two. The constructed kd-tree references about two times as many primitives as there are in the input.

The basic construction strategies discussed in Section2.2.5can also be applied to kd-trees. Implementation of the object median strategy is a bit more involved because of the primitive splitting. After primitives have been sorted the list cannot be simply split in half. Instead, a split plane has to be swept through the primitives to find the plane which, including primitive duplicates, partitions the set into ideally two halves. Observing that the number of primitives on both sides of a split plane changes at primitive starts and ends this can be implemented inO(n)by counting so called primitiveenter-andexit-eventsas described inWald and Havran[2006]. An example kd-tree constructed with the spatial median split is depicted in Figure2.15. Due to primitive splitting there is no upper bound on the number of kd-tree nodes depending on the number of input primitives. In practice, this requires to specify a maximum depth to ensure construction algorithm termination.

2.3.1 Traversal

kd-tree traversal is similar to BVH traversal. A major difference is that bounding volumes are defined implicitly by the series of half spaces down the tree. Only the scene bounding box is explicitly defined. Another major difference to BVHs is that traversal can imme-diately terminate as soon as an intersection has been found. The reason is that there is no overlap with other non-ancestral nodes as described earlier. Thus, the intersection is guaranteed to be the closest. This property of kd-trees is calledearly ray termination.

We outline the traversal process according to the description fromPharr et al.[2016].

Pseudocode for kd-tree traversal is provided in Algorithm2. First, the ray is intersected with the tight axis aligned scene bounding box to obtain initial ray parameter bounds [tmin,tmax]. If the ray misses the bounds there can be no intersection and traversal termi-nates. The currently processed nodencurrent is initialized with the kd-tree root. Ifncurrent is an inner node we have to identify which children are intersected by the ray. For this we have to intersect the split plane with the ray. The ray parameter for the intersection with the plane is

tplane= doa

da (2.28)

2.3. kd-Trees

Algorithm 2:Pseudocode for kd-tree traversal.

input :ray // ray we have to intersect with the scene

input :root // root node of the scene BVH

input :sceneBounds // tight AABB of the scene

output:iIdx // index of the closest intersected primitive

1 iIdxInvalidIdx // Set intersection index to invalid index

2 (tmin,tmax)←intersect_bounds(ray,sceneBounds) // Init ray parameter interval

3 iftmintmaxthen // Return if we miss the scene bounds

4 return

5 end

6 push(stack, (NIL,[∞,−∞]) // Init stack with invalid node and parameter interval

7 ncurrentroot // Start traversal at root

8 whilencurrent6=NIL do // Traversal loop

9 ifis_inner_node( ncurrent)then // Handle inner nodes

10 plane←get_split_plane(ncurrent) // Get split plane

11 // Compute ray/plane intersection parameter

12 tplane←intersect_plane(ray,plane)

13 // Order children to get a near and far child

14 (cnear,cfar)←identify_near_and_far_child(ray,ncurrent)

15 // Check which children have been intersected

16 iftmaxtplanetplane≤0then// only intersected near child

17 ncurrentcnear

18 else iftmintplanethen// only intersected far child

19 ncurrentcfar

20 else// intersected both children

21 ncurrentcnear

22 // Push far child with corresponding bounds interval on the stack

23 push(stack,(cfar,[tplane,tmax]))

24 // Shorten ray

25 tmaxtplane

26 end

27 else

28 // Find closest leaf primitive intersection

29 iIdx←intersect_leaf_primitives(ncurrent,ray,tmin,tmax)

30 ifiIdx6=InvalidIdx then// terminate on primitive intersection

31 return

32 end

33 // Get next node and corresponding parameter interval

34 (ncurrent,[tmin,tmax])←pop(stack)

35 end

36 end

near far {cnear}

tplane>tmax tmin

tmax

{cnear}

tplane<0 tmax

{cnear,cfar}

tplane∈[tmin,tmax] tmin

tmax

{cfar} tplane<tmin tmin

tmax

Figure 2.16: Depiction of the four situations when determining the next node during kd-tree traversal. Every ray shows the set of relevant child nodescnearand/orcfardepending on the plane intersection parametertplaneand its relation to the parent bounds intersection parameterstminandtmax. (Based onPharr et al.[2010], Figure 4.18)

withd ∈R being the plane distance and a ∈ {x,y,z}being the orthogonal plane axis.

This gives us the ray parameter intervals[tmin,tplane]and[tplane,tmax]of the intersection with the implicit children AABBs. The child which corresponds to the side of the split plane containing the ray origin is called the near childcnearand the other one is the far childcfar. Analyzing the sign of the ray direction componentda in dimensionaandtplane the intervals can be attributed to cnear and cfar. In case a child parameter interval has invalid limits, that is the upper bound is lower than the lower bound, the child is not intersected. As the union of the disjoint implicit children bounds is exactly the implicit bounds of the parent node the ray is guaranteed to intersect at least one child since the ray intersected the parent. Iftplaneis larger thantmaxthe ray only intersectscnear. In case tplaneis smaller than zero the ray points away from the split plane and again only intersects cnear. Iftplane is smaller than tminthe ray only intersectscfar. The only remaining case is wheretplane∈[tmin,tmax]holds and both children are intersected. Figure2.16shows the four different situations. In the case where both children are intersected the far child is put on the stack along with its parameter interval[tplane,tmax]. Before traversal continues with the near child the current parameter interval is shortened to its interval[tmin,tplane].

If ncurrent is a leaf the closest primitive intersection is determined and traversal can terminate immediately on intersection as explained at the beginning of this section. If a leaf contains duplicate primitive references it can happen that the closest intersection is outside of the implicit leaf bounds. The intersection has to be rejected in this case. In case there was no intersection the next node along with its parameter interval is popped from the stack.