Fractal Value Noise

Fractal Value Noise preview image

1 collaborator

Default-person Ethan Cuka (Author)



Tagged by Ethan Cuka 8 months ago

procedural generation 

Tagged by Ethan Cuka 8 months ago


Tagged by Ethan Cuka 8 months ago


Tagged by Ethan Cuka 8 months ago

Visible to everyone | Changeable by everyone
Model was written in NetLogo 6.3.0 • Viewed 82 times • Downloaded 1 time • Run 0 times
Download the 'Fractal Value Noise' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


Fractal Noise is a method for generating a field of semi-random values, where each region blends smoothly into its neighbors, but also has details of its own. By adding more layers of noise, representing smaller regions, it is possible to create an arbitrary amount of increasingly fine details.

This method is commonly used in computer graphics for procedurally generated textures and terrain: by beginning with a cloud of fractal noise and adding a variety of effects and filters, artists and programmers can create very rich patterns that appear convincing and naturalistic.

This model allows users to explore the different parameters of noise generation and how they can be used to create different textures.


The algorithm considers a square grid of points. At each point on the grid, it assigns a value between 1 and -1. At points not directly on the grid, it interpolates between its 4 nearest neighbors to smoothly transition between grid points.

The process is repeated, with a new grid of twice the frequency (smaller grid spacing) and half the amplitude (-0.5 to +0.5) This new grid is superimposed on top to add a new layer of smaller details.

By adding higher frequencies of noise on top of each other, the algorithm generates a cloud-like pattern, with both large variations in texture over broad regions, and small variations over narrow regions.

Finally, the resulting values are linearly scaled to be between -1 and 1.


  • Iterations controls how many layers of noise to generate. Fewer iterations will result in less detailed noise. There are diminishing returns for higher iterations based on the amplitude scaling.

  • Amplitude Scaling controls how strong each successive layer will be in the final product. At high amplitude scaling, only the first few iterations of noise, which represent low-frequency components, will be noticable. This results in smoother terrain. At low amplitude scaling, higher frequencies will be more visible. This results in more chaotic noise.

  • Frequency Scaling controls the dimensions of each successive layer. At the default (2), each layer of noise is twice as tightly-spaced as the one above it.

  • Zoom simply scales the noise cloud to examine wider or narrower details.

  • Offset adds a flat amount to each point, changing the threshold/"brightness" of the overall pattern.

  • Ridgify takes the absolute value of each point in the cloud and then rescales the cloud. At points where the noise passes through zero, this creates sharp lines.

  • Squarify finds each point's square root while preserving sign. This makes high and low regions more likely, while avoiding middle regions. (Observe how the histogram changes when Squarify is applied)

  • The seed" sliders affect the way underlying random values are generated.


  • As you vary each setting, consider what sort of textures an artist might be able to create with the resulting pattern.

  • Turn the number of iterations down to 1 to see the lowest level of noise generated. Why does it have a "blocky" texture? Why does this blockiness diminish when more iterations are added?

  • How does varying the amplitude scaling affect the "graininess" of the noise? Why?

  • Perfect fractal noise would look approximately the same at all zoom levels. How does the texture of this noise change at different zoom levels? Why? (Hint: the fundamental frequency of the generated noise is based off of the World size)

Seeding and Random Scalar Generation

For these questions, examine the rand function in the code, which is used to generate a random scalar between -1 and 1.

  • Why does the center of the noise cloud always look the same, no matter what seed parameters are used?

  • What happens when the X and Y seed are the same, or integer multiples of each other? Why does this happen?

  • What happens when seed-a is very low? Why does this happen?


  • The Squarify and Ridgify switches apply some new effects to the noise to create new patterns. What other effects can you think of to apply to the noise cloud?

  • Each iteration of noise uses the same seed to generate itself. As a result, each layer is just a scaled down version of the layer above. This produces an "alias"-like stripe that pass through the center of the noise. How would you prevent this? (There are multiple ways to do so!)


This model uses Value Noise, where each point on the grid is a scalar value between -1 and 1. A common alternative is Perlin Noise, or Gradient noise, where each grid point is a vector with a random direction, and points that do not sit on the grid have a value based on the dot product of their offset vector and the gradient vector.

The result is often noise with more convincing variations between regions. How would you alter the noise function in this program to generate Perlin noise, rather than Value noise?


This Netlogo model by Ethan Cuka, 2023

These two resources were used for help in generating convincing random values, and for interpolating between values.

Comments and Questions

Random function kinda sucks

I left some discussion problems in my model about the random seed function, since I found some fun problems with it: because the coordinates passed to it are centered at 0 and are the same for any given [x, y] regardless of octave, you get some weird issues with the noise: * Each layer of noise is the same, just scaled down, so you get these lines that lead towards the center as noise layers align with the layers behind them which gets worse at lower frequency scaling ratios. * The random numbers are generated from a high frequency sin wave with no phase shift, so the center of the noise is always the same color. On reflection, I don't know that the questions I raise regarding this are particularly insightful and are kind of unrelated to the topic. I probably should have just fixed it instead of leaving it broken on purpose. Both of these can be easily fixed any number of ways. I did it by just nudging the random function a bit based on the index of the current iteration, e.g: to-report rand [x y n] let dot seed-a * sin(n * ((x + n) * seed-x + (y - n) * seed-y)) report dot - floor dot end

Posted 8 months ago

Click to Run Model

patches-own [

to setup
  set seed-a random-float 100000
  set seed-x random-float 1000
  set seed-y random-float 1000

to go

;; Generate several layers of noise and superimpose them.

to generate
  ask patches [
    set height 0
    let amplitude 1
    let frequency 1 / (max-pxcor - min-pxcor)
    repeat iterations [
     set height height + amplitude *  (noise (pxcor * zoom * frequency) (pycor * zoom * frequency))
     set frequency frequency * frequency-scaling ;; Each layer of noise is a higher frequency than the previous, creating increasingly fine details
     set amplitude amplitude / amplitude-scaling ;; Each layer of noise is a lower amplitude than the previous so that small terrain details don't cover up larger ones

  if ridgify [
    ask patches [ set height -1 * abs (height * -1) ]
  if squarify [
    ask patches [ set height height / sqrt (abs height) ]
  ask patches [set pcolor scale-color white height -1 1]

;; Rescale all cells to be between -1 and 1

to rescale-height
  let height-max [height] of max-one-of patches [height]
  let height-min [height] of min-one-of patches [height]
  let delta height-max - height-min
  let m 2 / delta
  let b (-1 - m * height-min)
  ask patches
    set height (m * height + b + offset)

;; Fractal Noise generator
;; We imagine a square with 4 corner points, with our point of interest somewhere inside
;; We assign each point a random value, and consider the dot product between our point of interest and each corner point
;; Then we interpolate between the 4 nearest points to get smooth transitions

to-report noise [x y]
  ;; The "floor" part of our vector tells us which square inside the noise cloud we are located within
  ;; The "fractional" part of our vector tells us where we are within that square
  let floor-x floor x
  let frac-x x - floor-x
  let floor-y floor y
  let frac-y y - floor-y

  ;; This is a special cubic interpolation function, which will gives us smoother results than linear interpolation
  let u-x (frac-x * frac-x * (3 - 2 * frac-x))
  let u-y (frac-y * frac-y * (3 - 2 * frac-y))

  ;; These scalar values represent the value at each corner of the grid containing our point of interest.
  let a rand floor-x floor-y
  let b rand (floor-x + 1) floor-y
  let c rand floor-x (floor-y + 1)
  let d rand (floor-x + 1) (floor-y + 1)

  ;; We interpolate between our 4 points to get the value at our point of interest
  let int_1 (b - a) * u-x + a
  let int_2 (c - a) * u-y * (1 - u-x)
  let int_3 (d - b) * u-x * u-y
  report int_1 + int_2 + int_3

;; Generate a random scalar vector
;; We use this instead of random-float because it allows our noise cloud to remain the same from patch to patch - otherwise, each patch would
;; base its value on a completely differently seeded noise cloud, and the result would be random static!

to-report rand [x y]
  let dot seed-a * sin(x * seed-x + y * seed-y)
  report dot - floor dot

There is only one version of this model, created 8 months ago by Ethan Cuka.

Attached files

File Type Description Last updated
Fractal Value Noise.png preview Preview for 'Fractal Value Noise' 8 months ago, by Ethan Cuka Download

This model does not have any ancestors.

This model does not have any descendants.