There is a sketch on OpenProcessing which seems to have much more detail with OpenSimplexNoise:-
attr_reader :img, :colors, :theta, :phi, :remap1, :remap2
R = 5
RR = 1
def setup
sketch_title 'PNoise Pattern'
color_mode(RGB, 1.0)
@theta = 0
@phi = 0
# the dimensions of the image are twice the dimentions of
# the canvas to add antialiasing when the image is reduced
@img = create_image(2 * width, 2 * height, RGB)
@colors = (0..255).map { color(rand, rand, rand) }
@remap1 = ->(a, b, c) { ((SmoothNoise.noise(a, b, c) + 1) * 128).floor }
@remap2 = ->(a, b) { ((SmoothNoise.noise(a, b) + 1) * 128).floor }
end
def noisef(a, b, c, t)
remap2.call(remap1.call(a, b, c), t)
end
def draw
# fill the array with rand colors
# create pattern
img.load_pixels
grid(img.width, img.height) do |x, y|
# map x and y to angles between 0 and TWO_PI
@theta = map1d(x, 0..img.width, 0..TWO_PI)
@phi = map1d(y, 0..img.height, 0..TWO_PI)
# calculate the parameters of noise with the equation of a torus
# this is used to make the pattern seamless
nx = (R + RR * cos(phi)) * cos(theta)
ny = (R + RR * cos(phi)) * sin(theta)
nz = RR * sin(phi)
# normalize noise parameters so that the de pattern has homogeneous dimensions
nx = norm(nx, 0, R + RR)
ny = norm(ny, 0, R + RR)
nz = norm(nz, 0, RR)
# apply noise twice and use the equivalent color on the pallete
img.pixels[x + y * img.width] = colors[noisef(nx, ny, nz, frame_count / 5)]
end
img.update_pixels
# display pattern
image(img, 0, 0, width, height) # the image is reduce to the size of the canvas to make it smooth
end
def key_pressed
save(data_path('image.png'))
end
def settings
size(500, 500)
end
An interesting thing that came out of this experiment is you have to be careful where you declare your lambda functions (in this case within setup made most sense). I made virtue out of necessity when I created my remap
lambdas necessary because of SimplexNoise range (-1.0..1.0)
cf processing (and Perlin) noise range(0..1.0
).