Elevating Perlin Noise: Creative Tips for Dynamic Visuals

Title image

If you're tired of generating the same old Perlin noise patterns, this article is for you. I’ll share a few simple techniques to transform mundane noise into something truly captivating.

[Japanese version / 日本語版はこちら]

Standard 2D noise often yields predictable results—like this basic field:

The ordinary picture with the 2D noise.

Or this "hairy" pattern that many creative coders run into:

The ordinary picture of the line with the 2D noise.

I’m going to show you how to push these parameters further to create textures like these—from brindled fields to rhythmic ripples:

The brindled noise field.
The wavy noise field.
The noise field like a ripple.

With these tips, even that "hairy mess" can be turned into something artistic!

The noise field of concentric circle.

This article assumes you have some experience with the noise() function in Processing or p5.js. If you're new to noise, I recommend starting with this series:

📘 Come on! Feel the noise! Part 1
📘 Come on! Feel the noise! Part 2

 

The Standard Approach

First, let’s look at a typical way to apply noise to color using HSB mode.

HSB is ideal for creative coding because it allows for intuitive control over hue, saturation, and brightness.


colorMode(HSB, 360, 100, 100, 100);
let pHue = initHue + noise(n02) * hueStep;
let pSat = noise(10, n01, n02) * 100;
let pBri = noise(20, n01, n02) * 100;
fill(pHue % 360, pSat, pBri, 100);


In the basic example below, we map noise values directly to HSB parameters:


const w = 570;
const h = 360;
const wDiv = 285;
const hDiv = 180;
const nStep = 0.005;

function setup() {
  createCanvas(w, h);
  colorMode(HSB, 360, 100, 100, 100);
  noLoop();
}

function draw() {

  let cellW = w / wDiv;
  let cellH = h / hDiv;
  let baseHue = random(360);

  background(0, 0, 0, 100);
  noStroke();

  for (let x = 0; x < w; x += cellW) {
    let nX = x * nStep;
    for (let y = 0; y < h; y += cellH) {
      let nY = y * nStep;

      let nValH = noise(10, nX, nY);
      let nValS = noise(20, nX, nY);
      let nValB = noise(30, nX, nY);
      let nHue = (baseHue + nValH * 240) % 360;
      let nSat = 30 + 60 * nValS;
      let nBri = 20 + 80 * nValB;

      fill(nHue, nSat, nBri, 100);
      rect(x, y, cellW, cellH);
    }
  }

}

function mouseClicked() {
  let dt = new Date();
  noiseSeed(dt.getTime());
  redraw();
}


Changing the hue, saturation, brightness values with the Perlin noise.

You can adjust the "smoothness" by changing the nStep value. A smaller step creates a more gradual transition, while a larger step results in a more granular texture.


const nStep = 0.002;

Changing the hue, saturation, brightness values with the Perlin noise.


const nStep = 0.008;

Changing the hue, saturation, brightness values with the Perlin noise.

I'll show you the tips with this code as the base.

 

Tip 1: Nesting Noise (Domain Warping)

We start with a standard 2D noise implementation:


let nValH = noise(10, nX, nY);
let nValS = noise(20, nX, nY);
let nValB = noise(30, nX, nY);

Note: I used constants like 10, 20, and 30 as offsets to generate distinct noise sets. While it might look like 3D noise, it is effectively 2D noise with different seeds.

Instead of passing static coordinates to your noise function, try nesting them. This adds a second layer of distortion, often called "nested noise."

I put one more parameter 'nP' and calculate 'nP' with 'noise()'.


let nP = noise(nX, nY);
let nValH = noise(10 + nP, nX, nY);
let nValS = noise(30 + nP, nX, nY);
let nValB = noise(40 + nP, nX, nY);

The picture with the nested noise.

The result is much more organic and unpredictable.


let nP = noise(nX, nY) * 5;

The picture with the nested noise.

Starting to look interesting, right?

This technique is a simplified version of "Domain Warping," a powerful method for creating complex textures.

 

Tip 2: Mathematical Ingenuity

You don't have to use nX and nY linearly. By altering the input calculation, you can force the noise to follow specific geometric structures.

Diagonal Bias:


let nP = noise(nX + nY) * 5;

The noise field with the diagonal line.

Radial/Curved Structures:


let nP = noise(nX * nY) * 5;

The noise field with the curved line.


let nP = noise(nX * nX + nY * nY) * 5;

The noise field with the concentric circle.

 

Going Further with Trigonometry

Integrating sin() or cos() into your noise parameters can create mesmerizing, wave-like interference patterns.


let nP = (cos(nX * 2) + sin(nY)) * 5;

The noise field with the swirl.


let nP = cos(nX * sin(nY * 2.0)) * 3;

The noise field with the ripple.

 

Shaping Noise with Distance Functions

By calculating the distance (dist()) from the center or a specific point, you can constrain your noise to follow circular or swirling paths.


let nP = sin(dist(x, y, w * 0.5, h * 0.5) / w * HALF_PI) * 5;



let d = dist(x, y, w * 0.5, h * 0.5);
let dx = cos(PI * d / w) * w;
let dy = sin(PI * d / h) * h;
let nP = dist(x, y, dx, dy) * nStep * 5;



let dx = x;
let dy = (sin(x / w * PI * 3) * 0.2 * x / w + 0.5) * h;
let nP = dist(x, y, dx, dy) * nStep * 3;



let dx = constrain(x, 0, w * 0.7);
let dy = (sin(x / w * PI * 5) * 0.2 * (1 - x / w) + 0.5) * h;
let nP = dist(x, y, dx, dy) * nStep * 3;


 

Conclusion: Experiment and Explore

As you can see, the secret to mastering Perlin noise lies in how you manipulate its input parameters. By combining trigonometric functions, distance calculations, and nested noise, the possibilities are endless.

I’d love to see what you create using these techniques. Happy coding!

Next Post Previous Post
4 Comments
  • Unknown
    Unknown Thursday, November 18, 2021

    My man, you are awesome!

  • deconbatch
    deconbatch Friday, December 10, 2021

    Thank you so much! 😀

  • Michael Kohlhaas
    Michael Kohlhaas Thursday, December 26, 2024

    Remember how you did the first picture?

    • deconbatch
      deconbatch Friday, February 07, 2025

      I think it may be similar to the last code example in this article.
      [ Come on! Feel the noise! Part 1 ]
      https://www.deconbatch.com/2020/11/come-on-feel-noise-part-1.html
      Enjoy! 👍

Add Comment
comment url