diff --git a/pages/guides/configuration/Noise.md b/pages/guides/configuration/Noise.md
index 29a93f4..2c166dc 100644
--- a/pages/guides/configuration/Noise.md
+++ b/pages/guides/configuration/Noise.md
@@ -5,19 +5,20 @@
- [Determinism](#determinism)
- [Seeds](#seeds)
- [Flavors of Noise](#flavors-of-noise)
- - [Multidimensional Noise](#multidimensional-noise)
+ - [Multidimensional Sampling](#multidimensional-sampling)
- [Segmentation](#segmentation)
- [Applying Noise to World Generation](#applying-noise-to-world-generation)
- [Coherent Noise](#coherent-noise)
- [Noise Segmentation](#noise-segmentation)
-- [Manipulating Noise](#manipulating-noise)
- - [Noise Configs](#noise-configs)
+ - [Generalizing the Sampler](#generalizing-the-sampler)
+- [Configuring Samplers](#configuring-samplers)
+ - [Sampler Configs](#sampler-configs)
- [Noise Tool](#noise-tool)
- [Frequency](#frequency)
- [In Context](#in-context)
- - [Fractal Noise](#fractal-noise)
+ - [Fractalization](#fractalization)
- [Domain Warping](#domain-warping)
- - [Chained Functions](#chained-functions)
+ - [Sampler Composition](#sampler-composition)
- [Conclusion](#conclusion)
@@ -26,34 +27,31 @@
In Terra, noise does not refer to sound you can hear, but rather a series of
[randomly](https://en.wikipedia.org/wiki/Pseudorandom_number_generator)* generated values. These values are produced by
-something we will call a **noise function** - which is just a fancy algorithm that converts an input into a randomized
+something we will call a **noise sampler** - which is just a fancy function that converts an input into a randomized*
numeric output.
```none
-┌──────────────────┐ ┌────────────────┐ ┌───────────────────┐
-│ Input parameters │ → > Noise Function > → │ Randomized output │
-└──────────────────┘ └────────────────┘ │ (aka 'noise') │
- └───────────────────┘
+┌──────────────────┐ ┌───────────────┐ ┌─────────────────────────────┐
+│ Input parameters │ → > Noise Sampler > → │ Randomized Numerical output │
+└──────────────────┘ └───────────────┘ │ (aka 'noise') │
+ └─────────────────────────────┘
```
+The numerical output values can be used to determine just about anything in world generation - such as the
+probability of a feature generating somewhere, how a set of biomes might be placed, and or the shaping of terrain.
+
### Why is noise important?
-Noise is a central concept in Terra, because just about every random aspect of world generation is influenced by noise
-to some degree. Having a basic understanding of noise and how to manipulate it will give you insight into how worlds are
-randomly generated by Terra, and is an important skill to have if you want to develop your own config packs.
+Noise is a central concept in Terra, because as mentioned above, just about every aspect of world generation is
+influenced by it. Having a basic understanding of noise and how to manipulate it will give you insight into how
+worlds are randomly generated by Terra, and is especially important to understand if you want to develop your own config
+packs.
Before learning how to manipulate noise, you should first have an understanding of the underlying concepts outlined
here. Don't worry, we won't throw anything *too complicated* at you for now! Having a firm grasp on noise will bring you
closer to controlling exactly how world generation will behave, which is why having a foundational understanding is
important.
-Here is just a short of list of things heavily influenced by noise in Terra:
-
-* The placement of biomes in the world.
-* How terrain is shaped.
-* How flora and trees are distributed.
-
-
## Noise Basics
Here we will cover some key points is grasping noise in Terra. If you feel like certain concepts are too difficult to
@@ -62,25 +60,25 @@ understand, feel free to skim over them for now, and revisit them later.
### Demonstration
Let's begin with a demonstration displaying the most basic process of 'creating' noise. We will use a theoretical
-implementation of a noise function called [*white noise*](https://en.wikipedia.org/wiki/White_noise), and generate some
-values with it. Explaining how exactly our *white noise* function creates these values is outside the scope of this
-guide, however is not essential in understanding the general idea.
+sampler implementation of a noise algorithm called [*white noise*](https://en.wikipedia.org/wiki/White_noise), and
+generate some values with it. Explaining how exactly our *white noise* sampler produces these values is outside the
+scope of this guide, however is not essential in understanding the general idea.
- We will perform a couple samples with our function, using numbers 1 - 10 as an input, and record the outputs as both a
- number and a shade from black to white. **Conventionally, the values outputted by a noise function will be within a
- range of -1 to 1.** We can visualize the relationship between the value and shade on a number line as such:
+We will perform a couple samples with our sampler, using numbers 1 - 10 as an input, and record the outputs as both a
+number and a shade from black to white. **Conventionally, the values outputted by a noise sampler will be within a
+range of -1 to 1.** We can visualize the relationship between the value and shade on a number line as such:
-
+
- We will also round the output to one decimal place for simplicity. *(Typical outputs will produce decimals with
- **much higher** precision than just one decimal place!)*
+We will also round the output to one decimal place for simplicity. *(Typical outputs will produce decimals with
+**much higher** precision than just one decimal place!)*
###### MODEL
```none
┌────────────────────┐ ┌─────────────┐ ┌──────────────────────┐
│ Input parameters │ → > White Noise > → │ Randomized output │
-├────────────────────┤ │ Function │ │ within range [-1, 1] │
+├────────────────────┤ │ Sampler │ │ within range [-1, 1] │
│ Number from 1 - 10 │ └─────────────┘ └──────────────────────┘
└────────────────────┘
```
@@ -89,43 +87,42 @@ guide, however is not essential in understanding the general idea.
-Simple, right? All our noise function does is convert one value to another. You can think of noise functions like a
-little number machine that takes an input and scrambles it around to produce an output.
+Simple, right? All our noise sampler does is convert one value to a randomized value.
###### SIDE NOTE
-> Input numbers do not have to be whole numbers! This means you can input numbers like `1.5` and noise functions will
-> work still the same way. We've just used integers here for the sake of demonstration.
+> Input numbers do not have to be whole numbers! This means noise samplers will still work the same way with inputs like
+> `1.5`. We've just used integers here for the sake of demonstration.
### Determinism
-One requirement of Terra noise functions is that the output must be
+One requirement of samplers is that the output must be
[*deterministic*](https://en.wikipedia.org/wiki/Deterministic_system), meaning given any input, the output must always
-be the same. This means we can reliably re-produce any 'random' results we get from noise functions by feeding it the
+be the same. This means we can reliably re-produce any 'random' results we get from noise samplers by feeding it the
same input.
-Going off the results above, when passing the number `5` to our *white noise* function, we will always get the number
+Going off the results above, when passing the number `5` to our *white noise* sampler, we will always get the number
`0.4` back.
### Seeds
-Sometimes, we want to use the same input, and same noise function, but for multiple random unique outputs. In that case,
-we can use a seed in our noise function. Seeds are basically a way of getting a whole new uncorrelated set of random
-values from the same inputs + noise function. Unlike the input value, seeds must be a whole number, meaning `5324` would
-be a valid seed, but `231.23` would not.
+Sometimes, we want to use the same input, and the same noise sampler, but for multiple random unique outputs. In that
+case, we can utilize something called a seed in our noise sampler. Seeds are basically a way of getting a whole new
+uncorrelated set of random values from the same noise sampler and set of inputs. Unlike the input value, seeds must be a
+whole number, meaning `5324` would be a valid seed, but `231.23` would not.
Expanding on our basic model of noise generation we have:
```none
-┌──────────────────┐ ┌────────────────┐ ┌───────────────────┐
-│ Input parameters │ → > Noise Function > → │ Randomized output │
-├──────────────────┤ └────────────────┘ └───────────────────┘
+┌──────────────────┐ ┌───────────────┐ ┌───────────────────┐
+│ Input parameters │ → > Noise Sampler > → │ Randomized output │
+├──────────────────┤ └───────────────┘ └───────────────────┘
│ - Seed │
│ - Input value │
└──────────────────┘
```
-Here is an example using two different seeds to produce different outputs, using the same inputs and noise function from
+Here is an example using two different seeds to produce different outputs, using the same inputs and noise sampler from
the example above.
`Seed = 0`
@@ -137,44 +134,44 @@ the example above.
One usage of seeds that you might be familiar with is minecraft world seeds. A vanilla minecraft world seed gets
-inserted into the many noise functions that govern vanilla world generation, resulting in completely different worlds
-per seed (since each noise function will return a completely new set of values for each unique seed). Combined with
+inserted into the many noise algorithms that govern vanilla world generation, resulting in completely different worlds
+per seed (since each noise algorithm will return a completely new set of values for each unique seed). Combined with
[determinism](#determinism), we're able to produce new unique randomized worlds by picking a random seed, while also
being able to generate the exact same world* provided we use the same seed.
-###### VANILLA BEDROCK GENERATION TRIVIA
+###### VANILLA WORLD GENERATION TRIVIA
-> Some noise functions in vanilla generation use the same seed for every world (meaning they don't factor in the world
-> seed), which can result in every world generating a certain characteristic the exact same way. One notable example -
-> the function that controls bedrock formation uses a static seed for every world, leading every vanilla generated world
-> to share the same random configuration of bedrock.
+> In previous versions of Minecraft, Some noise algorithms used the same seed for every world (meaning they don't factor
+> in the world seed), which resulted in every world generating a certain characteristic the exact same way. One notable
+> example - the algorithm that controls bedrock formation used a static seed for every world, leading every world to
+> share the same random configuration of bedrock.
-Within Terra world generation, all noise producing functions use a combination of the world seed and a value called
-**salt**, to determine its own seed. Salt is a number you specify when defining noise configurations, and simply gets
-added to the world seed. This allows individual noise configurations to use new sets of output values, while sharing the
-same base noise function.
+Within Terra, all samplers use a combination of the world seed and a value called **salt**, to determine its own seed.
+Salt is a number you can specify when defining noise sampler configurations, and simply gets added to the world seed.
+This allows multiple noise samplers to produce different sets of output values, while sharing the same noise algorithm.
### Flavors of Noise
-There are many variants and implementations of noise functions, such as our *white noise* function above. Each has their
+There are many variants and implementations of noise samplers, such as our *white noise* sampler above. Each has their
own quirks, behaviors, and applications, however in general they all follow the same basic principles outlined here. We
-will cover a couple of these variants later down the line.
+will cover a couple of these variants later down the line, including samplers that don't necessarily produce random
+noise.
-Here is a small list of notable noise functions that are commonly used in Terra:
+Here is a small list of notable noise algorithms that are commonly used in Terra noise samplers:
* Simplex Noise
* Cellular / Voronoi / Worley Noise
* White Noise
* Value Noise
-### Multidimensional Noise
+### Multidimensional Sampling
-The phrase 'multidimensional noise' may sound intimidating, but don't worry, it's a fairly simple concept to understand.
-Simply put, multidimensional noise involves providing **multiple** input values, rather than just one. In every example
-thus far, we have only provided one value for each noise *'sample'* (excluding the seed), meaning we are conceptually
-only sampling in one dimension, however we can go further.
+The phrase 'multidimensional sampling' may sound intimidating, but don't worry, it's a fairly simple concept to
+understand. Simply put, multidimensional sampling involves providing **multiple** input values, rather than just one -
+in order to produce a singular output value. In every example thus far, we have only provided one value for each noise
+*'sample'* (excluding the seed), meaning we are conceptually only sampling in one dimension, however we can go further.
-The simplest example of multidimensional noise is just adding one extra input to our noise function, for a grand total
+The simplest example of multidimensional sampling is just adding one extra input to our noise sampler, for a grand total
of 2 inputs. Conveniently, that gives us 2 dimensions, thus we can easily display a set of 2D samples in a grid. We will
refer to the first input as `X`, and the second as `Z`.
@@ -186,7 +183,7 @@ label the `X` & `Z` axes for the sake of simplicity.
```none
┌──────────────────┐ ┌─────────────┐ ┌───────────────────┐
│ Input parameters │ → > White Noise > → │ Randomized output │
-├──────────────────┤ │ Function │ ├───────────────────┤
+├──────────────────┤ │ Sampler │ ├───────────────────┤
│ - Seed │ └─────────────┘ │ Displayed as as a │
| - Input 1 (X) | │ 2D grid of shades │
| - Input 2 (Z) | └───────────────────┘
@@ -197,21 +194,21 @@ label the `X` & `Z` axes for the sake of simplicity.
-As you can see, all we have done is added another dimension to our white noise function, allowing for noise to be
+As you can see, all we have done is added another dimension to our white noise sampler, allowing for noise to be
depicted as a 2D grid, rather than a list of values.
Taking this experiment further, let's use a larger sample size of 64 x 64:
-What we have done here is essentially produced a random image using our *white noise* function. By default, we will
+What we have done here is essentially produced a random image using our *white noise* sampler. By default, we will
assume the above format of visualizing noise in 2D as an image, where each output value represents a grayscale pixel.
###### HIGHER DIMENSIONS
-Many noise algorithms support an arbitrary amount of inputs, meaning that we can sample noise in any number of
-dimensions. Typically, we will only use up to three dimensions in Terra, where each input corresponds to the position on
-each axis `X`, `Y`, and `Z`.
+Many noise algorithms support an arbitrary amount of inputs, meaning that it's technically possible to sample noise in
+any number of dimensions. Typically, we will only use up to three dimensions in Terra, where each input corresponds to
+the position on each axis `X`, `Y`, and `Z`.
### Segmentation
@@ -244,8 +241,8 @@ white pixel`, and `threshold = 50%`, we get the following result:
> Most applications of segmentation in Terra are essentially fancy piecewise functions like the one above, written
> programmatically.
-Segmentation is a useful concept to understand when combined with noise, as it allows us to split noise functions into
-distinct values. We will cover an example of segmented noise and an application of it in the following section.
+Segmentation is a useful concept to understand when combined with noise, as it allows us to split noise into distinct
+values. We will cover an example of segmented noise and an application of it in the following section.
### Applying Noise to World Generation
@@ -264,9 +261,9 @@ where noise is involved:
Simple enough, now we know that grass will only generate where appropriate. With only these rules however, we would end
up with grass on top of every single grass block! What if we only wanted it on *some* grass blocks? Well we can use our
-*white noise* function for that!
+*white noise* sampler for that!
-Let's feed our *X & Z world coordinates & seed* into our *2D white noise* function, which will give us a randomized
+Let's feed our *X & Z world coordinates & seed* into our *2D white noise* sampler, which will give us a randomized
output value (from -1 to 1 as discussed) for every X-Z column for any given world seed. We will then use that output
value to determine whether we place some grass or not. The way this will be determined is by simply
[thresholding](#segmentation) it! We'll start with a threshold of `0`, where any value below our threshold will mean
@@ -277,7 +274,7 @@ value to determine whether we place some grass or not. The way this will be dete
```none
┌──────────────────┐ ┌─────────────┐ ┌───────────────────┐ ┌─────────────────────────┐
│ Input parameters │ → > White Noise > → │ Randomized output │ → > Threshold Function │
-├──────────────────┤ │ Function │ ├───────────────────┤ ├─────────────────────────┤
+├──────────────────┤ │ Sampler │ ├───────────────────┤ ├─────────────────────────┤
│ - World Seed │ └─────────────┘ │ A value from │ │ If below the threshold, │
| - X Coordinate │ │ -1 to 1 │ │ place grass. (Displayed │
| - Z Coordinate │ └───────────────────┘ │ as a green pixel) │
@@ -309,16 +306,16 @@ be grass or not.
Thus far, we have only covered noise that outputs seemingly random tv-static-like values, which is fine for simple
applications like the grass example above. But how can we get noise capable of producing smooth rolling hills, vast
-mountains, and other structured random generation? Let's place the white noise function under the category
-**'random noise'**, and introduce a new category of noise functions called **'coherent noise'**.
+mountains, and other structured random generation? Let's place the white noise sampler under the category
+**'random noise'**, and introduce a new category of noise samplers called **'coherent noise'**.
###### WHAT'S THE DIFFERENCE?
-The main difference that separates *random noise* from *coherent noise* is that while random noise functions produce
-noise with no apparent structure, coherent noise functions produce *'structured'* noise, where adjacent input values
+The main difference that separates *random noise* from *coherent noise* is that while random noise samplers produce
+noise with no apparent structure, coherent noise samplers produce *'structured'* noise, where adjacent input values
produce correlated output values.
-To get a better idea of the difference, here is a visualization of two different 2D sampled noise functions that both
+To get a better idea of the difference, here is a visualization of the output of two different 2D noise samplers that both
share the same inputs:
`Random | Coherent`
@@ -328,13 +325,21 @@ share the same inputs:
As you can see, the coherent noise example has a discernible structure where output values are smooth, compared to the
-random noise example where there's no apparent structure. The coherent noise function used above is known as
-**Simplex noise**, and is one of the many flavors of noise provided in Terra.
+random noise example where there's no apparent structure. The coherent noise algorithm used in the sampler above is
+known as **Simplex noise**, and is one of the many flavors of noise provided in Terra.
+
+###### CATEGORIZATION OF NOISE SAMPLERS
+
+- Noise Samplers
+ - Random Noise Samplers
+ - White Noise
+ - Coherent Noise Samplers
+ - Simplex Noise
### Noise Segmentation
Now that we have introduced coherent noise, we can provide a better visual example of noise
-[segmentation](#segmentation). Let's use the following list of colors and distribute them across a noise function
+[segmentation](#segmentation). Let's use the following list of colors and distribute them according to a noise sampler
via segmentation:
```yaml
@@ -345,8 +350,8 @@ colors:
- Blue
```
- Since we know that [noise outputs will generally be between -1 and 1](#demonstration), we will need to assign each
- color its own a range *within* the output range `[-1, 1]`. To do this, it's helpful to visualize things on a number
+ Since we know that [noise sampler outputs will generally be between -1 and 1](#demonstration), we will need to assign
+ each color its own a range *within* the output range `[-1, 1]`. To do this, it's helpful to visualize things on a number
line like so:
@@ -359,7 +364,7 @@ segment some *simplex noise* by categorizing the output values into our colors b
This is where the usefulness of segmentation comes in - *we can treat these colors as anything*, whether that is a set
-of biomes, a pattern of blocks, or anything else that requires a list and a noise function. For example, `red` could
+of biomes, a pattern of blocks, or anything else that requires a list and a sampler. For example, `red` could
represent a tropical island biome, `yellow` a beach, `green` shallow ocean, and `blue` deep ocean. Generally lists like
this will be defined as a [weighted pool](./Weighted-Pools) such that you can easily weigh certain items to take up more
space as needed. As an example, here is what our new biome list may look like:
@@ -372,38 +377,59 @@ biomes:
- DEEP_OCEAN: 1
```
-# Manipulating Noise
+### Generalizing the Sampler
+
+So far, we have defined the concept of a '*noise* sampler' as something that takes numerical inputs and a seed, and
+produces a numerical output dubbed 'noise'. We can make a more generalized definition of a **sampler** that encapsulates
+noise samplers:
+
+**A sampler is a function that takes a [seed](#seeds) and [dimensional coordinates](#multidimensional-sampling), and
+outputs a numerical value.**
-Now that we have covered some essential topics regarding noise, let's talk about creating, configuring, stretching,
-squishing, tweaking, and remixing it!
+In a practical sense, samplers provide a way of mapping a set of world coordinates in any given world (based on the
+seed) to a set of numerical values.
+
+###### CATEGORIZATION OF SAMPLERS
+
+- Samplers
+ - Noise Samplers
+ - Random Noise Samplers
+ - White Noise
+ - Coherent Noise Samplers
+ - Simplex Noise
+
+# Configuring Samplers
+
+Now that we have covered some essential topics regarding samplers and noise, let's talk about creating, configuring,
+stretching, squishing, tweaking, and remixing it!
-## Noise Configs
+## Sampler Configs
-So how exactly does this information translate to actually configuring noise in Terra? This is where we will introduce
-**noise configs**. When configuring [config packs](./Config-Packs) many options will require a noise config, which is
-written in YAML just like most other areas of pack development. The simplest noise config just requires a `type`, which
-defines the noise function for use in the context of a noise config definition.
+So how exactly does this information apply to Terra configuration? This is where we will introduce
+**sampler configs**. When configuring [config packs](./Config-Packs) many options will require a sampler config - which is
+written in YAML just like most other areas of pack development. The simplest sampler config just requires a `type`, which
+defines what kind of sampler to use.
Here what that would look like:
```yaml
-type:
+type:
```
-We can bring back our *white noise* function from earlier, which has type `WhiteNoise`, and insert it into the template
-above, giving us the following noise config:
+We can bring back our *white noise* sampler from earlier, which has type `WhiteNoise`, and insert it into the template
+above, giving us the following sampler config:
```yaml
type: WhiteNoise
```
-###### NOISE CONFIG PARAMETERS
+###### SAMPLER PARAMETERS
-In addition to specifying the noise function to use, the `type` key will also determine what other keys become available
-as either *required* or *optional* when defining a noise config. Some `type`s will have additional keys that need to be
-specified to function properly, and others like `WhiteNoise` don't require anything extra.
+In addition to specifying the type of sampler to use, the `type` key will also determine what other keys become available
+as either *required* or *optional* within the sampler config. Some `type`s will have additional keys that need to be
+specified to function properly, while others like `WhiteNoise` don't require anything extra.
One example of an *optional* key available when specifying the `WhiteNoise` type is `salt`. The function of salt is
covered in [Seeds](#seeds) if you need a refresher. Here is what the above example looks like with the `salt` key added:
@@ -414,35 +440,35 @@ salt: 2321
```
Another thing to note is that most optional parameters have a pre-defined default value that's set when not specified.
-When the `salt` key is not included in a noise config, it will default to its predefined value `0`.
+When the `salt` key is not included in a sampler config, it will default to its predefined value `0`.
### Noise Tool
-Now that we know how to write a simple noise config, we can use a handy program aptly named the **Noise Tool** to
+Now that we know how to write a simple sampler config, we can use a handy program aptly named the **Noise Tool** to
preview what our config looks like.
-The Noise Tool was specially designed for creating, previewing, and modifying noise configs, and is also what was used
+The Noise Tool was specially designed for creating, previewing, and modifying sampler configs, and is also what was used
to generate every image of noise used on this page. You can find the Noise Tool on GitHub -
[`Source`](https://github.com/PolyhedralDev/NoiseTool) [`Download`](https://github.com/PolyhedralDev/NoiseTool/releases)
###### TIP
> We suggest that you follow along the rest of this section with the Noise Tool, so you can try out parameters get the
-> hang of writing your own noise configs. Playing around and experimenting on your own is a great way of learning what
+> hang of writing your own sampler configs. Playing around and experimenting on your own is a great way of learning what
> each parameter does, and will give you an intuition on how you can fine tune them to your advantage.
-For a complete list of noise function `type`s and their parameters available in Terra, please refer to the
+For a complete list of sampler `type`s and their parameters available in Terra, please refer to the
[Noise Configuration](./Noise-Options) documentation.
### Frequency
-You might be wondering how we control just how large or how small details produced by noise functions are - This is
-where the concept of **frequency** comes in. Frequency is a number that modifies the scale of noise, where higher
-frequency produces more 'zoomed out' noise, while lower frequency results in more 'zoomed in' noise.
+You might be wondering how we control just how large or how small details produced by samplers are - This is
+where the concept of **frequency** comes in. Frequency is a number that modifies the 'scale' of sampler outputs, where
+higher frequency produces more 'zoomed out' outputs, while lower frequency results in more 'zoomed in' outputs.
-Let's preview some comparisons of the same noise function with varying frequencies:
+Let's preview some comparisons of a simplex noise sampler with varying frequencies:
`2x Frequency | 1x Frequency | 0.5x frequency`
@@ -466,31 +492,31 @@ As a general rule of thumb:
* Produces *larger* & *more spread out* details.
* Decreases the density of 'points' per unit of space.
-###### IN A NOISE CONFIG
+###### IN A SAMPLER CONFIG
Frequency can be defined for applicable `types`s via the `frequency` key like so:
```yaml
-type:
+type:
frequency:
```
-Something to note is that tweaking frequency is only really useful for functions in the
-[coherent noise](#coherent-noise) category. You're able to modify the frequency of random noise based functions, however
-they don't have the property of being able to scale like coherent noise functions do. There isn't much reason to scale
-the frequency of a random noise function, as doing so functionally has same effect as changing the seed.
+Something to note is that tweaking frequency is only really useful for samplers in the
+[coherent noise](#coherent-noise) category. You're able to modify the frequency of random noise based samplers, however
+they don't have the property of being able to scale like coherent noise samplers do. There isn't much reason to scale
+the frequency of a random noise sampler, as doing so functionally has same effect as changing the seed.
Under The Hood - How frequency works
-The driving math behind frequencies is very simple: *multiply the input coordinates of a noise function by the
+The driving math behind frequency is very simple: *multiply the input coordinates of a sampler by the
frequency*. Here is a model of the process:
```none
-┌──────────────────┐ ┌────────────────┐ ┌───────────────────┐
-│ Input parameters │ ╭──────┬ → > Noise Function > → │ Randomized output │
-├──────────────────┤ │ │ └────────────────┘ └───────────────────┘
+┌──────────────────┐ ┌─────────┐ ┌────────┐
+│ Input parameters │ ╭──────┬ → > Sampler > → │ Output │
+├──────────────────┤ │ │ └─────────┘ └────────┘
│ - Seed > ─────────╯ │
│ - Frequency > ─────────╮ │
| - Input 1 (X) > → X * Frequency ┤
@@ -500,7 +526,7 @@ frequency*. Here is a model of the process:
For example, if we have a frequency of `2`, and want to sample the coordinates `(X = 3, Z = 2)`, first the coordinates
will be multiplied by the frequency `2`, giving us the scaled coordinates `(X' = 6, Z' = 4)`. This new set of
-coordinates will then be input into the noise function which will then give us the final output value.
+coordinates will then be input into the sampler which will then give us the final output value.
> Based on this logic, we can deduct that the input:
>
@@ -513,13 +539,16 @@ coordinates will then be input into the noise function which will then give us t
Higher frequencies effectively produce *faster changes* when incrementing input coordinates, which is why higher
frequencies make details closer and therefore smaller.
+This concept in geometry is known simply as [scaling](https://en.wikipedia.org/wiki/Scaling_(geometry)), and can also be
+thought of as applying a scale transformation to the coordinate space of the world before passing it into the sampler.
+
### In Context
-To get a better idea of how noise configs get used in packs, Here is what one looks like in the context of a
-[palette configuration](./Palette-Configuration). The noise config is highlighted in green, and the key it's defined
-under is highlighted in yellow.
+To get a better idea of how sampler configs get used in packs, Here is what one looks like in the context of a
+[palette configuration](./Palette-Configuration). The sampler config is highlighted in green, and the key it's defined
+under is highlighted in orange.
```diff
id: DIRTY_GRASS
@@ -540,32 +569,32 @@ layers:
materials: "minecraft:stone"
```
-The usage of noise here controls the arrangement of the [weighted pool](./Weighted-Pools) of materials highlighted in
-red. To get a better idea of the relationship, here is a screenshot of a biome which uses the above palette
+The usage of noise here controls the arrangement of the [weighted pool](./Weighted-Pools) of materials (highlighted in
+red). To get a better idea of the relationship, here is a screenshot of a biome which uses the above palette
configuration:
This is also another great example of [noise segmentation](#noise-segmentation) in action with weighted pools. You can
-see our `OpenSimplex2` function has been segmented equally between grass blocks and dirt, giving us a nice random
+see our `OpenSimplex2` sampler has been segmented equally between grass blocks and dirt, giving us a nice random
pattern of surface blocks in the biome.
-### Fractal Noise
+### Fractalization
In some situations, [coherent noise](#coherent-noise) on its own may be far too smooth and uniform to produce
'*realistic*' results. Looking at the images above, you may notice plain simplex is quite *blobby*, which may not be
-desired for applications where more detail is required. This is where **fractal noise** comes in.
+desired for applications where more detail is required. This is where **fractalizers** come in handy.
-The basic premise of fractal noise that we can produce more detail by stacking multiple of the same noise function on
-top of each other, where each successive function (called an **octave**) has a higher [frequency](#frequency) and a
-scaled down output value (making it contribute less to the overall noise). This process of progressively stacking
-incrementally smaller noise layers to produce a [fractal](https://en.wikipedia.org/wiki/Fractal) effect is referred to
+The premise of fractalization is that we can produce more detail by combining the outputs of multiple of the same sampler
+together, where each successive sampler (called an **octave**) has a higher [frequency](#frequency) and a scaled down
+output value (making it contribute less to the final overall output). This process of progressively stacking
+incrementally smaller layers to produce a [fractal](https://en.wikipedia.org/wiki/Fractal) effect is referred to
as [fractal Brownian motion](https://en.wikipedia.org/wiki/Fractional_Brownian_motion) (Commonly abbreviated as fBm).
It might sound quite complicated in writing, so we can demonstrate this concept visually to get a better idea of what's
happening:
-`1 Octave (Regular Noise) | 2 Octaves | 3 Octaves | 4 Octaves`
+`1 Octave (No fractalization) | 2 Octaves | 3 Octaves | 4 Octaves`
@@ -575,25 +604,25 @@ happening:
-As you can see, the more octaves we add, the more detailed the noise gets. This is the main application of fractal
-noise - to produce more detail, especially at lower frequencies where detail is sparse. You won't have to worry about
-the exact math behind how each octave gets stacked, as Terra will handle all of that for you.
+As you can see, the more octaves we add, the more detailed the noise gets. This is the main application of
+fractalization - to produce more detail, especially at lower frequencies where detail is sparse. You won't have to worry
+about the exact math behind how each octave gets stacked, as Terra will handle all of that for you.
-###### IN A NOISE CONFIG
+###### IN A SAMPLER CONFIG
-When fractalizing noise configs, we define the fractalizer as *its own noise config*, which takes *another noise config*
-as an input. The syntax for this is as followed:
+When fractalizing sampler configs, we define the fractalizer as *its own sampler config*, which takes *the target sampler
+config* as a parameter. The syntax for this is as follows:
```yaml
type:
function:
- type: ... # Noise config to be fractalized
+ type: ... # Sampler config to be fractalized
```
-As you can see, we have the main noise config for our fractalizer, and a second noise config *nested* inside under the
-`function` key. The `function` key is the only **required** parameter for all fractalizers.
+As you can see, we have a fractalizer as the 'top level' sampler config, and a second sampler config *nested* inside
+under the `function` key. The `function` key is the only **required** parameter for all fractalizers.
-Based on this template, we can create a real noise config. Let's use the `fBm` fractalizer, with an input function with
+We can create a real sampler config based on this template - Let's use the `fBm` fractalizer, with an input sampler of
`type` `OpenSimplex2`:
```yaml
@@ -602,7 +631,7 @@ function:
type: OpenSimplex2
```
-Pretty simple, all we've done is passed some *simplex noise* into the *fBm* function. Fractalizers have a couple
+Pretty simple, all we've done is passed some *simplex noise* into the *fBm* sampler. Fractalizers have a couple
additional parameters, including `octaves`, `lacunarity`, and `gain`. Here is another example config with those
parameters already defined:
@@ -615,49 +644,48 @@ lacunarity: 2
gain: 0.75
```
-Feel free to preview this config in the [Noise Tool](#noise-tool), and have an experiment with each parameter to see
-what they all do. To see all available fractalizers and their parameters, please refer to the
+Feel free to preview this sampler config in the [Noise Tool](#noise-tool), and have an experiment with each parameter to
+see what they all do. To see all available fractalizers and their parameters, please refer to the
[Noise Configuration](./Noise-Options) documentation.
### Domain Warping
-Similar to fractal noise, domain warping involves manipulating the input *aka the **domain***, before it's passed to the
-noise function. More specifically, the domain of a noise function will be warped via translation by the output of a
-secondary warping function.
+Similar to fractalization, domain warping involves manipulating the input coordinates *aka the **domain***, before it's
+passed into the sampler. More specifically, the domain of a sampler will be warped via translation by the output of a
+secondary warping sampler.
-To demonstrate domain warping more clearly, let's take a 64 x 64 square of samples in a space. Our function *to be
-warped* will be a checkerboard pattern, and our *warping function* will be some basic simplex noise.
+To demonstrate domain warping more clearly, let's take a 64 x 64 square of samples in a space. Our sampler *to be
+warped* will be a checkerboard pattern, and our *warping sampler* will be some basic simplex noise.
-
-When domain warping the checker board function by the simplex we get the following result:
+When domain warping the checkerboard sampler by the simplex sampler we get the following result:
-As you can see, our once perfectly square boxes have been contorted out of shape by the warp function.
+As you can see, our once perfectly square boxes have been contorted out of shape by the warp sampler.
-###### IN A NOISE CONFIG
+###### IN A SAMPLER CONFIG
-To use domain warping, we will need to set the `type` to `DomainWarp`, and specify two additional required keys
-`function` and `warp`. As you may have already guessed, both `function` and `warp` need to be set to a noise config,
-similar to how [fractalizers](#fractal-noise) accept an input function:
+To use domain warping, we will need to set the sampler `type` to `DomainWarp`, and specify two additional required keys
+`function` and `warp`. As you may have already guessed, both `function` and `warp` need to be set to sampler configs,
+similar to how [fractalizers](#fractalization) take a sampler as a parameter:
```yaml
type: DomainWarp
function:
- type: ... # Noise config to be warped
+ type: ... # Sampler config to be warped
warp:
- type: ... # Warp noise config
+ type: ... # Sampler config that warps
```
-Additionally, we can specify `amplitude` which determines how much the function defined in `function` will be warped by
-the `warp` function. Here is an example of a real noise config which warps low frequency simplex with another simplex
-function:
+Additionally, we can specify `amplitude` which determines how much the sampler defined in `function` will be warped by
+the `warp` sampler. Here is an example of a real sampler config which warps low frequency simplex with another simplex
+sampler:
```yaml
type: DomainWarp
@@ -669,8 +697,8 @@ warp:
amplitude: 20
```
-Again it's recommended that you try out this noise config in the [Noise Tool](#noise-tool) and see what changing each
-parameter does - What happens if you use `WhiteNoise` as a warp function instead?
+Again it's recommended that you try out this sampler config in the [Noise Tool](#noise-tool) and see what changing each
+parameter does - What happens if you use `WhiteNoise` as a warp sampler instead?
@@ -678,32 +706,36 @@ parameter does - What happens if you use `WhiteNoise` as a warp function instead
To get an in depth understanding of what's happening, let's explain the formula that is used to achieve domain warping:
>
-> * We will define `noise(coordinate)` as our function to be warped, where `coordinate` represents the input values
+> * We will define `sampler(domain)` as our sampler to be warped, where `domain` represents the input values
> (such as the familiar `X` and `Z` coordinates).
>
-> * To *translate* `noise`, we can simply add some translation to the input: `noise(coordinate + translation)`.
+> * To *translate* `sampler()`, we can simply add some translation to the input: `sampler(domain + translation)`.
> Translating simply means moving left / right / up / down / etc.
>
-> * We can then define `warp_noise(coordinate)` as our warping function.
+> * We can then define `warp_sampler(domain)` as our warping sampler.
>
-> * If we make `translation` our `warp_noise` function then now the `coordinate` of `noise` will be translated by
-> `warp_noise` like so:
+> * If we replace `translation` with our `warp_sampler`, the `domain` of `sampler` will instead be translated by
+> `warp_sampler` like so:
>
-> `noise(coordinate + warp_noise(coordinate))`
+> `sampler(domain + warp_sampler(domain))`
>
-> * Finally, we can multiply the output of `warp_noise` by a value `amplitude`, which will control how 'strong' the
-> warping will be, to give us the final formula:
+> * Finally, we can multiply the output of `warp_sampler` by a value `amplitude`, which will control how 'strong' the
+> translation produced by `warp_sampler` will be, which gives us the final formula:
+>
+> `sampler(domain + warp_sampler(domain) * amplitude)`
>
-> `noise(coordinate + warp_noise(coordinate) * amplitude)`
+> A detail to note is that there will typically be several copies of `warp_sampler` for each coordinate for the domain,
+> where each copy is just salted differently. Without this, each coordinate would be warped by the same value, resulting
+> in translating each axis equally, resulting in anisotropy.
-### Chained Functions
+### Sampler Composition
-Because some keys such as `function` and `warp` accept a noise config, something we can do is *feed a
-[domain warp](#domain-warping) function into another domain warp function*. In fact, we could feed **any** noise
-function into any other one, given it has a parameter that accepts a noise config. This is incredibly powerful, as it
-allows for constructing complex highly configurable systems of noise. Here is an example where we domain warp some
+Because some keys such as `function` and `warp` accept any sampler config, something we can do is *feed a
+[domain warp](#domain-warping) sampler into another domain warp sampler*. In fact, we could feed **any** sampler into
+any other one, given it has a parameter that accepts a sampler. This is incredibly powerful, as it allows for
+constructing complex highly configurable systems of samplers. Here is an example where we domain warp some
[fractalized](#fractal-noise) simplex by more fractalized simplex (which has also been domain warped by more...
fractalized simplex!):
@@ -736,8 +768,8 @@ warp:
# Conclusion
-Now that you've got an idea of [what noise is](#what-is-noise), [how it works](#noise-basics), and a couple ways of
-[manipulating it](#manipulating-noise), you should now be equipped with the necessary knowledge to start configuring
-your own fancy noise functions for use in your own customized world generation! For more information on the available
-noise functions in Terra, please refer to the [Noise Configuration](./Noise-Options) documentation. If you have any
+Now that you've got an idea of [what noise is](#what-is-noise), [how it works](#noise-basics), and the basics of
+[configuring it](#configuring-samplers), you should now be equipped with the necessary knowledge to start configuring
+your own fancy samplers for use in your own customized world generation! For more information on the available
+samplers in Terra, please refer to the [Noise Configuration](./Noise-Options) documentation. If you have any
further questions, feel free to ask us in our [Discord](https://discord.gg/PXUEbbF)!