|
|
See "Fractal noise" in povray.advanced-users. After reading Christoph's
reply, I built this...
First, I *eventually* came up with a macro which always returns the same
random value within the same "cube" in space, but in neighoring cubes there
is no correlation. (See 1st image.)
You would not believe how hard it was to make a macro that takes a 3D vector
as a seed... OK, for 1D, you just use your value directly as the seed. But
for 2D? You could just use X+Y as the seed - but then you get diagonal
patterns. (Since 5+7 = 7+5.) You could also try X*Y, but that has the same
problem. (Plus X*0 = 0, which makes things harder still.)
The algorithm I eventually came up with is NOT FAST. Simply initialise a
random stream to zero, then throw away a given number of samples. How many?
100*X + 10*Y + Z, modulo 256. (Modulus to hopefully speed things up without
loosing "randomness".) Small problem: answer needs to be positive. Solution?
Use abs(). Problems? Now we have symmetry about the origin! Solution? If
anything is negative, add on some arbitary (smallish) constant - different
for each axis.
Did you follow all that? POV-Ray did - sloooooooooowly. Surely there must be
a Better Way...
Next, interpolation. You wouldn't believe it could be this hard... I started
with linear interpolation, but there were huge discontinuities between
cells. I eventually figured out that 1) I had the coordinate axies
hopelessly muddled up, and 2) the interpolation parameter was running
backwards from 1 to 0, not 0 to 1. (I.e., all the cells were upside-down,
back-to-front and mirror image. Heh.) Once I sorted all that out, it worked
just great.
Then I made a small alteration: I took the parameter that runs from 0 to 1,
and took the cosine. This totally messed up the image, until I round the
correct transformation to bring the cosine back into the correct range. The
result is the 2nd image. Since for each point in space this calls the
interlying random macro 8 times (for the corners of the cube), it is
SUPERBLY SLOW! (Parse time for that image was 1 min 6 sec; render was 20 sec
btw.) Oh, and of course, while the value varies nice and smoothly, the
derrivative does not. I should probably fix that. (Which would require
sampling more randoms per point ==> slower still!)
So there you have it - a single wave that could make up part of a Perlin
noise function. (If I've understood what I read.) To make a real Perlin
function, I'd need several such waves, all of different wavelengths, and add
them together. Given how hellishly slow this wave is by itself, maybe I'll
go watch some paint dry instead...
If anyone can think of a faster random function that takes a 3D seed
(instead of the 1D seed POV-Ray's seed() function required) I'd love to know
about it... All other developments I want to try would involve more calls to
the random function, which will only get slower!
Thanks,
Andrew.
Post a reply to this message
Attachments:
Download 'Noise1.png' (127 KB)
Download 'Noise2.png' (192 KB)
Preview of image 'Noise1.png'
Preview of image 'Noise2.png'
|
|