Efficient ray tracing—spatial subdivision
COSC342
Lecture 20 12 May 2016
We continue our examination of efficiency in ray tracing
Recall our benchmarking against professional ray tracing, and our set of problem areas to explore:
I Aliasing artefacts
I No surface/surface illumination
I No caustics
I Real shadows are soft
I Colour problems
Where are we spending the time?
I Let’s say we have 1000 × 1000 pixels in the image.
I We’ll assume we need 6 secondary rays per pixel.
I Say the scene contains 100K objects.
I It takes 10 operations per intersection test.
I On a 2GHz processor; maybe 5 clock cycles per operation.
I So how long does it take to render the image?
I (Is that really all that we want?)
More importantly: where are we wasting time?
I Most software spends the majority of its time in a very small subset of
the code.
I In a simple raytracer? Much of the time will be spent doing
intersection tests between rays and objects.
I But if we take any given ray, how many objects is it likely to actually
intersect?
Bounding volumes can reduce intersection test count
I Key idea: Enclose objects inside a volume that has a simple
intersection test (e.g. a sphere).
I You only need to know if the ray can hit the volume, not precisely
where it hits.
I Does this decrease or increase computation? It depends . . .
I For n rays; a cost B for an intersection test with a bounding volume;
m rays that intersect the bounding volume; and a cost I for object intersection tests, we get:
Hierarchical Volumes
I Key idea: Put bounding volumes within bounding volumes.
I In other words, we form a tree of bounding volumes.
I If the volumes are placed really well, then we get O(log n)
intersection tests.
I Unfortunately, good placement of the bounding boxes cannot always
be done automatically.
I Also, while non-spherical volumes can produce tighter bounds
Spatial Subdivision
I Rather than adding new (invisible) objects as boundaries . . .
I Let’s just divide up the volume of space within which the scene sits.
I But first some terminology: if a picture element is called a pixel . . .
Uniform space subdivision
I How do we
determine the next voxel to test?
Cleary’s Algorithm tells us which voxel to visit next
Ray dx dy ix iy I dx is the distancetravelled along the ray from its start to when the ray crosses a cell boundary in x (i.e. a vertical grid line in this case)
Cleary’s Algorithm—the process
I Let’s assume we start in voxel (x , y , z)
I Find smallest of dx, dy, dz—this will tell you which side of voxel wall
you will reach first.
I Increment that axis e.g.: for dx being smallest, set x ← x + 1.
I Update the appropriate d value, e.g.: dx ← dx + ix.
I Check voxel (x , y , z) for object intersections.
Adaptive Subdivision
I Instead of lots of little empty cells, let’s aim to make the empty cells
as big as possible.
I Use a tree structure to create a hierarchy of bounding cubes.
I You will get fewer voxels.
I Is there a down side?
Octrees—applying the Quadtree concept in 3D
I Divide until a cell has one object in it, or is too small.
I Octrees facilitate raytracing CSG objects well (we will cover CSG in a
later lecture).
I . . . but the voxel-stepping algorithm is no longer obvious.
I (For historical contests between uniform and non-uniform spatial
Some other neat tricks regarding optimisation
I Limit recursion depth by the colour contribution made to a pixel.
I Keep a reference to the last object that caused a shadow.
I Do the inside/outside test on triangles before plane intersection.
So instead of:
(b − a) × (p − a) · n, (c − b) × (p − b) · n, (a − c) × (p − c) · n do: