570 likes | 660 Views
Multi-Hit Ray Traversal. Christiaan Gribble Alexis Naveros Ethan Kerzner ACM SIGGRAPH Symposium on Interactive 3D Graphics & Games 15 March 2014. Why present at i3D?. Raise awareness of JCGT paper Overview Algorithm Performance Examples Wrap-up Generate interest.
E N D
Multi-Hit Ray Traversal Christiaan GribbleAlexis NaverosEthan Kerzner • ACM SIGGRAPH Symposium on Interactive 3D Graphics & Games15 March 2014
Why present at i3D? • Raise awareness of JCGT paper • Overview • Algorithm • Performance • Examples • Wrap-up • Generate interest Gribble et al., Multi-Hit Ray Traversal 2
Why present at i3D? • Raise awareness of JCGT paper • Generate interest • Applying algorithm • Improving algorithm • Exploring non-optical rendering Looking to collaborate on interesting problems in rendering Gribble et al., Multi-Hit Ray Traversal 3
Interval computation Non-optical rendering Optical rendering Gribble et al., Multi-Hit Ray Traversal 5
Interval computation Interval computation Non-optical rendering Gribble et al., Multi-Hit Ray Traversal 6
Interval computation • Difficult or impossible • Epsilon hacks • Missed/repeated intersections • Performance impacts Gribble et al., Multi-Hit Ray Traversal 7
Interval computation • Difficult or impossible • Performance impacts • Traversal restart • Operational overhead Are overlapping coplanar facets actually a problem? Gribble et al., Multi-Hit Ray Traversal 8
Interval computation Overlapping coplanar facets Gribble et al., Multi-Hit Ray Traversal 9
Multi-hit ray traversal • Which primitives are intersected? • One or more, & possibly all • Ordered by t-value along ray • Core operation in ray engine • Critical to interval generation • Applications Gribble et al., Multi-Hit Ray Traversal 11
Multi-hit ray traversal • Which primitives are intersected? • Core operation in ray engine • Avoids negative epsilon hacks • Alleviates traversal restart • Critical to interval generation • Applications Gribble et al., Multi-Hit Ray Traversal 12
Multi-hit ray traversal • Which primitives are intersected? • Core operation in ray engine • Critical to interval generation • Handles bad geometry gracefully • Enables early exit • Applications Gribble et al., Multi-Hit Ray Traversal 13
Multi-hit ray traversal • Which primitives are intersected? • Core operation in ray engine • Critical to interval generation • Applications • Ballistic simulation • Transparent rendering • … Gribble et al., Multi-Hit Ray Traversal 14
Buffered multi-hit with early exit 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) hitList hitMask repeatNode Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 15
Initialization 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) ray hitList hitMask repeatNode Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 16
Initialization 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) ray hitList - - - hitMask repeatNode Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 17
Traverse nodes 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) ray hitList - - - hitMask repeatNode Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 18
Traverse nodes 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - - - hitMask - - - - - - repeatNode Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 19
Find some hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - - - hitMask - - - - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 20
Find some hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitData hitList - - - hitMask - - - - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 21
Find some hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - - hitMask - - - - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 22
Find some hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitData hitList - - - hitMask - - - - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 23
Find some hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitData hitList - - - hitMask - - - - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 24
Find some hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList hitMask - - - - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 25
Find some hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitData hitList hitMask - - - - - - repeatNode F T Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 26
Process some hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - hitMask - - - - - - repeatNode T Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 27
Process some hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - - hitMask - - - - - repeatNode T Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 28
Process some hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - - - hitMask - - - - repeatNode T Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 29
Find some (more) hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - - - hitMask - - - repeatNode T F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 30
Find some (more) hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - - - hitMask - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 31
Find some (more) hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - - - hitMask - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 32
Find some (more) hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitData hitList - - - hitMask - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 33
Find some (more) hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - - hitMask - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 34
Find some (more) hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - - hitMask - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 35
Find some (more) hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - - hitMask - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 36
Process some (more) hits 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - - - hitMask - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 37
Traverse (more) nodes 1 function Traverse(root, ray) 2 Initialize(hitList) 3 node <- root 4 while Valid(node) do 5 if !Empty(node) then 6 Initialize(hitMask) 7 repeat 8 repeatNode <- FALSE 9 fortriangleinnodedo 10 if !Contains(hitMask, tID) then 11 if Intersect(triangle, ray) then 12 hitData <- (t, u, v, tID, ...) 13 if Full(hitList) then 14 repeatNode <- TRUE 15 Insert(hitList, hitData) 16 for hitData in hitList do 17 if !UserHit(ray, hitData) then 18 return 19 ifrepeatNodethen 20 Add(hitMask, hitData.tID) 21 until !repeatNode 22 node <- Next(node) node ray hitList - - - hitMask - - - repeatNode F Buffered multi-hit ray traversal Gribble et al., Multi-Hit Ray Traversal 38
Performance – tests • Find-first-intersection • First-hit v. buffered multi-hit • Isolates multi-hit overhead • Find-all-intersections • Find-some-intersections Gribble et al., Multi-Hit Ray Traversal 40
Performance – tests • Find-first-intersection • Find-all-intersections • Naive v. buffered multi-hit • Bounds performance expectations • Find-some-intersections Gribble et al., Multi-Hit Ray Traversal 41
Performance – tests • Find-first-intersection • Find-all-intersections • Find-some-intersections • Naive v. buffered multi-hit • Demonstrates in situ performance Gribble et al., Multi-Hit Ray Traversal 42
Performance – scenes • First-hit, naive & buffered multi-hit traversal implemented in Rayforce • First-hit performance is in range of 200-800 Mrps • Images rendered at 1024x768 pixels on an NVIDIA GeForce GTX 690 sibe 80K tris fair 174K tris conf 282K tris tank 1M tris sanm10M tris Gribble et al., Multi-Hit Ray Traversal 43
Find-first-intersection first-hit -29.08% buffered multi-hit -31.69% -30.44% -31.76% -30.75% Mips Gribble et al., Multi-Hit Ray Traversal 44
Find-all-intersections +9.74% naive multi-hit +8.07% buffered multi-hit +7.42% +12.30% +11.80% Mips Gribble et al., Multi-Hit Ray Traversal 45
Find-some-intersections +8.38% naive multi-hit +14.95% buffered multi-hit +15.40% Scenes of highest complexity +100.52% +80.97% Mips Gribble et al., Multi-Hit Ray Traversal 46
Example applications Ballistic simulation Transparent rendering Gribble et al., Multi-Hit Ray Traversal 47
Other (possible) applications • Alpha textures • Thin fibers • Constructive solid geometry [Wald et al. 2007] Gribble et al., Multi-Hit Ray Traversal 49
Other (possible) applications • Alpha textures • Thin fibers • Constructive solid geometry [Sintorn & Assarson 2008] Gribble et al., Multi-Hit Ray Traversal 50