I don't follow your code exactly, but here is a simplified description of the algorithm that will roughly achieve the effect (based on the image you posted).
The following explanation is not the super optimised version, but is one that's conceptually clear (I hope). Once you have got it running, you can optimise it (quite drastically, in fact).
- Generate n layers of uniform random
noise (just random greyscale
pixels).
- Now sample each of these by sampling every, 1, 2, 4, 8, ... 2^(n-1) pixels, and interpolating the intermediate pixels. Each layer is smoother than the previous one.
- Now scale of these with a factor of 1, 2, 4, 8, etc. Each layer is darker than the previous one.
- Add all these together.
- Normalise by dividing each pixel with (1 + 2 + 4 + 8 + ... 2^(n-1)).
The difficult step is the sampling and interpolation step. Suppose we are in the layer skipping sampling every m-th pixel. Here is the basic idea for m > 1 (if m is 1, we use the image as is):
for each pixel x and y
left_sample_coord = m *(x / m) //(integer division, automatically truncated)
right_sample_coord = (left_sample_point + m) % image_width
top_sample_point = m*(y / m)
bottom_sample_coord = (top_sample_point + m) % image_height
horizontal_weight = (x - left_sample_point) / (m - 1)
vertical_weight = (y - top_sample_point) / (m - 1)
sample_top_left = image(left_sample_coord, top_sample_point)
//and the same for the other four corners
//now combine the top two points
top_interpolate = sample_top_left * horizontal_weight + sample_top_right * (1-horizontal_weight)
//now combine the bottom two points
bottom_interpolate = sample_bottom_left * horizontal_weight + sample_bottom_right * (1-horizontal_weight)
//and combine these two last obtained values
smooth_noise(x, y) = top_interpolate * vertical_weight + bottom_interpolate * (1 - vertical_weight)
A few tips:
- The result of the algorithm above might seem a bit washed out. You can reduce this effect by using the same layer of noise for all layers, or be contrast enhancing the image afterwards.
- The algorithm above uses linear interpolation, but cosine interpolation (do a search) gives much better results.
- Make it possible to look at your layers separately during all parts of the algorithm. This will help you flush out bugs quickly.