The problem with holes
If you ever try to construct an object that has a lot of holes in POVRay, you'll find
that it renders incredibly slowly. This page attempts to explain why this happens
and suggests something that you might be able to do about it.
First of all, lets see how bad the problem is. Here's a slab with 1600
holes in it. It's constructed as the difference between a box and 1600 cylinders.
On my machine it took 26 minutes 25 seconds to render this image,
whereas a plain slab without holes renders in 3 seconds, and a union of the 1600 cylinders
renders in 4 seconds.

Why is the difference of these two fast things so slow?
We can see some of what's happening if we look at the statistics for the scene.
C:\Program Files\POV-Ray\scenes\MJW\HoleTest.pov Statistics, Resolution 512 x 384
----------------------------------------------------------------------------
Pixels: 196608 Samples: 196608 Smpls/Pxl: 1.00
Rays: 196608 Saved: 0 Max Level: 1/5
----------------------------------------------------------------------------
Ray->Shape Intersection Tests Succeeded Percentage
----------------------------------------------------------------------------
Box 176850 107987 61.06
Cone/Cylinder 282960000 148853 0.05
CSG Intersection 176850 94663 53.53
Bounding Box 168886 98133 58.11
Light Buffer 268817 120392 44.79
Vista Buffer 197305 120818 61.23
----------------------------------------------------------------------------
Calls to Noise: 0 Calls to DNoise: 10
----------------------------------------------------------------------------
Shadow Ray Tests: 149634 Succeeded: 8444
----------------------------------------------------------------------------
Smallest Alloc: 26 bytes Largest: 10284
Peak memory used: 2144877 bytes
----------------------------------------------------------------------------
Time For Parse: 0 hours 0 minutes 2.0 seconds (2 seconds)
Time For Trace: 0 hours 26 minutes 23.0 seconds (1583 seconds)
Total Time: 0 hours 26 minutes 25.0 seconds (1585 seconds)
The significant line is
Cone/Cylinder 282960000 148853 0.05
This indicates that there's a huge number of cylinder tests being performed.
If we divide the number of cylinder tests (282960000) by the
number of rays cast (196608) we can see that there are an average of 1439.21
cylinder tests being performed on every ray. In fact, we can see that POVRay
performed 176850 CSG intersection tests, and if we divide 282960000 by that
number we can see that each CSG test required 1600 cylinder tests.

If we compare that with the relevant statistics from rendering a union
of 1600 cylinders we see this:-
Ray->Shape Intersection Tests Succeeded Percentage
----------------------------------------------------------------------------
Cone/Cylinder 141522 73966 52.26
Bounding Box 352932 107854 30.56
Light Buffer 1834283 576040 31.40
Vista Buffer 1512813 789580 52.19
The number of cylinder tests per ray is now only 0.72.
What's happening is that with a union of cylinders, POVRay is able to perform
some very clever bounding. If creates a bounding box around each cylinder, and
knows that it doesn't need to actually test the cylinder if the ray doesn't
intersect the bounding box. Furthermore, it creates a second level of bounding boxes
around clusters of first level bounding boxes, and it knows that it doesn't
have to test each first level box if the ray doesn't intersect the second level
bounding box, and so on.
So, what can we do about it
What we can do is to change from having one slab with 1600 holes to having a large
number of small slabs, each with a few holes.

In this image I've deliberately pulled the small slabs apart so that you can see
what's going on. If I keep the slabs together, then the resulting image is indistinguishable
from the original image, but it now only takes 8 seconds to render.
The relevant statistics are:
Ray->Shape Intersection Tests Succeeded Percentage
----------------------------------------------------------------------------
Cone/Cylinder 2839792 93181 3.28
Bounding Box 289371 106373 36.76
Light Buffer 1538201 508758 33.07
Vista Buffer 922299 461201 50.01
It turns out that the best we can do is to have 1600 slabs each with one hole in each
which renders in 5 seconds and gives statistics like this:
Ray->Shape Intersection Tests Succeeded Percentage
----------------------------------------------------------------------------
Cone/Cylinder 179410 66043 36.81
Bounding Box 597354 142627 23.88
Light Buffer 3274980 1093527 33.39
Vista Buffer 1640353 880769 53.69
Source Code
Download
Here's the scene file that I used to perform these tests. The number of slabs
and the number of holes per slab are controlled by the variables at the start of the file.
#declare N = 4; // Each box has N*N holes
#declare M = 10; // There are M*M boxes
Setting N=40, M=1 gives the worst case, and N=1, M=40 gives the fastest render.
Other Tricks
Holes Tutorial Part 2: Iso-Holes
Holes Tutorial Part 3: Transparent Holes (Bubbles)
Holes Tutorial Part 4: Blob-Holes
Back to Mike's Homepage
|