Uniformly Distributed Perlin Noise

Problem

Processing’s noise implementation has many issues:

  • Repeats after a very small cycle in the x and y axes.
  • Strange repeating motion in z axis.
  • Block-like pattern/artefacts
  • Normally distributed (bell-curve distribution). Sometimes this is good, but I’d say this is generally undesirable in creative coding, and particularly undesirable for color generation (as exemplified below).

Solution

To mainly solve the fourth point, I created a small library that outputs noise values that are uniformly distributed between [ 0, 1 ]. In most of my use-cases (in creative coding and elsewhere) this distribution is much more desirable. Not only that, the library wraps FastNoiseLite providing “much better quality” noise compared the abysmal offering in Processing.

Comparison

Images showing Processing’s noise() on the left verrsus UniformNoise on the right.

Octaves = 1

Octaves = 4

Octaves = 16

Small scale, octaves = 4

Sketch Code

Code...
import micycle.uniformnoise.*;

UniformNoise noise;

int octaves = 4;

void setup() {
  size(800, 800);
  loadPixels();
  noise = new UniformNoise();
  noiseDetail(octaves);
}

void draw() {
  float scale = 1;
  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      float val;
      int col;
      if (x < width/2) {
        val = noise(x * 0.015f*scale, y * 0.015f*scale, frameCount*0.035f);
        col = hsbToRgb(val, 1, 1);
      } else {
        val = noise.uniformNoise(x * 0.0085f*scale, y * 0.0085f*scale, frameCount*0.01f, octaves, 0.5f);
        col  = hsbToRgb(val, 1, 1);
      }
      pixels[y * width + x] = col;
    }
  }
  updatePixels();
}

public static int hsbToRgb(float hue, float saturation, float value) {
  float r = 0, g = 0, b = 0;

  int h = (int)(hue * 6);
  float f = hue * 6 - h;
  float p = value * (1 - saturation);
  float q = value * (1 - f * saturation);
  float t = value * (1 - (1 - f) * saturation);

  if (h == 0) {
    r = value;
    g = t;
    b = p;
  } else if (h == 1) {
    r = q;
    g = value;
    b = p;
  } else if (h == 2) {
    r = p;
    g = value;
    b = t;
  } else if (h == 3) {
    r = p;
    g = q;
    b = value;
  } else if (h == 4) {
    r = t;
    g = p;
    b = value;
  } else if (h <= 6) {
    r = value;
    g = p;
    b = q;
  }
  return -16777216 | ((int) (r*255) << 16 | (int) (g*255) << 8 | (int) (b*255));
}
10 Likes

This may provide some context to the use of Perlin noise in Processing:

Processing reference:

:)

1 Like

I thought I would compare JRubyArt noise (derived from KdotJPG OpenSimplex2) to see how that would fare, here is the test code:-

load_library :uniform_noise

java_import 'micycle.uniformnoise.UniformNoise'
java_import 'java.awt.Color'

OCTAVES = 4

def setup
  sketch_title 'Uniform Noise Test'
  load_pixels
  @unoise = UniformNoise.new
end

def draw
  grid(width, height) do |x, y|
    val = if x < width / 2
            (noise(x * 0.015, y * 0.015, frame_count * 0.035) + 1) / 2
          else
            @unoise.uniform_noise(x * 0.0085, y * 0.0085, frame_count * 0.01, OCTAVES, 0.5)
          end
    col = Color.HSBtoRGB(val, 1, 1)
    pixels[y * width + x] = col
  end
  update_pixels
end

def settings
  size(800, 800)
end

Here is the result

The uniform noise is clearly the winner here, but OpenSimplex2 is an improvement over the processing “perlin noise”. There is even a variation that is more suitable for creating terrains.

4 Likes