# Fractal Value Noise

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

## WHAT IS IT?

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.

## HOW IT WORKS

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.

## HOW TO USE IT

**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.

## THINGS TO NOTICE

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?

## THINGS TO TRY

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!)

## EXTENDING THE MODEL

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?

## CREDITS AND REFERENCES

This Netlogo model by Ethan Cuka, 2023

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

https://thebookofshaders.com/13/ https://www.shadertoy.com/view/4dS3Wd

## Comments and Questions

patches-own [ height ] to setup clear-all set seed-a random-float 100000 set seed-x random-float 1000 set seed-y random-float 1000 generate reset-ticks end to go generate tick end ;; 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 ] ] rescale-height if ridgify [ ask patches [ set height -1 * abs (height * -1) ] rescale-height ] if squarify [ ask patches [ set height height / sqrt (abs height) ] rescale-height ] ask patches [set pcolor scale-color white height -1 1] end ;; 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) ] end ;; 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 end ;; 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 end

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

## Attached files

File | Type | Description | Last updated | |
---|---|---|---|---|

Fractal Value Noise.png | preview | Preview for 'Fractal Value Noise' | 9 months ago, by Ethan Cuka | Download |

This model does not have any ancestors.

This model does not have any descendants.

Ethan Cuka

## 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 9 months ago