New perlin noise function help

Hello!

I’m working on part two of my Pixelblaze & Lux Lavalier code tutorial, and trying to understand the ranges of values passed to and returned from the perlin function.

This code shows perlin returning numbers ranging from approx -0.5 to 0.5. Note that I’m using 0.01 for time just so the min and max vars that I’m watching (in the vars watch) update quicker.

export var min
export var max

export function beforeRender(delta) {
  t = time(.01)
  noiseSpeed = t * 256 // noise inputs range from 0 to 256?
  w = perlin(noiseSpeed, 0, 0, 0)
  if (w < min) min = w
  if (w > max) max = w
  w = w + 0.5 // perlin returns values ranging from -0.5 to 0.5? adjust them to 0.0 to 1.0
}

export function render2D(index, x, y) {
  h = x - w
  hsv(h, 1, 1)
}

That makes a 1D rainbow (vertical bands) that moves horizontally back and forth irregularly.

Question one: It works, but seems to freeze in place periodically, not sure why?

Then, when I try to make a 2D noise rainbow with this code, I get a different range of return values from perlin (-0.885971 to 0.772766):

export var min
export var max

export function beforeRender(delta) {
  t = time(.01) // very slow sawtooth wave, every 458.752 seconds!
  noiseSpeed = t * 256 // noise inputs range from 0 to 256
}

export function render2D(index, x, y) {
  x2 = x + noiseSpeed
  y2 = y
  w = perlin(x2, y2, 0, 0)
  if (w < min) min = w
  if (w > max) max = w
  w = (w * 1.1 + 1) / 2 // adjust the value to 0.0 to 1.0
  h = w
  hsv(h, 1, 1)
}

Question 2: what is the expected range of inputs and outputs, to and from the perlin noise function? Question 3: Why multiply noiseSpeed (ranging from 0.0 to 1.0) by 256? Wouldn’t that result in a range from 0 to 256? I would expect, if it’s a one byte range, that you’d multiply by 255 to get 0 to 255.

Any assistance would be greatly appreciated, thanks!

Hi,
I’ll have a go at this, and @wizard can correct me later on the details!

perlin() returns a value that’s guaranteed to be between -1 and 1, but is not guaranteed to contain the full range along any given path through the noise space. (To shift it to a 0 to 1 range, I use n = 0.5+0.5*perlin(x,y,z,seed).)

Over time, with a relatively complex x,y,z path through the noise field, the distribution of noise values is approximately Gaussian. Central values occur frequently, full-on -1 and 1 much less so.

In this implementation, if the x, y and z parameters are all integers the returned noise value will always be zero. The default range of x,y, and z is 0.0 - 255.9999. It wraps at 256. Negative numbers seem to start at the “far” edge and work backwards.

The nearer to integer the coordinate values, the nearer the returned noise value to zero. That’s part of the explanation for the “freeze” in your 1D version. The other part is this: – when you’re perturbing only x, and holding y and z at zero, you’re walking a grid edge and it’s something of a degenerate case. X Values from 255.0001 - 255.9999 also all return 0. So in a given run, chances are that you will periodically land on short sequences where x has values that cause the function to return 0, which means the display is still.

There’s no real trick to the multiplier: when you use 256 with a 0 - 1 sawtooth wave, you’re just mapping the wave’s value to the full default range of the noise field. You can change this with setPerlinWrap() when convenient. A lower multiplier means you move across the noise field more slowly as the sawtooth increases and higher means faster.

3 Likes

Thanks @zranger1! I’ve updated the tutorial: Lux Lavalier | Writing Your Own Patterns: Part 2

4 Likes