ruby perlin noise generator
Been experimenting with Perlin Noise, which is a math function that is used (among other places) in special effects to generate realistic textures. I’m starting to use it to generate color maps instead of picking up colors from photographs. In keeping with my promise to post code samples on this site, here’s a Perlin noise generator in Ruby. The logic came from the pseudocode on this site. (Thanks, Hugo!)
It doesn’t seem to work perfectly… most specifically, it’s supposed to generate a number between -1.0 and 1.0, but it frequently steps over those boundaries. Anyone who can point out why that happens gets a cookie.
It’s working for my purposes, though. Pictures coming soon.
class PerlinMap
attr_accessor :persistence, :seed, :num_octaves
def initialize (p = 0.5, s = 100000, o = 6)
@persistence = p
@seed = s
@num_octaves = o
end
def result(x, y)
total = 0
@num_octaves.times do |i|
@i = i
frequency = 2 ** i
amplitude = @persistence ** i
total += interpolated_noise(x * frequency, y * frequency) * amplitude
end
srand
total
end
private
def noise(x, y)
srand (x * y * x + y) + @seed + @i
rx = rand * 2.0
rx - 1.0
end
def smooth_noise(x, y)
corners = ( noise(x-1, y-1) + noise(x+1, y-1) + noise(x-1, y+1) + noise(x+1, y+1) ) / 16
sides = ( noise(x-1, y) + noise(x+1, y) + noise(x, y-1) + noise(x, y+1) ) / 8
center = noise(x, y) / 4
corners + sides + center
end
def interpolate (a, b, x)
ft = x * Math::PI
f = ( 1.0 - Math.cos( ft ) ) * 0.5
a * ( 1.0 - f ) + b * f
end
def interpolated_noise(x, y)
int_x = x.to_i
frac_x = x - int_x
int_y = y.to_i
frac_y = y - int_y
v1 = smooth_noise(int_x, int_y)
v2 = smooth_noise(int_x + 1, int_y)
v3 = smooth_noise(int_x, int_y + 1)
v4 = smooth_noise(int_x + 1, int_y + 1)
i1 = interpolate(v1 , v2 , frac_x)
i2 = interpolate(v3 , v4 , frac_x)
interpolate(i1 , i2 , frac_y)
end
end