The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .clang-format
├── .github
    ├── FUNDING.yml
    └── workflows
    │   ├── deploy-web-preview-app.yml
    │   ├── publish-js.yml
    │   └── publish-rust.yml
├── .gitignore
├── C
    ├── FastNoiseLite.h
    └── README.md
├── CSharp
    ├── FastNoiseLite.cs
    └── README.md
├── Cpp
    ├── FastNoiseLite.h
    └── README.md
├── Fortran
    ├── README.md
    └── fast_noise_lite.f90
├── GLSL
    ├── FastNoiseLite.glsl
    └── README.md
├── GML
    ├── FastNoiseLite.gml
    └── FastNoiseLite.yymps
├── Go
    ├── README.md
    └── fastnoise.go
├── HLSL
    ├── FastNoiseLite.hlsl
    └── README.md
├── Haxe
    ├── FastNoiseLite.hx
    └── README.md
├── Java
    ├── FastNoiseLite.java
    └── README.md
├── JavaScript
    ├── FastNoiseLite.js
    ├── README.md
    └── package.json
├── LICENSE
├── Odin
    ├── FastNoiseLite.odin
    └── README.md
├── Pascal
    ├── README.md
    └── fastnoiselite.pas
├── PowerShell
    ├── PSFastNoiseLite.ps1
    └── README.md
├── README.md
├── Rust
    ├── Cargo.lock
    ├── Cargo.toml
    ├── README.md
    └── src
    │   └── lib.rs
├── WebPreviewApp
    ├── CMakeLists.txt
    ├── build.ps1
    └── main.cpp
├── Zig
    ├── README.md
    └── fastnoise.zig
└── go.mod


/.clang-format:
--------------------------------------------------------------------------------
 1 | ---
 2 | Language: Cpp
 3 | BasedOnStyle: LLVM
 4 | AccessModifierOffset: -4
 5 | AlignOperands: false
 6 | AlignTrailingComments: false
 7 | AlwaysBreakTemplateDeclarations: Yes
 8 | PointerAlignment: Left
 9 | BraceWrapping: 
10 |   AfterCaseLabel: true
11 |   AfterClass: true
12 |   AfterControlStatement: true
13 |   AfterEnum: true
14 |   AfterFunction: true
15 |   AfterNamespace: true
16 |   AfterStruct: true
17 |   AfterUnion: true
18 |   AfterExternBlock: false
19 |   BeforeCatch: true
20 |   BeforeElse: true
21 |   SplitEmptyFunction: true
22 |   SplitEmptyRecord: true
23 |   SplitEmptyNamespace: true
24 | BreakBeforeBraces: Custom
25 | BreakConstructorInitializers: AfterColon
26 | ColumnLimit: 500
27 | Cpp11BracedListStyle: false
28 | IncludeCategories: 
29 |   - Regex: '^<.*'
30 |     Priority: 1
31 |   - Regex: '^".*'
32 |     Priority: 2
33 |   - Regex: '.*'
34 |     Priority: 3
35 | IncludeIsMainRegex: '([-_](test|unittest))?
#39;
36 | IndentWidth: 4
37 | MaxEmptyLinesToKeep: 2
38 | NamespaceIndentation: All
39 | TabWidth: 4
40 | ...
41 | 


--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
 1 | # These are supported funding model platforms
 2 | 
 3 | github: Auburn
 4 | patreon: # Replace with a single Patreon username
 5 | open_collective: # Replace with a single Open Collective username
 6 | ko_fi: # Replace with a single Ko-fi username
 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
 9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 | 


--------------------------------------------------------------------------------
/.github/workflows/deploy-web-preview-app.yml:
--------------------------------------------------------------------------------
 1 | name: Update WebPreviewApp
 2 | 
 3 | on:
 4 |   # Runs on pushes targeting the default branch
 5 |   push:
 6 |     branches:  
 7 |       - master
 8 |     paths:
 9 |       - 'WebPreviewApp/**'
10 |       - 'Cpp/**'
11 | 
12 |   # Allows you to run this workflow manually from the Actions tab
13 |   workflow_dispatch:
14 | 
15 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
16 | permissions:
17 |   contents: read
18 |   pages: write
19 |   id-token: write
20 | 
21 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
22 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
23 | concurrency:
24 |   group: "pages"
25 |   cancel-in-progress: false
26 | 
27 | jobs:
28 |   # Single deploy job since we're just deploying
29 |   deploy:
30 |     environment:
31 |       name: github-pages
32 |       url: ${{ steps.deployment.outputs.page_url }}
33 |     runs-on: windows-latest
34 |     steps:
35 |       - name: Checkout
36 |         uses: actions/checkout@v3
37 | 
38 |       - name: Build WebPreviewApp
39 |         run: './build.ps1'
40 |         working-directory: './WebPreviewApp'
41 |         shell: powershell
42 | 
43 |       - name: Create Pages Directory
44 |         run: 'New-Item pagesbuild -ItemType Directory'
45 |         shell: powershell
46 | 
47 |       - name: Copy WebPreviewApp HTML
48 |         run: 'Copy-Item ./WebPreviewApp/build/FastNoiseLitePreview.html -Destination ./pagesbuild/index.html'
49 |         shell: powershell
50 | 
51 |       - name: Setup Pages
52 |         uses: actions/configure-pages@v3
53 |       - name: Upload artifact
54 |         uses: actions/upload-pages-artifact@v2
55 |         with:
56 |           # Upload pagesbuild dir
57 |           path: './pagesbuild'
58 |       - name: Deploy to GitHub Pages
59 |         id: deployment
60 |         uses: actions/deploy-pages@v2
61 | 
62 | 


--------------------------------------------------------------------------------
/.github/workflows/publish-js.yml:
--------------------------------------------------------------------------------
 1 | on:
 2 |   push:
 3 |     branches:
 4 |       - master
 5 |     paths:
 6 |       - 'JavaScript/package.json' # The version number must be bumped in order to publish to npm
 7 |       
 8 |   # Allows you to run this workflow manually from the Actions tab
 9 |   workflow_dispatch:
10 | 
11 | name: Publish to npm
12 | 
13 | jobs:
14 |   publish:
15 |     name: Publish
16 |     runs-on: ubuntu-latest
17 |     steps:
18 |       - name: Checkout sources
19 |         uses: actions/checkout@v4
20 | 
21 |       - name: Set up Node.js
22 |         uses: actions/setup-node@v3
23 |         with:
24 |           node-version: '20.x'
25 |           registry-url: 'https://registry.npmjs.org'
26 | 
27 |       - name: Publish to npm
28 |         run: cd JavaScript && npm publish
29 |         env:
30 |           NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
31 | 


--------------------------------------------------------------------------------
/.github/workflows/publish-rust.yml:
--------------------------------------------------------------------------------
 1 | on:
 2 |   push:
 3 |     branches:
 4 |       - master
 5 |     paths:
 6 |       - 'Rust/Cargo.toml' # The version number must be bumped in order to publish to crates.io
 7 | 
 8 |   # Allows you to run this workflow manually from the Actions tab
 9 |   workflow_dispatch:
10 |   
11 | name: Publish Rust (crates.io)
12 | 
13 | jobs:
14 |   publish:
15 |     name: Publish to crates.io
16 |     runs-on: ubuntu-latest
17 |     steps:
18 |       - name: Checkout repo
19 |         uses: actions/checkout@v4
20 | 
21 |       - name: Publish to crates.io
22 |         run: cd Rust && cargo publish
23 |         env:
24 |           CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
25 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
 1 | *.swp
 2 | *.*~
 3 | project.lock.json
 4 | .DS_Store
 5 | *.pyc
 6 | nupkg/
 7 | 
 8 | # Visual Studio Code
 9 | .vscode
10 | 
11 | # Rider
12 | .idea
13 | 
14 | # User-specific files
15 | *.suo
16 | *.user
17 | *.userosscache
18 | *.sln.docstates
19 | 
20 | # Build results
21 | [Dd]ebug/
22 | [Dd]ebugPublic/
23 | [Rr]elease/
24 | [Rr]eleases/
25 | [Pp]ublish/
26 | [Tt]arget/
27 | x64/
28 | x86/
29 | build/
30 | bld/
31 | [Bb]in/
32 | [Oo]bj/
33 | [Oo]ut/
34 | msbuild.log
35 | msbuild.err
36 | msbuild.wrn
37 | 
38 | # Visual Studio 2015
39 | .vs/
40 | 
41 | # JS stuff
42 | node_modules
43 | 
44 | emsdk


--------------------------------------------------------------------------------
/C/README.md:
--------------------------------------------------------------------------------
 1 | Add `#define FNL_IMPL` before including `FastNoiseLite.h` in exactly one source file, or you will get linker errors
 2 | 
 3 | ## Getting Started
 4 | 
 5 | Here's an example for creating a 128x128 array of OpenSimplex2 noise
 6 | 
 7 | ```c
 8 | // Create and configure noise state
 9 | fnl_state noise = fnlCreateState();
10 | noise.noise_type = FNL_NOISE_OPENSIMPLEX2;
11 | 
12 | // Gather noise data
13 | float* noiseData = malloc(128 * 128 * sizeof(float));
14 | int index = 0;
15 | 
16 | for (int y = 0; y < 128; y++)
17 | {
18 |     for (int x = 0; x < 128; x++) 
19 |     {
20 |         noiseData[index++] = fnlGetNoise2D(&noise, x, y);
21 |     }
22 | }
23 | 
24 | // Do something with this data...
25 | 
26 | // Free data later
27 | free(noiseData);
28 | ```
29 | 


--------------------------------------------------------------------------------
/CSharp/README.md:
--------------------------------------------------------------------------------
 1 | ## Getting Started
 2 | 
 3 | Here's an example for creating a 128x128 array of OpenSimplex2 noise
 4 | 
 5 | ```csharp
 6 | // Create and configure FastNoise object
 7 | FastNoiseLite noise = new FastNoiseLite();
 8 | noise.SetNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
 9 | 
10 | // Gather noise data
11 | float[,] noiseData = new float[128, 128];
12 | 
13 | for (int x = 0; x < 128; x++)
14 | {
15 |     for (int y = 0; y < 128; y++)
16 |     {
17 |         noiseData[x, y] = noise.GetNoise(x, y);
18 |     }
19 | }
20 | 
21 | 
22 | // Do something with this data...
23 | ```


--------------------------------------------------------------------------------
/Cpp/README.md:
--------------------------------------------------------------------------------
 1 | ## Getting Started
 2 | 
 3 | Here's an example for creating a 128x128 array of OpenSimplex2 noise
 4 | 
 5 | ```cpp
 6 | // Create and configure FastNoise object
 7 | FastNoiseLite noise;
 8 | noise.SetNoiseType(FastNoiseLite::NoiseType_OpenSimplex2);
 9 | 
10 | // Gather noise data
11 | std::vector<float> noiseData(128 * 128);
12 | int index = 0;
13 | 
14 | for (int y = 0; y < 128; y++)
15 | {
16 |     for (int x = 0; x < 128; x++)
17 |     {
18 |         noiseData[index++] = noise.GetNoise((float)x, (float)y);
19 |     }
20 | }
21 | 
22 | // Do something with this data...
23 | ```
24 | 


--------------------------------------------------------------------------------
/Fortran/README.md:
--------------------------------------------------------------------------------
 1 | ## Getting Started
 2 | 
 3 | Here's an example for creating a 128x128 array of OpenSimplex2S noise
 4 | 
 5 | ```Fortran
 6 | program test_fast_noise
 7 |   use :: fast_noise_lite
 8 |   use, intrinsic :: iso_c_binding
 9 |   implicit none
10 | 
11 |   type(fnl_state) :: noise_state
12 |   real(c_float), dimension(128,128) :: noise_data
13 |   integer(c_int) :: x, y
14 | 
15 |   ! Create the state.
16 |   noise_state = fnl_state()
17 |   noise_state%noise_type = FNL_NOISE_OPENSIMPLEX2S
18 | 
19 |   ! Collect the noise data.
20 |   do y = 1,128
21 |     do x = 1,128
22 |       noise_data(x,y) = fnl_get_noise_2d(noise_state, real(x, c_float), real(y, c_float))
23 |     end do
24 |   end do
25 | 
26 |   ! Do something with this data...
27 | end program test_fast_noise
28 | ```


--------------------------------------------------------------------------------
/GLSL/README.md:
--------------------------------------------------------------------------------
 1 | ## Getting Started
 2 | 
 3 | Here's an example for creating a 128x128 array of OpenSimplex2 noise
 4 | 
 5 | ```glsl
 6 | // Create and configure noise state
 7 | fnl_state noise = fnlCreateState();
 8 | noise.noise_type = FNL_NOISE_OPENSIMPLEX2;
 9 | 
10 | // Gather noise data
11 | float noiseData[128 * 128];
12 | int index = 0;
13 | 
14 | for (int y = 0; y < 128; y++)
15 | {
16 |     for (int x = 0; x < 128; x++) 
17 |     {
18 |         noiseData[index++] = fnlGetNoise2D(noise, x, y);
19 |     }
20 | }
21 | 
22 | // Do something with this data...
23 | ```
24 | 
25 | ## ShaderToy Demo
26 | https://www.shadertoy.com/view/sttBz8
27 | 


--------------------------------------------------------------------------------
/GML/FastNoiseLite.yymps:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Auburn/FastNoiseLite/582f7cf21065a48ee1c3cf62048831bbaa4581c5/GML/FastNoiseLite.yymps


--------------------------------------------------------------------------------
/Go/README.md:
--------------------------------------------------------------------------------
 1 | ## Getting Started
 2 | 
 3 | Here's an example for creating a 128x128 array of OpenSimplex2 noise
 4 | 
 5 | ```go
 6 | import "fastnoise"
 7 | 
 8 | // Create and configure noise state (either float32 or float64)
 9 | var noise = fastnoise.New[float32]()
10 | noise.NoiseType(fastnoise.OpenSimplex2)
11 | 
12 | // Gather noise data
13 | var noiseData [128][128]float32
14 | 
15 | for x := 0; x < 128; x++ {
16 | 	for y := 0; y < 128; y++ {
17 | 		noiseData[x][y] = noise.Noise2D(x, y)
18 | 	}
19 | }
20 | 
21 | // Do something with this data...
22 | ```
23 | 


--------------------------------------------------------------------------------
/Go/fastnoise.go:
--------------------------------------------------------------------------------
   1 | // MIT License
   2 | //
   3 | // Copyright(c) 2023 Jordan Peck (jordan.me2@gmail.com)
   4 | // Copyright(c) 2023 Contributors
   5 | //
   6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
   7 | // of this software and associated documentation files(the "Software"), to deal
   8 | // in the Software without restriction, including without limitation the rights
   9 | // to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
  10 | // copies of the Software, and to permit persons to whom the Software is
  11 | // furnished to do so, subject to the following conditions :
  12 | //
  13 | // The above copyright notice and this permission notice shall be included in all
  14 | // copies or substantial portions of the Software.
  15 | //
  16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
  19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22 | // SOFTWARE.
  23 | //
  24 | // .'',;:cldxkO00KKXXNNWWWNNXKOkxdollcc::::::;:::ccllloooolllllllllooollc:,'...        ...........',;cldxkO000Okxdlc::;;;,,;;;::cclllllll
  25 | // ..',;:ldxO0KXXNNNNNNNNXXK0kxdolcc::::::;;;,,,,,,;;;;;;;;;;:::cclllllc:;'....       ...........',;:ldxO0KXXXK0Okxdolc::;;;;::cllodddddo
  26 | // ...',:loxO0KXNNNNNXXKK0Okxdolc::;::::::::;;;,,'''''.....''',;:clllllc:;,'............''''''''',;:loxO0KXNNNNNXK0Okxdollccccllodxxxxxxd
  27 | // ....';:ldkO0KXXXKK00Okxdolcc:;;;;;::cclllcc:;;,''..... ....',;clooddolcc:;;;;,,;;;;;::::;;;;;;:cloxk0KXNWWWWWWNXKK0Okxddoooddxxkkkkkxx
  28 | // .....';:ldxkOOOOOkxxdolcc:;;;,,,;;:cllooooolcc:;'...      ..,:codxkkkxddooollloooooooollcc:::::clodkO0KXNWWWWWWNNXK00Okxxxxxxxxkkkkxxx
  29 | // . ....';:cloddddo___________,,,,;;:clooddddoolc:,...      ..,:ldx__00OOOkkk___kkkkkkxxdollc::::cclodkO0KXXNNNNNNXXK0OOkxxxxxxxxxxxxddd
  30 | // .......',;:cccc:|           |,,,;;:cclooddddoll:;'..     ..';cox|  \KKK000|   |KK00OOkxdocc___;::clldxxkO0KKKKK00Okkxdddddddddddddddoo
  31 | // .......'',,,,,''|   ________|',,;;::cclloooooolc:;'......___:ldk|   \KK000|   |XKKK0Okxolc|   |;;::cclodxxkkkkxxdoolllcclllooodddooooo
  32 | // ''......''''....|   |  ....'',,,,;;;::cclloooollc:;,''.'|   |oxk|    \OOO0|   |KKK00Oxdoll|___|;;;;;::ccllllllcc::;;,,;;;:cclloooooooo
  33 | // ;;,''.......... |   |_____',,;;;____:___cllo________.___|   |___|     \xkk|   |KK_______ool___:::;________;;;_______...'',;;:ccclllloo
  34 | // c:;,''......... |         |:::/     '   |lo/        |           |      \dx|   |0/       \d|   |cc/        |'/       \......',,;;:ccllo
  35 | // ol:;,'..........|    _____|ll/    __    |o/   ______|____    ___|   |   \o|   |/   ___   \|   |o/   ______|/   ___   \ .......'',;:clo
  36 | // dlc;,...........|   |::clooo|    /  |   |x\___   \KXKKK0|   |dol|   |\   \|   |   |   |   |   |d\___   \..|   |  /   /       ....',:cl
  37 | // xoc;'...  .....'|   |llodddd|    \__|   |_____\   \KKK0O|   |lc:|   |'\       |   |___|   |   |_____\   \.|   |_/___/...      ...',;:c
  38 | // dlc;'... ....',;|   |oddddddo\          |          |Okkx|   |::;|   |..\      |\         /|   |          | \         |...    ....',;:c
  39 | // ol:,'.......',:c|___|xxxddollc\_____,___|_________/ddoll|___|,,,|___|...\_____|:\ ______/l|___|_________/...\________|'........',;::cc
  40 | // c:;'.......';:codxxkkkkxxolc::;::clodxkOO0OOkkxdollc::;;,,''''',,,,''''''''''',,'''''',;:loxkkOOkxol:;,'''',,;:ccllcc:;,'''''',;::ccll
  41 | // ;,'.......',:codxkOO0OOkxdlc:;,,;;:cldxxkkxxdolc:;;,,''.....'',;;:::;;,,,'''''........,;cldkO0KK0Okdoc::;;::cloodddoolc:;;;;;::ccllooo
  42 | // .........',;:lodxOO0000Okdoc:,,',,;:clloddoolc:;,''.......'',;:clooollc:;;,,''.......',:ldkOKXNNXX0Oxdolllloddxxxxxxdolccccccllooodddd
  43 | // .    .....';:cldxkO0000Okxol:;,''',,;::cccc:;,,'.......'',;:cldxxkkxxdolc:;;,'.......';coxOKXNWWWNXKOkxddddxxkkkkkkxdoollllooddxxxxkkk
  44 | //       ....',;:codxkO000OOxdoc:;,''',,,;;;;,''.......',,;:clodkO00000Okxolc::;,,''..',;:ldxOKXNWWWNNK0OkkkkkkkkkkkxxddooooodxxkOOOOO000
  45 | //       ....',;;clodxkkOOOkkdolc:;,,,,,,,,'..........,;:clodxkO0KKXKK0Okxdolcc::;;,,,;;:codkO0XXNNNNXKK0OOOOOkkkkxxdoollloodxkO0KKKXXXXX
  46 | //
  47 | // VERSION: 1.1.1
  48 | // https://github.com/Auburn/FastNoiseLite
  49 | 
  50 | package fastnoise
  51 | 
  52 | import (
  53 | 	"math"
  54 | )
  55 | 
  56 | // Float represents a floating-point number type.
  57 | type Float interface {
  58 | 	float32 | float64
  59 | }
  60 | 
  61 | // Enum types
  62 | type (
  63 | 	// NoiseType describes a noise algorithm.
  64 | 	NoiseType int
  65 | 	// RotationType3D describes a rotation method to apply to 3D noise.
  66 | 	RotationType3D int
  67 | 	// FractalType describes the fractal method for fractal noise types.
  68 | 	FractalType int
  69 | 	// CellularDistanceFunc describes the method for cellular distance functions.
  70 | 	CellularDistanceFunc int
  71 | 	// CellularReturnType describes the return type for cellular distance noise.
  72 | 	CellularReturnType int
  73 | 	// DomainWarpType describes the method used for domain warps.
  74 | 	DomainWarpType int
  75 | )
  76 | 
  77 | const (
  78 | 	OpenSimplex2 NoiseType = iota
  79 | 	OpenSimplex2S
  80 | 	Cellular
  81 | 	Perlin
  82 | 	ValueCubic
  83 | 	Value
  84 | 	TypeCount // The number of noise types
  85 | )
  86 | 
  87 | const (
  88 | 	RotationNone RotationType3D = iota
  89 | 	RotationImproveXYPlanes
  90 | 	RotationImproveXZPlanes
  91 | )
  92 | 
  93 | const (
  94 | 	FractalNone FractalType = iota
  95 | 	FractalFBm
  96 | 	FractalRidged
  97 | 	FractalPingPong
  98 | 	FractalDomainWarpProgressive
  99 | 	FractalDomainWarpIndependent
 100 | )
 101 | 
 102 | const (
 103 | 	CellularDistanceEuclidean CellularDistanceFunc = iota
 104 | 	CellularDistanceEuclideanSq
 105 | 	CellularDistanceManhattan
 106 | 	CellularDistanceHybrid
 107 | )
 108 | 
 109 | const (
 110 | 	CellularReturnCellValue CellularReturnType = iota
 111 | 	CellularReturnDistance
 112 | 	CellularReturnDistance2
 113 | 	CellularReturnDistance2Add
 114 | 	CellularReturnDistance2Sub
 115 | 	CellularReturnDistance2Mul
 116 | 	CellularReturnDistance2Div
 117 | )
 118 | 
 119 | const (
 120 | 	DomainWarpOpenSimplex2 DomainWarpType = iota
 121 | 	DomainWarpOpenSimplex2Reduced
 122 | 	DomainWarpBasicGrid
 123 | )
 124 | 
 125 | type (
 126 | 	// noise2DFunc is a prototype for a function that generates 2D noise.
 127 | 	noise2DFunc[T Float] func(state *State[T], seed int, x, y T) T
 128 | 	// noise3DFunc is a prototype for a function that generates 3D noise.
 129 | 	noise3DFunc[T Float] func(state *State[T], seed int, x, y, z T) T
 130 | )
 131 | 
 132 | // State contains the configuration for generating a noise. This should only be created
 133 | // with NewState, as it will initialize with sane defaults, including any private members.
 134 | //
 135 | // May be used to generate either float32 or float64 values.
 136 | type State[T Float] struct {
 137 | 	// Seed for all noise types.
 138 | 	//
 139 | 	// Default: 1337
 140 | 	Seed int
 141 | 	// Frequency for all noise types.
 142 | 	//
 143 | 	// Default: 0.01
 144 | 	Frequency T
 145 | 	// noiseType specifies the algorithm that will be used with GetNoise2D and GetNoise3D.
 146 | 	//
 147 | 	// Default: OpenSimplex2
 148 | 	noiseType NoiseType
 149 | 	// RotationType3D specified the type of rotation applied to 3D noise.
 150 | 	//
 151 | 	// Default: RotationNone
 152 | 	RotationType3D RotationType3D
 153 | 	// fractalType specifies the method used for combining octaves for all fractal noise types.
 154 | 	// Only effects DomainWarp2D and DomainWarp3D functions.
 155 | 	//
 156 | 	// Default: FractalNone
 157 | 	fractalType FractalType
 158 | 	// Octaves is the number of octaves used for all fractal noise types.
 159 | 	//
 160 | 	// Default: 3
 161 | 	Octaves int
 162 | 	// Lacunarity is the octave Lacunarity for all fractal noise types.
 163 | 	//
 164 | 	// Default: 2.0
 165 | 	Lacunarity T
 166 | 	// Gain is the octave gain for all fractal noise types.
 167 | 	//
 168 | 	// Default: 0.5
 169 | 	Gain T
 170 | 	// WeightedStrength is the octave weighting for all non-domain warp fractal types.
 171 | 	//
 172 | 	// Default: 0.0
 173 | 	WeightedStrength T
 174 | 	// PingPongStrength is the strength of the fractal ping pong effect.
 175 | 	//
 176 | 	// Default: 2.0
 177 | 	PingPongStrength T
 178 | 	// CellularDistanceFunc specifies the distance function used in cellular noise calculations.
 179 | 	//
 180 | 	// Default: CellularDistanceEuclideanSq,
 181 | 	CellularDistanceFunc CellularDistanceFunc
 182 | 	// CellularReturnType specifies the cellular return type from cellular noise calculations.
 183 | 	//
 184 | 	// Default: CellularReturnDistance,
 185 | 	CellularReturnType CellularReturnType
 186 | 	// CellularJitterMod is the maximum distance a cellular point can move from it's grid position.
 187 | 	// Setting this higher than 1 will cause artifacts.
 188 | 	//
 189 | 	// Default: 1.0
 190 | 	CellularJitterMod T
 191 | 	// DomainWarpType specifies the algorithm when using DomainWarp2D or DomainWarp3D.
 192 | 	//
 193 | 	// Default: DomainWarpOpenSimplex2
 194 | 	DomainWarpType DomainWarpType
 195 | 	// DomainWarpAmp is the maximum warp distance from original position when using DomainWarp2D
 196 | 	// or DomainWarp3D.
 197 | 	//
 198 | 	// Default: 1.0
 199 | 	DomainWarpAmp T
 200 | 	// noise2D contains the function used to generate 2D noise based on the state settings.
 201 | 	noise2D noise2DFunc[T]
 202 | 	// noise3D contains the function used to generate 3D noise based on the state settings.
 203 | 	noise3D noise3DFunc[T]
 204 | }
 205 | 
 206 | // Constants
 207 | 
 208 | var gradients2D = []float32{
 209 | 	0.130526192220052, 0.99144486137381, 0.38268343236509, 0.923879532511287, 0.608761429008721, 0.793353340291235, 0.793353340291235, 0.608761429008721,
 210 | 	0.923879532511287, 0.38268343236509, 0.99144486137381, 0.130526192220051, 0.99144486137381, -0.130526192220051, 0.923879532511287, -0.38268343236509,
 211 | 	0.793353340291235, -0.60876142900872, 0.608761429008721, -0.793353340291235, 0.38268343236509, -0.923879532511287, 0.130526192220052, -0.99144486137381,
 212 | 	-0.130526192220052, -0.99144486137381, -0.38268343236509, -0.923879532511287, -0.608761429008721, -0.793353340291235, -0.793353340291235, -0.608761429008721,
 213 | 	-0.923879532511287, -0.38268343236509, -0.99144486137381, -0.130526192220052, -0.99144486137381, 0.130526192220051, -0.923879532511287, 0.38268343236509,
 214 | 	-0.793353340291235, 0.608761429008721, -0.608761429008721, 0.793353340291235, -0.38268343236509, 0.923879532511287, -0.130526192220052, 0.99144486137381,
 215 | 	0.130526192220052, 0.99144486137381, 0.38268343236509, 0.923879532511287, 0.608761429008721, 0.793353340291235, 0.793353340291235, 0.608761429008721,
 216 | 	0.923879532511287, 0.38268343236509, 0.99144486137381, 0.130526192220051, 0.99144486137381, -0.130526192220051, 0.923879532511287, -0.38268343236509,
 217 | 	0.793353340291235, -0.60876142900872, 0.608761429008721, -0.793353340291235, 0.38268343236509, -0.923879532511287, 0.130526192220052, -0.99144486137381,
 218 | 	-0.130526192220052, -0.99144486137381, -0.38268343236509, -0.923879532511287, -0.608761429008721, -0.793353340291235, -0.793353340291235, -0.608761429008721,
 219 | 	-0.923879532511287, -0.38268343236509, -0.99144486137381, -0.130526192220052, -0.99144486137381, 0.130526192220051, -0.923879532511287, 0.38268343236509,
 220 | 	-0.793353340291235, 0.608761429008721, -0.608761429008721, 0.793353340291235, -0.38268343236509, 0.923879532511287, -0.130526192220052, 0.99144486137381,
 221 | 	0.130526192220052, 0.99144486137381, 0.38268343236509, 0.923879532511287, 0.608761429008721, 0.793353340291235, 0.793353340291235, 0.608761429008721,
 222 | 	0.923879532511287, 0.38268343236509, 0.99144486137381, 0.130526192220051, 0.99144486137381, -0.130526192220051, 0.923879532511287, -0.38268343236509,
 223 | 	0.793353340291235, -0.60876142900872, 0.608761429008721, -0.793353340291235, 0.38268343236509, -0.923879532511287, 0.130526192220052, -0.99144486137381,
 224 | 	-0.130526192220052, -0.99144486137381, -0.38268343236509, -0.923879532511287, -0.608761429008721, -0.793353340291235, -0.793353340291235, -0.608761429008721,
 225 | 	-0.923879532511287, -0.38268343236509, -0.99144486137381, -0.130526192220052, -0.99144486137381, 0.130526192220051, -0.923879532511287, 0.38268343236509,
 226 | 	-0.793353340291235, 0.608761429008721, -0.608761429008721, 0.793353340291235, -0.38268343236509, 0.923879532511287, -0.130526192220052, 0.99144486137381,
 227 | 	0.130526192220052, 0.99144486137381, 0.38268343236509, 0.923879532511287, 0.608761429008721, 0.793353340291235, 0.793353340291235, 0.608761429008721,
 228 | 	0.923879532511287, 0.38268343236509, 0.99144486137381, 0.130526192220051, 0.99144486137381, -0.130526192220051, 0.923879532511287, -0.38268343236509,
 229 | 	0.793353340291235, -0.60876142900872, 0.608761429008721, -0.793353340291235, 0.38268343236509, -0.923879532511287, 0.130526192220052, -0.99144486137381,
 230 | 	-0.130526192220052, -0.99144486137381, -0.38268343236509, -0.923879532511287, -0.608761429008721, -0.793353340291235, -0.793353340291235, -0.608761429008721,
 231 | 	-0.923879532511287, -0.38268343236509, -0.99144486137381, -0.130526192220052, -0.99144486137381, 0.130526192220051, -0.923879532511287, 0.38268343236509,
 232 | 	-0.793353340291235, 0.608761429008721, -0.608761429008721, 0.793353340291235, -0.38268343236509, 0.923879532511287, -0.130526192220052, 0.99144486137381,
 233 | 	0.130526192220052, 0.99144486137381, 0.38268343236509, 0.923879532511287, 0.608761429008721, 0.793353340291235, 0.793353340291235, 0.608761429008721,
 234 | 	0.923879532511287, 0.38268343236509, 0.99144486137381, 0.130526192220051, 0.99144486137381, -0.130526192220051, 0.923879532511287, -0.38268343236509,
 235 | 	0.793353340291235, -0.60876142900872, 0.608761429008721, -0.793353340291235, 0.38268343236509, -0.923879532511287, 0.130526192220052, -0.99144486137381,
 236 | 	-0.130526192220052, -0.99144486137381, -0.38268343236509, -0.923879532511287, -0.608761429008721, -0.793353340291235, -0.793353340291235, -0.608761429008721,
 237 | 	-0.923879532511287, -0.38268343236509, -0.99144486137381, -0.130526192220052, -0.99144486137381, 0.130526192220051, -0.923879532511287, 0.38268343236509,
 238 | 	-0.793353340291235, 0.608761429008721, -0.608761429008721, 0.793353340291235, -0.38268343236509, 0.923879532511287, -0.130526192220052, 0.99144486137381,
 239 | 	0.38268343236509, 0.923879532511287, 0.923879532511287, 0.38268343236509, 0.923879532511287, -0.38268343236509, 0.38268343236509, -0.923879532511287,
 240 | 	-0.38268343236509, -0.923879532511287, -0.923879532511287, -0.38268343236509, -0.923879532511287, 0.38268343236509, -0.38268343236509, 0.923879532511287,
 241 | }
 242 | 
 243 | var randVecs2D = []float32{
 244 | 	-0.2700222198, -0.9628540911, 0.3863092627, -0.9223693152,
 245 | 	0.04444859006, -0.999011673, -0.5992523158, -0.8005602176,
 246 | 	-0.7819280288, 0.6233687174, 0.9464672271, 0.3227999196,
 247 | 	-0.6514146797, -0.7587218957, 0.9378472289, 0.347048376,
 248 | 	-0.8497875957, -0.5271252623, -0.879042592, 0.4767432447,
 249 | 	-0.892300288, -0.4514423508, -0.379844434, -0.9250503802,
 250 | 	-0.9951650832, 0.0982163789, 0.7724397808, -0.6350880136,
 251 | 	0.7573283322, -0.6530343002, -0.9928004525, -0.119780055,
 252 | 	-0.0532665713, 0.9985803285, 0.9754253726, -0.2203300762,
 253 | 	-0.7665018163, 0.6422421394, 0.991636706, 0.1290606184,
 254 | 	-0.994696838, 0.1028503788, -0.5379205513, -0.84299554,
 255 | 	0.5022815471, -0.8647041387, 0.4559821461, -0.8899889226,
 256 | 	-0.8659131224, -0.5001944266, 0.0879458407, -0.9961252577,
 257 | 	-0.5051684983, 0.8630207346, 0.7753185226, -0.6315704146,
 258 | 	-0.6921944612, 0.7217110418, -0.5191659449, -0.8546734591,
 259 | 	0.8978622882, -0.4402764035, -0.1706774107, 0.9853269617,
 260 | 	-0.9353430106, -0.3537420705, -0.9992404798, 0.03896746794,
 261 | 	-0.2882064021, -0.9575683108, -0.9663811329, 0.2571137995,
 262 | 	-0.8759714238, -0.4823630009, -0.8303123018, -0.5572983775,
 263 | 	0.05110133755, -0.9986934731, -0.8558373281, -0.5172450752,
 264 | 	0.09887025282, 0.9951003332, 0.9189016087, 0.3944867976,
 265 | 	-0.2439375892, -0.9697909324, -0.8121409387, -0.5834613061,
 266 | 	-0.9910431363, 0.1335421355, 0.8492423985, -0.5280031709,
 267 | 	-0.9717838994, -0.2358729591, 0.9949457207, 0.1004142068,
 268 | 	0.6241065508, -0.7813392434, 0.662910307, 0.7486988212,
 269 | 	-0.7197418176, 0.6942418282, -0.8143370775, -0.5803922158,
 270 | 	0.104521054, -0.9945226741, -0.1065926113, -0.9943027784,
 271 | 	0.445799684, -0.8951327509, 0.105547406, 0.9944142724,
 272 | 	-0.992790267, 0.1198644477, -0.8334366408, 0.552615025,
 273 | 	0.9115561563, -0.4111755999, 0.8285544909, -0.5599084351,
 274 | 	0.7217097654, -0.6921957921, 0.4940492677, -0.8694339084,
 275 | 	-0.3652321272, -0.9309164803, -0.9696606758, 0.2444548501,
 276 | 	0.08925509731, -0.996008799, 0.5354071276, -0.8445941083,
 277 | 	-0.1053576186, 0.9944343981, -0.9890284586, 0.1477251101,
 278 | 	0.004856104961, 0.9999882091, 0.9885598478, 0.1508291331,
 279 | 	0.9286129562, -0.3710498316, -0.5832393863, -0.8123003252,
 280 | 	0.3015207509, 0.9534596146, -0.9575110528, 0.2883965738,
 281 | 	0.9715802154, -0.2367105511, 0.229981792, 0.9731949318,
 282 | 	0.955763816, -0.2941352207, 0.740956116, 0.6715534485,
 283 | 	-0.9971513787, -0.07542630764, 0.6905710663, -0.7232645452,
 284 | 	-0.290713703, -0.9568100872, 0.5912777791, -0.8064679708,
 285 | 	-0.9454592212, -0.325740481, 0.6664455681, 0.74555369,
 286 | 	0.6236134912, 0.7817328275, 0.9126993851, -0.4086316587,
 287 | 	-0.8191762011, 0.5735419353, -0.8812745759, -0.4726046147,
 288 | 	0.9953313627, 0.09651672651, 0.9855650846, -0.1692969699,
 289 | 	-0.8495980887, 0.5274306472, 0.6174853946, -0.7865823463,
 290 | 	0.8508156371, 0.52546432, 0.9985032451, -0.05469249926,
 291 | 	0.1971371563, -0.9803759185, 0.6607855748, -0.7505747292,
 292 | 	-0.03097494063, 0.9995201614, -0.6731660801, 0.739491331,
 293 | 	-0.7195018362, -0.6944905383, 0.9727511689, 0.2318515979,
 294 | 	0.9997059088, -0.0242506907, 0.4421787429, -0.8969269532,
 295 | 	0.9981350961, -0.061043673, -0.9173660799, -0.3980445648,
 296 | 	-0.8150056635, -0.5794529907, -0.8789331304, 0.4769450202,
 297 | 	0.0158605829, 0.999874213, -0.8095464474, 0.5870558317,
 298 | 	-0.9165898907, -0.3998286786, -0.8023542565, 0.5968480938,
 299 | 	-0.5176737917, 0.8555780767, -0.8154407307, -0.5788405779,
 300 | 	0.4022010347, -0.9155513791, -0.9052556868, -0.4248672045,
 301 | 	0.7317445619, 0.6815789728, -0.5647632201, -0.8252529947,
 302 | 	-0.8403276335, -0.5420788397, -0.9314281527, 0.363925262,
 303 | 	0.5238198472, 0.8518290719, 0.7432803869, -0.6689800195,
 304 | 	-0.985371561, -0.1704197369, 0.4601468731, 0.88784281,
 305 | 	0.825855404, 0.5638819483, 0.6182366099, 0.7859920446,
 306 | 	0.8331502863, -0.553046653, 0.1500307506, 0.9886813308,
 307 | 	-0.662330369, -0.7492119075, -0.668598664, 0.743623444,
 308 | 	0.7025606278, 0.7116238924, -0.5419389763, -0.8404178401,
 309 | 	-0.3388616456, 0.9408362159, 0.8331530315, 0.5530425174,
 310 | 	-0.2989720662, -0.9542618632, 0.2638522993, 0.9645630949,
 311 | 	0.124108739, -0.9922686234, -0.7282649308, -0.6852956957,
 312 | 	0.6962500149, 0.7177993569, -0.9183535368, 0.3957610156,
 313 | 	-0.6326102274, -0.7744703352, -0.9331891859, -0.359385508,
 314 | 	-0.1153779357, -0.9933216659, 0.9514974788, -0.3076565421,
 315 | 	-0.08987977445, -0.9959526224, 0.6678496916, 0.7442961705,
 316 | 	0.7952400393, -0.6062947138, -0.6462007402, -0.7631674805,
 317 | 	-0.2733598753, 0.9619118351, 0.9669590226, -0.254931851,
 318 | 	-0.9792894595, 0.2024651934, -0.5369502995, -0.8436138784,
 319 | 	-0.270036471, -0.9628500944, -0.6400277131, 0.7683518247,
 320 | 	-0.7854537493, -0.6189203566, 0.06005905383, -0.9981948257,
 321 | 	-0.02455770378, 0.9996984141, -0.65983623, 0.751409442,
 322 | 	-0.6253894466, -0.7803127835, -0.6210408851, -0.7837781695,
 323 | 	0.8348888491, 0.5504185768, -0.1592275245, 0.9872419133,
 324 | 	0.8367622488, 0.5475663786, -0.8675753916, -0.4973056806,
 325 | 	-0.2022662628, -0.9793305667, 0.9399189937, 0.3413975472,
 326 | 	0.9877404807, -0.1561049093, -0.9034455656, 0.4287028224,
 327 | 	0.1269804218, -0.9919052235, -0.3819600854, 0.924178821,
 328 | 	0.9754625894, 0.2201652486, -0.3204015856, -0.9472818081,
 329 | 	-0.9874760884, 0.1577687387, 0.02535348474, -0.9996785487,
 330 | 	0.4835130794, -0.8753371362, -0.2850799925, -0.9585037287,
 331 | 	-0.06805516006, -0.99768156, -0.7885244045, -0.6150034663,
 332 | 	0.3185392127, -0.9479096845, 0.8880043089, 0.4598351306,
 333 | 	0.6476921488, -0.7619021462, 0.9820241299, 0.1887554194,
 334 | 	0.9357275128, -0.3527237187, -0.8894895414, 0.4569555293,
 335 | 	0.7922791302, 0.6101588153, 0.7483818261, 0.6632681526,
 336 | 	-0.7288929755, -0.6846276581, 0.8729032783, -0.4878932944,
 337 | 	0.8288345784, 0.5594937369, 0.08074567077, 0.9967347374,
 338 | 	0.9799148216, -0.1994165048, -0.580730673, -0.8140957471,
 339 | 	-0.4700049791, -0.8826637636, 0.2409492979, 0.9705377045,
 340 | 	0.9437816757, -0.3305694308, -0.8927998638, -0.4504535528,
 341 | 	-0.8069622304, 0.5906030467, 0.06258973166, 0.9980393407,
 342 | 	-0.9312597469, 0.3643559849, 0.5777449785, 0.8162173362,
 343 | 	-0.3360095855, -0.941858566, 0.697932075, -0.7161639607,
 344 | 	-0.002008157227, -0.9999979837, -0.1827294312, -0.9831632392,
 345 | 	-0.6523911722, 0.7578824173, -0.4302626911, -0.9027037258,
 346 | 	-0.9985126289, -0.05452091251, -0.01028102172, -0.9999471489,
 347 | 	-0.4946071129, 0.8691166802, -0.2999350194, 0.9539596344,
 348 | 	0.8165471961, 0.5772786819, 0.2697460475, 0.962931498,
 349 | 	-0.7306287391, -0.6827749597, -0.7590952064, -0.6509796216,
 350 | 	-0.907053853, 0.4210146171, -0.5104861064, -0.8598860013,
 351 | 	0.8613350597, 0.5080373165, 0.5007881595, -0.8655698812,
 352 | 	-0.654158152, 0.7563577938, -0.8382755311, -0.545246856,
 353 | 	0.6940070834, 0.7199681717, 0.06950936031, 0.9975812994,
 354 | 	0.1702942185, -0.9853932612, 0.2695973274, 0.9629731466,
 355 | 	0.5519612192, -0.8338697815, 0.225657487, -0.9742067022,
 356 | 	0.4215262855, -0.9068161835, 0.4881873305, -0.8727388672,
 357 | 	-0.3683854996, -0.9296731273, -0.9825390578, 0.1860564427,
 358 | 	0.81256471, 0.5828709909, 0.3196460933, -0.9475370046,
 359 | 	0.9570913859, 0.2897862643, -0.6876655497, -0.7260276109,
 360 | 	-0.9988770922, -0.047376731, -0.1250179027, 0.992154486,
 361 | 	-0.8280133617, 0.560708367, 0.9324863769, -0.3612051451,
 362 | 	0.6394653183, 0.7688199442, -0.01623847064, -0.9998681473,
 363 | 	-0.9955014666, -0.09474613458, -0.81453315, 0.580117012,
 364 | 	0.4037327978, -0.9148769469, 0.9944263371, 0.1054336766,
 365 | 	-0.1624711654, 0.9867132919, -0.9949487814, -0.100383875,
 366 | 	-0.6995302564, 0.7146029809, 0.5263414922, -0.85027327,
 367 | 	-0.5395221479, 0.841971408, 0.6579370318, 0.7530729462,
 368 | 	0.01426758847, -0.9998982128, -0.6734383991, 0.7392433447,
 369 | 	0.639412098, -0.7688642071, 0.9211571421, 0.3891908523,
 370 | 	-0.146637214, -0.9891903394, -0.782318098, 0.6228791163,
 371 | 	-0.5039610839, -0.8637263605, -0.7743120191, -0.6328039957,
 372 | }
 373 | 
 374 | var gradients3D = []float32{
 375 | 	0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0,
 376 | 	1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0,
 377 | 	1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0,
 378 | 	0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0,
 379 | 	1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0,
 380 | 	1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0,
 381 | 	0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0,
 382 | 	1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0,
 383 | 	1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0,
 384 | 	0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0,
 385 | 	1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0,
 386 | 	1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0,
 387 | 	0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0,
 388 | 	1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0,
 389 | 	1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0,
 390 | 	1, 1, 0, 0, 0, -1, 1, 0, -1, 1, 0, 0, 0, -1, -1, 0,
 391 | }
 392 | 
 393 | var randVecs3D = []float32{
 394 | 	-0.7292736885, -0.6618439697, 0.1735581948, 0,
 395 | 	0.790292081, -0.5480887466, -0.2739291014, 0,
 396 | 	0.7217578935, 0.6226212466, -0.3023380997, 0,
 397 | 	0.565683137, -0.8208298145, -0.0790000257, 0,
 398 | 	0.760049034, -0.5555979497, -0.3370999617, 0,
 399 | 	0.3713945616, 0.5011264475, 0.7816254623, 0,
 400 | 	-0.1277062463, -0.4254438999, -0.8959289049, 0,
 401 | 	-0.2881560924, -0.5815838982, 0.7607405838, 0,
 402 | 	0.5849561111, -0.662820239, -0.4674352136, 0,
 403 | 	0.3307171178, 0.0391653737, 0.94291689, 0,
 404 | 	0.8712121778, -0.4113374369, -0.2679381538, 0,
 405 | 	0.580981015, 0.7021915846, 0.4115677815, 0,
 406 | 	0.503756873, 0.6330056931, -0.5878203852, 0,
 407 | 	0.4493712205, 0.601390195, 0.6606022552, 0,
 408 | 	-0.6878403724, 0.09018890807, -0.7202371714, 0,
 409 | 	-0.5958956522, -0.6469350577, 0.475797649, 0,
 410 | 	-0.5127052122, 0.1946921978, -0.8361987284, 0,
 411 | 	-0.9911507142, -0.05410276466, -0.1212153153, 0,
 412 | 	-0.2149721042, 0.9720882117, -0.09397607749, 0,
 413 | 	-0.7518650936, -0.5428057603, 0.3742469607, 0,
 414 | 	0.5237068895, 0.8516377189, -0.02107817834, 0,
 415 | 	0.6333504779, 0.1926167129, -0.7495104896, 0,
 416 | 	-0.06788241606, 0.3998305789, 0.9140719259, 0,
 417 | 	-0.5538628599, -0.4729896695, -0.6852128902, 0,
 418 | 	-0.7261455366, -0.5911990757, 0.3509933228, 0,
 419 | 	-0.9229274737, -0.1782808786, 0.3412049336, 0,
 420 | 	-0.6968815002, 0.6511274338, 0.3006480328, 0,
 421 | 	0.9608044783, -0.2098363234, -0.1811724921, 0,
 422 | 	0.06817146062, -0.9743405129, 0.2145069156, 0,
 423 | 	-0.3577285196, -0.6697087264, -0.6507845481, 0,
 424 | 	-0.1868621131, 0.7648617052, -0.6164974636, 0,
 425 | 	-0.6541697588, 0.3967914832, 0.6439087246, 0,
 426 | 	0.6993340405, -0.6164538506, 0.3618239211, 0,
 427 | 	-0.1546665739, 0.6291283928, 0.7617583057, 0,
 428 | 	-0.6841612949, -0.2580482182, -0.6821542638, 0,
 429 | 	0.5383980957, 0.4258654885, 0.7271630328, 0,
 430 | 	-0.5026987823, -0.7939832935, -0.3418836993, 0,
 431 | 	0.3202971715, 0.2834415347, 0.9039195862, 0,
 432 | 	0.8683227101, -0.0003762656404, -0.4959995258, 0,
 433 | 	0.791120031, -0.08511045745, 0.6057105799, 0,
 434 | 	-0.04011016052, -0.4397248749, 0.8972364289, 0,
 435 | 	0.9145119872, 0.3579346169, -0.1885487608, 0,
 436 | 	-0.9612039066, -0.2756484276, 0.01024666929, 0,
 437 | 	0.6510361721, -0.2877799159, -0.7023778346, 0,
 438 | 	-0.2041786351, 0.7365237271, 0.644859585, 0,
 439 | 	-0.7718263711, 0.3790626912, 0.5104855816, 0,
 440 | 	-0.3060082741, -0.7692987727, 0.5608371729, 0,
 441 | 	0.454007341, -0.5024843065, 0.7357899537, 0,
 442 | 	0.4816795475, 0.6021208291, -0.6367380315, 0,
 443 | 	0.6961980369, -0.3222197429, 0.641469197, 0,
 444 | 	-0.6532160499, -0.6781148932, 0.3368515753, 0,
 445 | 	0.5089301236, -0.6154662304, -0.6018234363, 0,
 446 | 	-0.1635919754, -0.9133604627, -0.372840892, 0,
 447 | 	0.52408019, -0.8437664109, 0.1157505864, 0,
 448 | 	0.5902587356, 0.4983817807, -0.6349883666, 0,
 449 | 	0.5863227872, 0.494764745, 0.6414307729, 0,
 450 | 	0.6779335087, 0.2341345225, 0.6968408593, 0,
 451 | 	0.7177054546, -0.6858979348, 0.120178631, 0,
 452 | 	-0.5328819713, -0.5205125012, 0.6671608058, 0,
 453 | 	-0.8654874251, -0.0700727088, -0.4960053754, 0,
 454 | 	-0.2861810166, 0.7952089234, 0.5345495242, 0,
 455 | 	-0.04849529634, 0.9810836427, -0.1874115585, 0,
 456 | 	-0.6358521667, 0.6058348682, 0.4781800233, 0,
 457 | 	0.6254794696, -0.2861619734, 0.7258696564, 0,
 458 | 	-0.2585259868, 0.5061949264, -0.8227581726, 0,
 459 | 	0.02136306781, 0.5064016808, -0.8620330371, 0,
 460 | 	0.200111773, 0.8599263484, 0.4695550591, 0,
 461 | 	0.4743561372, 0.6014985084, -0.6427953014, 0,
 462 | 	0.6622993731, -0.5202474575, -0.5391679918, 0,
 463 | 	0.08084972818, -0.6532720452, 0.7527940996, 0,
 464 | 	-0.6893687501, 0.0592860349, 0.7219805347, 0,
 465 | 	-0.1121887082, -0.9673185067, 0.2273952515, 0,
 466 | 	0.7344116094, 0.5979668656, -0.3210532909, 0,
 467 | 	0.5789393465, -0.2488849713, 0.7764570201, 0,
 468 | 	0.6988182827, 0.3557169806, -0.6205791146, 0,
 469 | 	-0.8636845529, -0.2748771249, -0.4224826141, 0,
 470 | 	-0.4247027957, -0.4640880967, 0.777335046, 0,
 471 | 	0.5257722489, -0.8427017621, 0.1158329937, 0,
 472 | 	0.9343830603, 0.316302472, -0.1639543925, 0,
 473 | 	-0.1016836419, -0.8057303073, -0.5834887393, 0,
 474 | 	-0.6529238969, 0.50602126, -0.5635892736, 0,
 475 | 	-0.2465286165, -0.9668205684, -0.06694497494, 0,
 476 | 	-0.9776897119, -0.2099250524, -0.007368825344, 0,
 477 | 	0.7736893337, 0.5734244712, 0.2694238123, 0,
 478 | 	-0.6095087895, 0.4995678998, 0.6155736747, 0,
 479 | 	0.5794535482, 0.7434546771, 0.3339292269, 0,
 480 | 	-0.8226211154, 0.08142581855, 0.5627293636, 0,
 481 | 	-0.510385483, 0.4703667658, 0.7199039967, 0,
 482 | 	-0.5764971849, -0.07231656274, -0.8138926898, 0,
 483 | 	0.7250628871, 0.3949971505, -0.5641463116, 0,
 484 | 	-0.1525424005, 0.4860840828, -0.8604958341, 0,
 485 | 	-0.5550976208, -0.4957820792, 0.667882296, 0,
 486 | 	-0.1883614327, 0.9145869398, 0.357841725, 0,
 487 | 	0.7625556724, -0.5414408243, -0.3540489801, 0,
 488 | 	-0.5870231946, -0.3226498013, -0.7424963803, 0,
 489 | 	0.3051124198, 0.2262544068, -0.9250488391, 0,
 490 | 	0.6379576059, 0.577242424, -0.5097070502, 0,
 491 | 	-0.5966775796, 0.1454852398, -0.7891830656, 0,
 492 | 	-0.658330573, 0.6555487542, -0.3699414651, 0,
 493 | 	0.7434892426, 0.2351084581, 0.6260573129, 0,
 494 | 	0.5562114096, 0.8264360377, -0.0873632843, 0,
 495 | 	-0.3028940016, -0.8251527185, 0.4768419182, 0,
 496 | 	0.1129343818, -0.985888439, -0.1235710781, 0,
 497 | 	0.5937652891, -0.5896813806, 0.5474656618, 0,
 498 | 	0.6757964092, -0.5835758614, -0.4502648413, 0,
 499 | 	0.7242302609, -0.1152719764, 0.6798550586, 0,
 500 | 	-0.9511914166, 0.0753623979, -0.2992580792, 0,
 501 | 	0.2539470961, -0.1886339355, 0.9486454084, 0,
 502 | 	0.571433621, -0.1679450851, -0.8032795685, 0,
 503 | 	-0.06778234979, 0.3978269256, 0.9149531629, 0,
 504 | 	0.6074972649, 0.733060024, -0.3058922593, 0,
 505 | 	-0.5435478392, 0.1675822484, 0.8224791405, 0,
 506 | 	-0.5876678086, -0.3380045064, -0.7351186982, 0,
 507 | 	-0.7967562402, 0.04097822706, -0.6029098428, 0,
 508 | 	-0.1996350917, 0.8706294745, 0.4496111079, 0,
 509 | 	-0.02787660336, -0.9106232682, -0.4122962022, 0,
 510 | 	-0.7797625996, -0.6257634692, 0.01975775581, 0,
 511 | 	-0.5211232846, 0.7401644346, -0.4249554471, 0,
 512 | 	0.8575424857, 0.4053272873, -0.3167501783, 0,
 513 | 	0.1045223322, 0.8390195772, -0.5339674439, 0,
 514 | 	0.3501822831, 0.9242524096, -0.1520850155, 0,
 515 | 	0.1987849858, 0.07647613266, 0.9770547224, 0,
 516 | 	0.7845996363, 0.6066256811, -0.1280964233, 0,
 517 | 	0.09006737436, -0.9750989929, -0.2026569073, 0,
 518 | 	-0.8274343547, -0.542299559, 0.1458203587, 0,
 519 | 	-0.3485797732, -0.415802277, 0.840000362, 0,
 520 | 	-0.2471778936, -0.7304819962, -0.6366310879, 0,
 521 | 	-0.3700154943, 0.8577948156, 0.3567584454, 0,
 522 | 	0.5913394901, -0.548311967, -0.5913303597, 0,
 523 | 	0.1204873514, -0.7626472379, -0.6354935001, 0,
 524 | 	0.616959265, 0.03079647928, 0.7863922953, 0,
 525 | 	0.1258156836, -0.6640829889, -0.7369967419, 0,
 526 | 	-0.6477565124, -0.1740147258, -0.7417077429, 0,
 527 | 	0.6217889313, -0.7804430448, -0.06547655076, 0,
 528 | 	0.6589943422, -0.6096987708, 0.4404473475, 0,
 529 | 	-0.2689837504, -0.6732403169, -0.6887635427, 0,
 530 | 	-0.3849775103, 0.5676542638, 0.7277093879, 0,
 531 | 	0.5754444408, 0.8110471154, -0.1051963504, 0,
 532 | 	0.9141593684, 0.3832947817, 0.131900567, 0,
 533 | 	-0.107925319, 0.9245493968, 0.3654593525, 0,
 534 | 	0.377977089, 0.3043148782, 0.8743716458, 0,
 535 | 	-0.2142885215, -0.8259286236, 0.5214617324, 0,
 536 | 	0.5802544474, 0.4148098596, -0.7008834116, 0,
 537 | 	-0.1982660881, 0.8567161266, -0.4761596756, 0,
 538 | 	-0.03381553704, 0.3773180787, -0.9254661404, 0,
 539 | 	-0.6867922841, -0.6656597827, 0.2919133642, 0,
 540 | 	0.7731742607, -0.2875793547, -0.5652430251, 0,
 541 | 	-0.09655941928, 0.9193708367, -0.3813575004, 0,
 542 | 	0.2715702457, -0.9577909544, -0.09426605581, 0,
 543 | 	0.2451015704, -0.6917998565, -0.6792188003, 0,
 544 | 	0.977700782, -0.1753855374, 0.1155036542, 0,
 545 | 	-0.5224739938, 0.8521606816, 0.02903615945, 0,
 546 | 	-0.7734880599, -0.5261292347, 0.3534179531, 0,
 547 | 	-0.7134492443, -0.269547243, 0.6467878011, 0,
 548 | 	0.1644037271, 0.5105846203, -0.8439637196, 0,
 549 | 	0.6494635788, 0.05585611296, 0.7583384168, 0,
 550 | 	-0.4711970882, 0.5017280509, -0.7254255765, 0,
 551 | 	-0.6335764307, -0.2381686273, -0.7361091029, 0,
 552 | 	-0.9021533097, -0.270947803, -0.3357181763, 0,
 553 | 	-0.3793711033, 0.872258117, 0.3086152025, 0,
 554 | 	-0.6855598966, -0.3250143309, 0.6514394162, 0,
 555 | 	0.2900942212, -0.7799057743, -0.5546100667, 0,
 556 | 	-0.2098319339, 0.85037073, 0.4825351604, 0,
 557 | 	-0.4592603758, 0.6598504336, -0.5947077538, 0,
 558 | 	0.8715945488, 0.09616365406, -0.4807031248, 0,
 559 | 	-0.6776666319, 0.7118504878, -0.1844907016, 0,
 560 | 	0.7044377633, 0.312427597, 0.637304036, 0,
 561 | 	-0.7052318886, -0.2401093292, -0.6670798253, 0,
 562 | 	0.081921007, -0.7207336136, -0.6883545647, 0,
 563 | 	-0.6993680906, -0.5875763221, -0.4069869034, 0,
 564 | 	-0.1281454481, 0.6419895885, 0.7559286424, 0,
 565 | 	-0.6337388239, -0.6785471501, -0.3714146849, 0,
 566 | 	0.5565051903, -0.2168887573, -0.8020356851, 0,
 567 | 	-0.5791554484, 0.7244372011, -0.3738578718, 0,
 568 | 	0.1175779076, -0.7096451073, 0.6946792478, 0,
 569 | 	-0.6134619607, 0.1323631078, 0.7785527795, 0,
 570 | 	0.6984635305, -0.02980516237, -0.715024719, 0,
 571 | 	0.8318082963, -0.3930171956, 0.3919597455, 0,
 572 | 	0.1469576422, 0.05541651717, -0.9875892167, 0,
 573 | 	0.708868575, -0.2690503865, 0.6520101478, 0,
 574 | 	0.2726053183, 0.67369766, -0.68688995, 0,
 575 | 	-0.6591295371, 0.3035458599, -0.6880466294, 0,
 576 | 	0.4815131379, -0.7528270071, 0.4487723203, 0,
 577 | 	0.9430009463, 0.1675647412, -0.2875261255, 0,
 578 | 	0.434802957, 0.7695304522, -0.4677277752, 0,
 579 | 	0.3931996188, 0.594473625, 0.7014236729, 0,
 580 | 	0.7254336655, -0.603925654, 0.3301814672, 0,
 581 | 	0.7590235227, -0.6506083235, 0.02433313207, 0,
 582 | 	-0.8552768592, -0.3430042733, 0.3883935666, 0,
 583 | 	-0.6139746835, 0.6981725247, 0.3682257648, 0,
 584 | 	-0.7465905486, -0.5752009504, 0.3342849376, 0,
 585 | 	0.5730065677, 0.810555537, -0.1210916791, 0,
 586 | 	-0.9225877367, -0.3475211012, -0.167514036, 0,
 587 | 	-0.7105816789, -0.4719692027, -0.5218416899, 0,
 588 | 	-0.08564609717, 0.3583001386, 0.929669703, 0,
 589 | 	-0.8279697606, -0.2043157126, 0.5222271202, 0,
 590 | 	0.427944023, 0.278165994, 0.8599346446, 0,
 591 | 	0.5399079671, -0.7857120652, -0.3019204161, 0,
 592 | 	0.5678404253, -0.5495413974, -0.6128307303, 0,
 593 | 	-0.9896071041, 0.1365639107, -0.04503418428, 0,
 594 | 	-0.6154342638, -0.6440875597, 0.4543037336, 0,
 595 | 	0.1074204368, -0.7946340692, 0.5975094525, 0,
 596 | 	-0.3595449969, -0.8885529948, 0.28495784, 0,
 597 | 	-0.2180405296, 0.1529888965, 0.9638738118, 0,
 598 | 	-0.7277432317, -0.6164050508, -0.3007234646, 0,
 599 | 	0.7249729114, -0.00669719484, 0.6887448187, 0,
 600 | 	-0.5553659455, -0.5336586252, 0.6377908264, 0,
 601 | 	0.5137558015, 0.7976208196, -0.3160000073, 0,
 602 | 	-0.3794024848, 0.9245608561, -0.03522751494, 0,
 603 | 	0.8229248658, 0.2745365933, -0.4974176556, 0,
 604 | 	-0.5404114394, 0.6091141441, 0.5804613989, 0,
 605 | 	0.8036581901, -0.2703029469, 0.5301601931, 0,
 606 | 	0.6044318879, 0.6832968393, 0.4095943388, 0,
 607 | 	0.06389988817, 0.9658208605, -0.2512108074, 0,
 608 | 	0.1087113286, 0.7402471173, -0.6634877936, 0,
 609 | 	-0.713427712, -0.6926784018, 0.1059128479, 0,
 610 | 	0.6458897819, -0.5724548511, -0.5050958653, 0,
 611 | 	-0.6553931414, 0.7381471625, 0.159995615, 0,
 612 | 	0.3910961323, 0.9188871375, -0.05186755998, 0,
 613 | 	-0.4879022471, -0.5904376907, 0.6429111375, 0,
 614 | 	0.6014790094, 0.7707441366, -0.2101820095, 0,
 615 | 	-0.5677173047, 0.7511360995, 0.3368851762, 0,
 616 | 	0.7858573506, 0.226674665, 0.5753666838, 0,
 617 | 	-0.4520345543, -0.604222686, -0.6561857263, 0,
 618 | 	0.002272116345, 0.4132844051, -0.9105991643, 0,
 619 | 	-0.5815751419, -0.5162925989, 0.6286591339, 0,
 620 | 	-0.03703704785, 0.8273785755, 0.5604221175, 0,
 621 | 	-0.5119692504, 0.7953543429, -0.3244980058, 0,
 622 | 	-0.2682417366, -0.9572290247, -0.1084387619, 0,
 623 | 	-0.2322482736, -0.9679131102, -0.09594243324, 0,
 624 | 	0.3554328906, -0.8881505545, 0.2913006227, 0,
 625 | 	0.7346520519, -0.4371373164, 0.5188422971, 0,
 626 | 	0.9985120116, 0.04659011161, -0.02833944577, 0,
 627 | 	-0.3727687496, -0.9082481361, 0.1900757285, 0,
 628 | 	0.91737377, -0.3483642108, 0.1925298489, 0,
 629 | 	0.2714911074, 0.4147529736, -0.8684886582, 0,
 630 | 	0.5131763485, -0.7116334161, 0.4798207128, 0,
 631 | 	-0.8737353606, 0.18886992, -0.4482350644, 0,
 632 | 	0.8460043821, -0.3725217914, 0.3814499973, 0,
 633 | 	0.8978727456, -0.1780209141, -0.4026575304, 0,
 634 | 	0.2178065647, -0.9698322841, -0.1094789531, 0,
 635 | 	-0.1518031304, -0.7788918132, -0.6085091231, 0,
 636 | 	-0.2600384876, -0.4755398075, -0.8403819825, 0,
 637 | 	0.572313509, -0.7474340931, -0.3373418503, 0,
 638 | 	-0.7174141009, 0.1699017182, -0.6756111411, 0,
 639 | 	-0.684180784, 0.02145707593, -0.7289967412, 0,
 640 | 	-0.2007447902, 0.06555605789, -0.9774476623, 0,
 641 | 	-0.1148803697, -0.8044887315, 0.5827524187, 0,
 642 | 	-0.7870349638, 0.03447489231, 0.6159443543, 0,
 643 | 	-0.2015596421, 0.6859872284, 0.6991389226, 0,
 644 | 	-0.08581082512, -0.10920836, -0.9903080513, 0,
 645 | 	0.5532693395, 0.7325250401, -0.396610771, 0,
 646 | 	-0.1842489331, -0.9777375055, -0.1004076743, 0,
 647 | 	0.0775473789, -0.9111505856, 0.4047110257, 0,
 648 | 	0.1399838409, 0.7601631212, -0.6344734459, 0,
 649 | 	0.4484419361, -0.845289248, 0.2904925424, 0,
 650 | }
 651 | 
 652 | // ====================
 653 | // Public API
 654 | // ====================
 655 | 
 656 | // New initializes a new noise generator state with default values. This function must be used
 657 | // to create new states.
 658 | func New[T Float]() *State[T] {
 659 | 	state := &State[T]{
 660 | 		Seed:                 1337,
 661 | 		Frequency:            0.01,
 662 | 		noiseType:            OpenSimplex2,
 663 | 		RotationType3D:       RotationNone,
 664 | 		fractalType:          FractalNone,
 665 | 		Octaves:              3,
 666 | 		Lacunarity:           2.0,
 667 | 		Gain:                 0.5,
 668 | 		WeightedStrength:     0.0,
 669 | 		PingPongStrength:     2.0,
 670 | 		CellularDistanceFunc: CellularDistanceEuclideanSq,
 671 | 		CellularReturnType:   CellularReturnDistance,
 672 | 		CellularJitterMod:    1.0,
 673 | 		DomainWarpAmp:        30.0,
 674 | 		DomainWarpType:       DomainWarpOpenSimplex2,
 675 | 	}
 676 | 	state.apply()
 677 | 	return state
 678 | }
 679 | 
 680 | // apply determines the function to use for generating noise, and caches it to reduce overhead
 681 | // each time it GetNoise2D or GetNoise3D is invoked.
 682 | func (state *State[T]) apply() {
 683 | 	switch state.fractalType {
 684 | 	case FractalFBm:
 685 | 		state.noise2D = genFractalFBM2D[T]
 686 | 		state.noise3D = genFractalFBM3D[T]
 687 | 	case FractalRidged:
 688 | 		state.noise2D = genFractalRidged2D[T]
 689 | 		state.noise3D = genFractalRidged3D[T]
 690 | 	case FractalPingPong:
 691 | 		state.noise2D = genFractalPingPong2D[T]
 692 | 		state.noise3D = genFractalPingPong3D[T]
 693 | 	default:
 694 | 		switch state.noiseType {
 695 | 		case OpenSimplex2:
 696 | 			state.noise2D = singleSimplex2D[T]
 697 | 			state.noise3D = singleOpenSimplex23D[T]
 698 | 		case OpenSimplex2S:
 699 | 			state.noise2D = singleOpenSimplex2S2D[T]
 700 | 			state.noise3D = singleOpenSimplex2S3D[T]
 701 | 		case Cellular:
 702 | 			state.noise2D = singleCellular2D[T]
 703 | 			state.noise3D = singleCellular3D[T]
 704 | 		case Perlin:
 705 | 			state.noise2D = singlePerlin2D[T]
 706 | 			state.noise3D = singlePerlin3D[T]
 707 | 		case ValueCubic:
 708 | 			state.noise2D = singleValueCubic2D[T]
 709 | 			state.noise3D = singleValueCubic3D[T]
 710 | 		case Value:
 711 | 			state.noise2D = singleValue2D[T]
 712 | 			state.noise3D = singleValue3D[T]
 713 | 		default:
 714 | 			state.noise2D = func(_ *State[T], _ int, _, _ T) T { return 0 }
 715 | 			state.noise3D = func(_ *State[T], _ int, _, _, _ T) T { return 0 }
 716 | 		}
 717 | 	}
 718 | }
 719 | 
 720 | // NoiseType specifies the algorithm that will be used with GetNoise2D and GetNoise3D.
 721 | //
 722 | // Default: OpenSimplex2
 723 | func (state *State[T]) NoiseType(nt NoiseType) {
 724 | 	state.noiseType = nt
 725 | 	state.apply()
 726 | }
 727 | 
 728 | // FractalType specifies the method used for combining octaves for all fractal noise types.
 729 | // Only effects DomainWarp2D and DomainWarp3D functions.
 730 | //
 731 | // Default: FractalNone
 732 | func (state *State[T]) FractalType(ft FractalType) {
 733 | 	state.fractalType = ft
 734 | 	state.apply()
 735 | }
 736 | 
 737 | // GetNoise2D calculates the noise value at the specified 2D position using the current state
 738 | // settings.
 739 | //
 740 | // This is a convenience function for GetNoise2D that accepts integral coordinates.
 741 | // Return values are always normalized and in the range of -1.0 and 1.0.
 742 | func (state *State[T]) Noise2D(x, y int) T {
 743 | 	fx, fy := state.transformNoiseCoordinate2D(T(x), T(y))
 744 | 	return state.noise2D(state, state.Seed, fx, fy)
 745 | }
 746 | 
 747 | // GetNoise3D calculates the noise value at the specified 3D position using the current state
 748 | // settings.
 749 | //
 750 | // This is a convenience function for GetNoise3D that accepts integral coordinates.
 751 | // Return values are always normalized and in the range of -1.0 and 1.0.
 752 | func (state *State[T]) Noise3D(x, y, z int) T {
 753 | 	fx, fy, fz := state.transformNoiseCoordinate3D(T(x), T(y), T(z))
 754 | 	return state.noise3D(state, state.Seed, fx, fy, fz)
 755 | }
 756 | 
 757 | // GetNoise2D calculates the noise value at the specified 2D position using the current state
 758 | // settings.
 759 | //
 760 | // Return values are always normalized and in the range of -1.0 and 1.0.
 761 | func (state *State[T]) GetNoise2D(x, y T) T {
 762 | 	x, y = state.transformNoiseCoordinate2D(x, y)
 763 | 	return state.noise2D(state, state.Seed, x, y)
 764 | }
 765 | 
 766 | // GetNoise3D calculates the noise value at the specified 3D position using the current state
 767 | // settings.
 768 | //
 769 | // Return values are always normalized and in the range of -1.0 and 1.0.
 770 | func (state *State[T]) GetNoise3D(x, y, z T) T {
 771 | 	x, y, z = state.transformNoiseCoordinate3D(x, y, z)
 772 | 	return state.noise3D(state, state.Seed, x, y, z)
 773 | }
 774 | 
 775 | // DomainWarp2D warps the input position using current domain warp settings.
 776 | func (state *State[T]) DomainWarp2D(x, y T) (T, T) {
 777 | 	xx := x
 778 | 	yy := y
 779 | 	switch state.fractalType {
 780 | 	default:
 781 | 		domainWarpSingle2D(state, &xx, &yy)
 782 | 	case FractalDomainWarpProgressive:
 783 | 		domainWarpFractalProgressive2D(state, &xx, &yy)
 784 | 	case FractalDomainWarpIndependent:
 785 | 		domainWarpFractalIndependent2D(state, &xx, &yy)
 786 | 	}
 787 | 	return xx, yy
 788 | }
 789 | 
 790 | // DomainWarp2D warps the input position using current domain warp settings.
 791 | func (state *State[T]) DomainWarp3D(x, y, z T) (T, T, T) {
 792 | 	xx := x
 793 | 	yy := y
 794 | 	zz := z
 795 | 	switch state.fractalType {
 796 | 	default:
 797 | 		domainWarpSingle3D(state, &xx, &yy, &zz)
 798 | 	case FractalDomainWarpProgressive:
 799 | 		domainWarpFractalProgressive3D(state, &xx, &yy, &zz)
 800 | 	case FractalDomainWarpIndependent:
 801 | 		domainWarpFractalIndependent3D(state, &xx, &yy, &zz)
 802 | 	}
 803 | 	return xx, yy, zz
 804 | }
 805 | 
 806 | // ====================
 807 | // Private/implemenation
 808 | // ====================
 809 | 
 810 | // Utilities
 811 | 
 812 | func fastMin[T Float](x, y T) T {
 813 | 	if x < y {
 814 | 		return x
 815 | 	}
 816 | 	return y
 817 | }
 818 | 
 819 | func fastMax[T Float](x, y T) T {
 820 | 	if x > y {
 821 | 		return x
 822 | 	}
 823 | 	return y
 824 | }
 825 | 
 826 | func fastAbs[T Float](f T) T {
 827 | 	if f < 0 {
 828 | 		return -f
 829 | 	}
 830 | 	return f
 831 | }
 832 | 
 833 | func fastSqrt[T Float](a T) T {
 834 | 	// Benchmarks using Quake's famous "inverse square root" were actually slightly slower than
 835 | 	// using the built-in math library.
 836 | 	return T(math.Sqrt(float64(a)))
 837 | }
 838 | 
 839 | func fastFloor[T Float](f T) int {
 840 | 	if f >= 0 {
 841 | 		return int(f)
 842 | 	}
 843 | 	return int(f) - 1
 844 | }
 845 | 
 846 | func fastRound[T Float](f T) int {
 847 | 	if f >= 0 {
 848 | 		return int(f + 0.5)
 849 | 	}
 850 | 	return int(f - 0.5)
 851 | }
 852 | 
 853 | func lerp[T Float](a, b, t T) T {
 854 | 	return a + t*(b-a)
 855 | }
 856 | 
 857 | func interpHermite[T Float](t T) T {
 858 | 	return t * t * (3 - 2*t)
 859 | }
 860 | 
 861 | func interpQuintic[T Float](t T) T {
 862 | 	return t * t * t * (t*(t*6-15) + 10)
 863 | }
 864 | 
 865 | func cubicLerp[T Float](a, b, c, d, t T) T {
 866 | 	var p T = (d - c) - (a - b)
 867 | 	return t*t*t*p + t*t*((a-b)-p) + t*(c-a) + b
 868 | }
 869 | 
 870 | func pingPong[T Float](t T) T {
 871 | 	t -= T(int(t*0.5)) * 2
 872 | 	if t < 1 {
 873 | 		return t
 874 | 	}
 875 | 	return 2 - t
 876 | }
 877 | 
 878 | func calculateFractalBounding[T Float](state *State[T]) T {
 879 | 	gain := fastAbs(state.Gain)
 880 | 	amp := gain
 881 | 	var ampFractal T = 1.0
 882 | 	for i := 1; i < state.Octaves; i++ {
 883 | 		ampFractal += amp
 884 | 		amp *= gain
 885 | 	}
 886 | 	return 1.0 / ampFractal
 887 | }
 888 | 
 889 | // Hashing
 890 | 
 891 | const (
 892 | 	primeX int = 501125321
 893 | 	primeY int = 1136930381
 894 | 	primeZ int = 1720413743
 895 | 
 896 | 	primeX2 = primeX << 1
 897 | 	primeY2 = -2021106534
 898 | 	primeZ2 = -854139810
 899 | )
 900 | 
 901 | func hash2D(seed, xPrimed, yPrimed int) uint32 {
 902 | 	hash := seed ^ xPrimed ^ yPrimed
 903 | 	return uint32(hash) * 0x27d4eb2d
 904 | }
 905 | 
 906 | func hash3D(seed, xPrimed, yPrimed, zPrimed int) uint32 {
 907 | 	hash := seed ^ xPrimed ^ yPrimed ^ zPrimed
 908 | 	return uint32(hash) * 0x27d4eb2d
 909 | }
 910 | 
 911 | func valCoord2D[T Float](seed, xPrimed, yPrimed int) T {
 912 | 	hash := hash2D(seed, xPrimed, yPrimed)
 913 | 	hash *= hash
 914 | 	hash ^= hash << 19
 915 | 	return T(int32(hash)) * (1 / 2147483648.0)
 916 | }
 917 | 
 918 | func valCoord3D[T Float](seed, xPrimed, yPrimed, zPrimed int) T {
 919 | 	hash := hash3D(seed, xPrimed, yPrimed, zPrimed)
 920 | 	hash *= hash
 921 | 	hash ^= hash << 19
 922 | 	return T(int32(hash)) * (1 / 2147483648.0)
 923 | }
 924 | 
 925 | func gradCoord2D[T Float](seed, xPrimed, yPrimed int, xd, yd T) T {
 926 | 	hash := hash2D(seed, xPrimed, yPrimed)
 927 | 	hash ^= hash >> 15
 928 | 	hash &= 127 << 1
 929 | 	return xd*T(gradients2D[hash]) + yd*T(gradients2D[hash|1])
 930 | }
 931 | 
 932 | func gradCoord3D[T Float](seed, xPrimed, yPrimed, zPrimed int, xd, yd, zd T) T {
 933 | 	hash := hash3D(seed, xPrimed, yPrimed, zPrimed)
 934 | 	hash ^= hash >> 15
 935 | 	hash &= 63 << 2
 936 | 	return xd*T(gradients3D[hash]) + yd*T(gradients3D[hash|1]) + zd*T(gradients3D[hash|2])
 937 | }
 938 | 
 939 | func gradCoordOut2D[T Float](seed, xPrimed, yPrimed int, xo, yo *T) {
 940 | 	hash := hash2D(seed, xPrimed, yPrimed) & (255 << 1)
 941 | 	*xo = T(randVecs2D[hash])
 942 | 	*yo = T(randVecs2D[hash|1])
 943 | }
 944 | 
 945 | func gradCoordOut3D[T Float](seed, xPrimed, yPrimed, zPrimed int, xo, yo, zo *T) {
 946 | 	hash := hash3D(seed, xPrimed, yPrimed, zPrimed) & (255 << 2)
 947 | 	*xo = T(randVecs3D[hash])
 948 | 	*yo = T(randVecs3D[hash|1])
 949 | 	*zo = T(randVecs3D[hash|2])
 950 | }
 951 | 
 952 | func gradCoordDual2D[T Float](seed, xPrimed, yPrimed int, xd, yd T, xo, yo *T) {
 953 | 	hash := hash2D(seed, xPrimed, yPrimed)
 954 | 	index1 := hash & (127 << 1)
 955 | 	index2 := (hash >> 7) & (255 << 1)
 956 | 
 957 | 	xg := T(gradients2D[index1])
 958 | 	yg := T(gradients2D[index1|1])
 959 | 	value := xd*xg + yd*yg
 960 | 
 961 | 	xgo := T(randVecs2D[index2])
 962 | 	ygo := T(randVecs2D[index2|1])
 963 | 
 964 | 	*xo = value * xgo
 965 | 	*yo = value * ygo
 966 | }
 967 | 
 968 | func gradCoordDual3D[T Float](seed, xPrimed, yPrimed, zPrimed int, xd, yd, zd T, xo, yo, zo *T) {
 969 | 	hash := hash3D(seed, xPrimed, yPrimed, zPrimed)
 970 | 	index1 := hash & (63 << 2)
 971 | 	index2 := (hash >> 6) & (255 << 2)
 972 | 
 973 | 	xg := T(gradients3D[index1])
 974 | 	yg := T(gradients3D[index1|1])
 975 | 	zg := T(gradients3D[index1|2])
 976 | 	value := xd*xg + yd*yg + zd*zg
 977 | 
 978 | 	xgo := T(randVecs3D[index2])
 979 | 	ygo := T(randVecs3D[index2|1])
 980 | 	zgo := T(randVecs3D[index2|2])
 981 | 
 982 | 	*xo = value * xgo
 983 | 	*yo = value * ygo
 984 | 	*zo = value * zgo
 985 | }
 986 | 
 987 | func genNoiseSingle2D[T Float](state *State[T], seed int, x, y T) T {
 988 | 	switch state.noiseType {
 989 | 	case OpenSimplex2:
 990 | 		return singleSimplex2D(state, seed, x, y)
 991 | 	case OpenSimplex2S:
 992 | 		return singleOpenSimplex2S2D(state, seed, x, y)
 993 | 	case Cellular:
 994 | 		return singleCellular2D(state, seed, x, y)
 995 | 	case Perlin:
 996 | 		return singlePerlin2D(state, seed, x, y)
 997 | 	case ValueCubic:
 998 | 		return singleValueCubic2D(state, seed, x, y)
 999 | 	case Value:
1000 | 		return singleValue2D(state, seed, x, y)
1001 | 	default:
1002 | 		return 0
1003 | 	}
1004 | }
1005 | 
1006 | func genNoiseSingle3D[T Float](state *State[T], seed int, x, y, z T) T {
1007 | 	switch state.noiseType {
1008 | 	case OpenSimplex2:
1009 | 		return singleOpenSimplex23D(state, seed, x, y, z)
1010 | 	case OpenSimplex2S:
1011 | 		return singleOpenSimplex2S3D(state, seed, x, y, z)
1012 | 	case Cellular:
1013 | 		return singleCellular3D(state, seed, x, y, z)
1014 | 	case Perlin:
1015 | 		return singlePerlin3D(state, seed, x, y, z)
1016 | 	case ValueCubic:
1017 | 		return singleValueCubic3D(state, seed, x, y, z)
1018 | 	case Value:
1019 | 		return singleValue3D(state, seed, x, y, z)
1020 | 	default:
1021 | 		return 0
1022 | 	}
1023 | }
1024 | 
1025 | // Noise Coordinate Transforms (frequency, and possible skew or rotation)
1026 | 
1027 | func (state *State[T]) transformNoiseCoordinate2D(x, y T) (T, T) {
1028 | 	tx := x * state.Frequency
1029 | 	ty := y * state.Frequency
1030 | 
1031 | 	switch state.noiseType {
1032 | 	case OpenSimplex2, OpenSimplex2S:
1033 | 		const SQRT3 float64 = 1.7320508075688772935274463415059
1034 | 		const F2 float64 = 0.5 * (SQRT3 - 1)
1035 | 		t := (tx + ty) * T(F2)
1036 | 		tx += t
1037 | 		ty += t
1038 | 	}
1039 | 	return tx, ty
1040 | }
1041 | 
1042 | func (state *State[T]) transformNoiseCoordinate3D(x, y, z T) (T, T, T) {
1043 | 	tx := x * state.Frequency
1044 | 	ty := y * state.Frequency
1045 | 	tz := z * state.Frequency
1046 | 
1047 | 	switch state.RotationType3D {
1048 | 	case RotationImproveXYPlanes:
1049 | 		xy := tx + ty
1050 | 		s2 := xy * -0.211324865405187
1051 | 		tz *= 0.577350269189626
1052 | 		tx += s2 - tz
1053 | 		ty = ty + s2 - tz
1054 | 		tz += xy * 0.577350269189626
1055 | 	case RotationImproveXZPlanes:
1056 | 		xz := tx + tz
1057 | 		s2 := xz * -0.211324865405187
1058 | 		ty *= 0.577350269189626
1059 | 		tx += s2 - ty
1060 | 		tz += s2 - ty
1061 | 		ty += xz * 0.577350269189626
1062 | 	default:
1063 | 		switch state.noiseType {
1064 | 		case OpenSimplex2, OpenSimplex2S:
1065 | 			const R3 float64 = 2.0 / 3.0
1066 | 			r := (tx + ty + tz) * T(R3) // Rotation, not skew
1067 | 			tx = r - tx
1068 | 			ty = r - ty
1069 | 			tz = r - tz
1070 | 		}
1071 | 	}
1072 | 	return tx, ty, tz
1073 | }
1074 | 
1075 | // Domain Warp Coordinate Transforms
1076 | 
1077 | func transformDomainWarpCoordinate2D[T Float](state *State[T], x, y *T) {
1078 | 	switch state.DomainWarpType {
1079 | 	case DomainWarpOpenSimplex2, DomainWarpOpenSimplex2Reduced:
1080 | 		const SQRT3 float64 = 1.7320508075688772935274463415059
1081 | 		const F2 float64 = 0.5 * (SQRT3 - 1)
1082 | 		t := (*x + *y) * T(F2)
1083 | 		*x += t
1084 | 		*y += t
1085 | 	}
1086 | }
1087 | 
1088 | func transformDomainWarpCoordinate3D[T Float](state *State[T], x, y, z *T) {
1089 | 	switch state.RotationType3D {
1090 | 	case RotationImproveXYPlanes:
1091 | 		xy := *x + *y
1092 | 		s2 := xy * -0.211324865405187
1093 | 		*z *= 0.577350269189626
1094 | 		*x += s2 - *z
1095 | 		*y = *y + s2 - *z
1096 | 		*z += xy * 0.577350269189626
1097 | 	case RotationImproveXZPlanes:
1098 | 		xz := *x + *z
1099 | 		s2 := xz * -0.211324865405187
1100 | 		*y *= 0.577350269189626
1101 | 		*x += s2 - *y
1102 | 		*z += s2 - *y
1103 | 		*y += xz * 0.577350269189626
1104 | 	default:
1105 | 		switch state.DomainWarpType {
1106 | 		case DomainWarpOpenSimplex2, DomainWarpOpenSimplex2Reduced:
1107 | 			const R3 float64 = 2.0 / 3.0
1108 | 			r := (*x + *y + *z) * T(R3) // Rotation, not skew
1109 | 			*x = r - *x
1110 | 			*y = r - *y
1111 | 			*z = r - *z
1112 | 		}
1113 | 	}
1114 | }
1115 | 
1116 | // Fractal FBm
1117 | func genFractalFBM2D[T Float](state *State[T], seed int, x, y T) (sum T) {
1118 | 	amp := calculateFractalBounding(state)
1119 | 
1120 | 	for i := 0; i < state.Octaves; i++ {
1121 | 		noise := genNoiseSingle2D(state, seed, x, y)
1122 | 		seed++
1123 | 		sum += noise * amp
1124 | 		amp *= lerp(1.0, fastMin(noise+1, 2)*0.5, state.WeightedStrength)
1125 | 
1126 | 		x *= state.Lacunarity
1127 | 		y *= state.Lacunarity
1128 | 		amp *= state.Gain
1129 | 	}
1130 | 
1131 | 	return
1132 | }
1133 | 
1134 | func genFractalFBM3D[T Float](state *State[T], seed int, x, y, z T) (sum T) {
1135 | 	amp := calculateFractalBounding(state)
1136 | 
1137 | 	for i := 0; i < state.Octaves; i++ {
1138 | 		noise := genNoiseSingle3D(state, seed, x, y, z)
1139 | 		seed++
1140 | 		sum += noise * amp
1141 | 		amp *= lerp(1.0, (noise+1)*0.5, state.WeightedStrength)
1142 | 
1143 | 		x *= state.Lacunarity
1144 | 		y *= state.Lacunarity
1145 | 		z *= state.Lacunarity
1146 | 		amp *= state.Gain
1147 | 	}
1148 | 
1149 | 	return
1150 | }
1151 | 
1152 | // Fractal Ridged
1153 | 
1154 | func genFractalRidged2D[T Float](state *State[T], seed int, x, y T) (sum T) {
1155 | 	amp := calculateFractalBounding(state)
1156 | 
1157 | 	for i := 0; i < state.Octaves; i++ {
1158 | 		noise := fastAbs(genNoiseSingle2D(state, seed, x, y))
1159 | 		seed++
1160 | 		sum += (noise*-2 + 1) * amp
1161 | 		amp *= lerp(1.0, 1-noise, state.WeightedStrength)
1162 | 
1163 | 		x *= state.Lacunarity
1164 | 		y *= state.Lacunarity
1165 | 		amp *= state.Gain
1166 | 	}
1167 | 
1168 | 	return
1169 | }
1170 | 
1171 | func genFractalRidged3D[T Float](state *State[T], seed int, x, y, z T) (sum T) {
1172 | 	amp := calculateFractalBounding(state)
1173 | 
1174 | 	for i := 0; i < state.Octaves; i++ {
1175 | 		noise := fastAbs(genNoiseSingle3D(state, seed, x, y, z))
1176 | 		seed++
1177 | 		sum += (noise*-2 + 1) * amp
1178 | 		amp *= lerp(1.0, 1-noise, state.WeightedStrength)
1179 | 
1180 | 		x *= state.Lacunarity
1181 | 		y *= state.Lacunarity
1182 | 		z *= state.Lacunarity
1183 | 		amp *= state.Gain
1184 | 	}
1185 | 
1186 | 	return
1187 | }
1188 | 
1189 | // Fractal PingPong
1190 | 
1191 | func genFractalPingPong2D[T Float](state *State[T], seed int, x, y T) (sum T) {
1192 | 	amp := calculateFractalBounding(state)
1193 | 
1194 | 	for i := 0; i < state.Octaves; i++ {
1195 | 		noise := pingPong((genNoiseSingle2D(state, seed, x, y) + 1) * state.PingPongStrength)
1196 | 		seed++
1197 | 		sum += (noise - 0.5) * 2 * amp
1198 | 		amp *= lerp(1.0, noise, state.WeightedStrength)
1199 | 
1200 | 		x *= state.Lacunarity
1201 | 		y *= state.Lacunarity
1202 | 		amp *= state.Gain
1203 | 	}
1204 | 
1205 | 	return
1206 | }
1207 | 
1208 | func genFractalPingPong3D[T Float](state *State[T], seed int, x, y, z T) (sum T) {
1209 | 	amp := calculateFractalBounding(state)
1210 | 
1211 | 	for i := 0; i < state.Octaves; i++ {
1212 | 		noise := pingPong((genNoiseSingle3D(state, seed, x, y, z) + 1) * state.PingPongStrength)
1213 | 		seed++
1214 | 		sum += (noise - 0.5) * 2 * amp
1215 | 		amp *= lerp(1.0, noise, state.WeightedStrength)
1216 | 
1217 | 		x *= state.Lacunarity
1218 | 		y *= state.Lacunarity
1219 | 		z *= state.Lacunarity
1220 | 		amp *= state.Gain
1221 | 	}
1222 | 
1223 | 	return
1224 | }
1225 | 
1226 | // Simplex/OpenSimplex2 Noise
1227 | 
1228 | func singleSimplex2D[T Float](state *State[T], seed int, x, y T) T {
1229 | 	// 2D OpenSimplex2 case uses the same algorithm as ordinary Simplex.
1230 | 
1231 | 	const SQRT3 float64 = 1.7320508075688772935274463415059
1232 | 	const G2 float64 = (3 - SQRT3) / 6
1233 | 
1234 | 	i := fastFloor(x)
1235 | 	j := fastFloor(y)
1236 | 	xi := x - T(i)
1237 | 	yi := y - T(j)
1238 | 
1239 | 	t := (xi + yi) * T(G2)
1240 | 	x0 := xi - t
1241 | 	y0 := yi - t
1242 | 
1243 | 	i *= primeX
1244 | 	j *= primeY
1245 | 
1246 | 	var n0, n1, n2 T
1247 | 	a := 0.5 - x0*x0 - y0*y0
1248 | 	if a <= 0 {
1249 | 		n0 = 0
1250 | 	} else {
1251 | 		n0 = (a * a) * (a * a) * gradCoord2D(seed, i, j, x0, y0)
1252 | 	}
1253 | 
1254 | 	c := T(2*(1-2*G2)*(1/G2-2))*t + (T(-2*(1-2*G2)*(1-2*G2)) + a)
1255 | 	if c <= 0 {
1256 | 		n2 = 0
1257 | 	} else {
1258 | 		x2 := x0 + (2*T(G2) - 1)
1259 | 		y2 := y0 + (2*T(G2) - 1)
1260 | 		n2 = (c * c) * (c * c) * gradCoord2D(seed, i+primeX, j+primeY, x2, y2)
1261 | 	}
1262 | 
1263 | 	if y0 > x0 {
1264 | 		x1 := x0 + T(G2)
1265 | 		y1 := y0 + (T(G2) - 1)
1266 | 		b := 0.5 - x1*x1 - y1*y1
1267 | 		if b <= 0 {
1268 | 			n1 = 0
1269 | 		} else {
1270 | 			n1 = (b * b) * (b * b) * gradCoord2D(seed, i, j+primeY, x1, y1)
1271 | 		}
1272 | 	} else {
1273 | 		x1 := x0 + (T(G2) - 1)
1274 | 		y1 := y0 + T(G2)
1275 | 		b := 0.5 - x1*x1 - y1*y1
1276 | 		if b <= 0 {
1277 | 			n1 = 0
1278 | 		} else {
1279 | 			n1 = (b * b) * (b * b) * gradCoord2D(seed, i+primeX, j, x1, y1)
1280 | 		}
1281 | 	}
1282 | 
1283 | 	return (n0 + n1 + n2) * 99.83685446303647
1284 | }
1285 | 
1286 | func singleOpenSimplex23D[T Float](state *State[T], seed int, x, y, z T) T {
1287 | 	// 3D OpenSimplex2 case uses two offset rotated cube grids.
1288 | 
1289 | 	i := fastRound(x)
1290 | 	j := fastRound(y)
1291 | 	k := fastRound(z)
1292 | 	x0 := x - T(i)
1293 | 	y0 := y - T(j)
1294 | 	z0 := z - T(k)
1295 | 
1296 | 	xNSign := int(-x0-1.0) | 1
1297 | 	yNSign := int(-y0-1.0) | 1
1298 | 	zNSign := int(-z0-1.0) | 1
1299 | 
1300 | 	ax0 := T(xNSign) * -x0
1301 | 	ay0 := T(yNSign) * -y0
1302 | 	az0 := T(zNSign) * -z0
1303 | 
1304 | 	i *= primeX
1305 | 	j *= primeY
1306 | 	k *= primeZ
1307 | 
1308 | 	var value T
1309 | 	a := (0.6 - x0*x0) - (y0*y0 + z0*z0)
1310 | 
1311 | 	for l := 0; true; l++ {
1312 | 		if a > 0 {
1313 | 			value += (a * a) * (a * a) * gradCoord3D(seed, i, j, k, x0, y0, z0)
1314 | 		}
1315 | 
1316 | 		b := a + 1
1317 | 		i1 := i
1318 | 		j1 := j
1319 | 		k1 := k
1320 | 		x1 := x0
1321 | 		y1 := y0
1322 | 		z1 := z0
1323 | 		if ax0 >= ay0 && ax0 >= az0 {
1324 | 			x1 += T(xNSign)
1325 | 			b -= T(xNSign) * 2 * x1
1326 | 			i1 -= xNSign * primeX
1327 | 		} else if ay0 > ax0 && ay0 >= az0 {
1328 | 			y1 += T(yNSign)
1329 | 			b -= T(yNSign) * 2 * y1
1330 | 			j1 -= yNSign * primeY
1331 | 		} else {
1332 | 			z1 += T(zNSign)
1333 | 			b -= T(zNSign) * 2 * z1
1334 | 			k1 -= zNSign * primeZ
1335 | 		}
1336 | 
1337 | 		if b > 0 {
1338 | 			value += (b * b) * (b * b) * gradCoord3D(seed, i1, j1, k1, x1, y1, z1)
1339 | 		}
1340 | 
1341 | 		if l == 1 {
1342 | 			break
1343 | 		}
1344 | 
1345 | 		ax0 := 0.5 - ax0
1346 | 		ay0 := 0.5 - ay0
1347 | 		az0 := 0.5 - az0
1348 | 
1349 | 		x0 = T(xNSign) * ax0
1350 | 		y0 = T(yNSign) * ay0
1351 | 		z0 = T(zNSign) * az0
1352 | 
1353 | 		a += (0.75 - ax0) - (ay0 + az0)
1354 | 
1355 | 		i += (xNSign >> 1) & primeX
1356 | 		j += (yNSign >> 1) & primeY
1357 | 		k += (zNSign >> 1) & primeZ
1358 | 
1359 | 		xNSign = -xNSign
1360 | 		yNSign = -yNSign
1361 | 		zNSign = -zNSign
1362 | 
1363 | 		seed = ^seed
1364 | 	}
1365 | 
1366 | 	return value * 32.69428253173828125
1367 | }
1368 | 
1369 | // OpenSimplex2S Noise
1370 | 
1371 | func singleOpenSimplex2S2D[T Float](state *State[T], seed int, x, y T) T {
1372 | 	// 2D OpenSimplex2S case is a modified 2D simplex noise.
1373 | 
1374 | 	const SQRT3 float64 = 1.7320508075688772935274463415059
1375 | 	const G2 float64 = (3 - SQRT3) / 6
1376 | 
1377 | 	i := fastFloor(x)
1378 | 	j := fastFloor(y)
1379 | 	xi := x - T(i)
1380 | 	yi := y - T(j)
1381 | 
1382 | 	i *= primeX
1383 | 	j *= primeY
1384 | 	i1 := i + primeX
1385 | 	j1 := j + primeY
1386 | 
1387 | 	t := (xi + yi) * T(G2)
1388 | 	x0 := xi - t
1389 | 	y0 := yi - t
1390 | 
1391 | 	a0 := (2.0 / 3.0) - x0*x0 - y0*y0
1392 | 	value := (a0 * a0) * (a0 * a0) * gradCoord2D(seed, i, j, x0, y0)
1393 | 
1394 | 	a1 := T(2*(1-2*G2)*(1/G2-2))*t + (T(-2*(1-2*G2)*(1-2*G2)) + a0)
1395 | 	x1 := x0 - T(1-2*G2)
1396 | 	y1 := y0 - T(1-2*G2)
1397 | 	value += (a1 * a1) * (a1 * a1) * gradCoord2D(seed, i1, j1, x1, y1)
1398 | 
1399 | 	// Nested conditionals were faster than compact bit logic/arithmetic.
1400 | 	xmyi := xi - yi
1401 | 	if t > T(G2) {
1402 | 		if xi+xmyi > 1 {
1403 | 			x2 := x0 + T(3*G2-2)
1404 | 			y2 := y0 + T(3*G2-1)
1405 | 			a2 := (2.0 / 3.0) - x2*x2 - y2*y2
1406 | 			if a2 > 0 {
1407 | 				value += (a2 * a2) * (a2 * a2) * gradCoord2D(seed, i+(primeX2), j+primeY, x2, y2)
1408 | 			}
1409 | 		} else {
1410 | 			x2 := x0 + T(G2)
1411 | 			y2 := y0 + T(G2-1)
1412 | 			a2 := (2.0 / 3.0) - x2*x2 - y2*y2
1413 | 			if a2 > 0 {
1414 | 				value += (a2 * a2) * (a2 * a2) * gradCoord2D(seed, i, j+primeY, x2, y2)
1415 | 			}
1416 | 		}
1417 | 
1418 | 		if yi-xmyi > 1 {
1419 | 			x3 := x0 + T(3*G2-1)
1420 | 			y3 := y0 + T(3*G2-2)
1421 | 			a3 := (2.0 / 3.0) - x3*x3 - y3*y3
1422 | 			if a3 > 0 {
1423 | 				value += (a3 * a3) * (a3 * a3) * gradCoord2D(seed, i+primeX, j+(primeY2), x3, y3)
1424 | 			}
1425 | 		} else {
1426 | 			x3 := x0 + T(G2-1)
1427 | 			y3 := y0 + T(G2)
1428 | 			a3 := (2.0 / 3.0) - x3*x3 - y3*y3
1429 | 			if a3 > 0 {
1430 | 				value += (a3 * a3) * (a3 * a3) * gradCoord2D(seed, i+primeX, j, x3, y3)
1431 | 			}
1432 | 		}
1433 | 	} else {
1434 | 		if xi+xmyi < 0 {
1435 | 			x2 := x0 + T(1-G2)
1436 | 			y2 := y0 - T(G2)
1437 | 			a2 := (2.0 / 3.0) - x2*x2 - y2*y2
1438 | 			if a2 > 0 {
1439 | 				value += (a2 * a2) * (a2 * a2) * gradCoord2D(seed, i-primeX, j, x2, y2)
1440 | 			}
1441 | 		} else {
1442 | 			x2 := x0 + T(G2-1)
1443 | 			y2 := y0 + T(G2)
1444 | 			a2 := (2.0 / 3.0) - x2*x2 - y2*y2
1445 | 			if a2 > 0 {
1446 | 				value += (a2 * a2) * (a2 * a2) * gradCoord2D(seed, i+primeX, j, x2, y2)
1447 | 			}
1448 | 		}
1449 | 
1450 | 		if yi < xmyi {
1451 | 			x2 := x0 - T(G2)
1452 | 			y2 := y0 - T(G2-1)
1453 | 			a2 := (2.0 / 3.0) - x2*x2 - y2*y2
1454 | 			if a2 > 0 {
1455 | 				value += (a2 * a2) * (a2 * a2) * gradCoord2D(seed, i, j-primeY, x2, y2)
1456 | 			}
1457 | 		} else {
1458 | 			x2 := x0 + T(G2)
1459 | 			y2 := y0 + T(G2-1)
1460 | 			a2 := (2.0 / 3.0) - x2*x2 - y2*y2
1461 | 			if a2 > 0 {
1462 | 				value += (a2 * a2) * (a2 * a2) * gradCoord2D(seed, i, j+primeY, x2, y2)
1463 | 			}
1464 | 		}
1465 | 	}
1466 | 
1467 | 	return value * 18.24196194486065
1468 | }
1469 | 
1470 | func singleOpenSimplex2S3D[T Float](state *State[T], seed int, x, y, z T) T {
1471 | 	// 3D OpenSimplex2S case uses two offset rotated cube grids.
1472 | 
1473 | 	i := fastFloor(x)
1474 | 	j := fastFloor(y)
1475 | 	k := fastFloor(z)
1476 | 	xi := x - T(i)
1477 | 	yi := y - T(j)
1478 | 	zi := z - T(k)
1479 | 
1480 | 	i *= primeX
1481 | 	j *= primeY
1482 | 	k *= primeZ
1483 | 
1484 | 	seed2 := seed + 1293373
1485 | 
1486 | 	xNMask := int(-0.5 - xi)
1487 | 	yNMask := int(-0.5 - yi)
1488 | 	zNMask := int(-0.5 - zi)
1489 | 
1490 | 	x0 := xi + T(xNMask)
1491 | 	y0 := yi + T(yNMask)
1492 | 	z0 := zi + T(zNMask)
1493 | 	a0 := 0.75 - x0*x0 - y0*y0 - z0*z0
1494 | 	value := (a0 * a0) * (a0 * a0) * gradCoord3D(seed, i+(xNMask&primeX), j+(yNMask&primeY), k+(zNMask&primeZ), x0, y0, z0)
1495 | 
1496 | 	x1 := xi - 0.5
1497 | 	y1 := yi - 0.5
1498 | 	z1 := zi - 0.5
1499 | 	a1 := 0.75 - x1*x1 - y1*y1 - z1*z1
1500 | 	value += (a1 * a1) * (a1 * a1) * gradCoord3D(seed2, i+primeX, j+primeY, k+primeZ, x1, y1, z1)
1501 | 
1502 | 	xAFlipMask0 := T((xNMask|1)<<1) * x1
1503 | 	yAFlipMask0 := T((yNMask|1)<<1) * y1
1504 | 	zAFlipMask0 := T((zNMask|1)<<1) * z1
1505 | 	xAFlipMask1 := T(-2-(xNMask<<2))*x1 - 1.0
1506 | 	yAFlipMask1 := T(-2-(yNMask<<2))*y1 - 1.0
1507 | 	zAFlipMask1 := T(-2-(zNMask<<2))*z1 - 1.0
1508 | 
1509 | 	skip5 := false
1510 | 	a2 := T(xAFlipMask0) + a0
1511 | 	if a2 > 0 {
1512 | 		x2 := x0 - T(xNMask|1)
1513 | 		y2 := y0
1514 | 		z2 := z0
1515 | 		value += (a2 * a2) * (a2 * a2) * gradCoord3D(seed, i+(^xNMask&primeX), j+(yNMask&primeY), k+(zNMask&primeZ), x2, y2, z2)
1516 | 	} else {
1517 | 		a3 := yAFlipMask0 + zAFlipMask0 + a0
1518 | 		if a3 > 0 {
1519 | 			x3 := x0
1520 | 			y3 := y0 - T(yNMask|1)
1521 | 			z3 := z0 - T(zNMask|1)
1522 | 			value += (a3 * a3) * (a3 * a3) * gradCoord3D(seed, i+(xNMask&primeX), j+(^yNMask&primeY), k+(^zNMask&primeZ), x3, y3, z3)
1523 | 		}
1524 | 
1525 | 		a4 := T(xAFlipMask1) + a1
1526 | 		if a4 > 0 {
1527 | 			x4 := T(xNMask|1) + x1
1528 | 			y4 := y1
1529 | 			z4 := z1
1530 | 			value += (a4 * a4) * (a4 * a4) * gradCoord3D(seed2, i+(xNMask&(primeX2)), j+primeY, k+primeZ, x4, y4, z4)
1531 | 			skip5 = true
1532 | 		}
1533 | 	}
1534 | 
1535 | 	skip9 := false
1536 | 	a6 := T(yAFlipMask0) + a0
1537 | 	if a6 > 0 {
1538 | 		x6 := x0
1539 | 		y6 := y0 - T(yNMask|1)
1540 | 		z6 := z0
1541 | 		value += (a6 * a6) * (a6 * a6) * gradCoord3D(seed, i+(xNMask&primeX), j+(^yNMask&primeY), k+(zNMask&primeZ), x6, y6, z6)
1542 | 	} else {
1543 | 		a7 := T(xAFlipMask0+zAFlipMask0) + a0
1544 | 		if a7 > 0 {
1545 | 			x7 := x0 - T(xNMask|1)
1546 | 			y7 := y0
1547 | 			z7 := z0 - T(zNMask|1)
1548 | 			value += (a7 * a7) * (a7 * a7) * gradCoord3D(seed, i+(^xNMask&primeX), j+(yNMask&primeY), k+(^zNMask&primeZ), x7, y7, z7)
1549 | 		}
1550 | 
1551 | 		a8 := T(yAFlipMask1) + a1
1552 | 		if a8 > 0 {
1553 | 			x8 := x1
1554 | 			y8 := T(yNMask|1) + y1
1555 | 			z8 := z1
1556 | 			value += (a8 * a8) * (a8 * a8) * gradCoord3D(seed2, i+primeX, j+(yNMask&(primeY2)), k+primeZ, x8, y8, z8)
1557 | 			skip9 = true
1558 | 		}
1559 | 	}
1560 | 
1561 | 	skipD := false
1562 | 	aA := T(zAFlipMask0) + a0
1563 | 	if aA > 0 {
1564 | 		xA := x0
1565 | 		yA := y0
1566 | 		zA := z0 - T(zNMask|1)
1567 | 		value += (aA * aA) * (aA * aA) * gradCoord3D(seed, i+(xNMask&primeX), j+(yNMask&primeY), k+(^zNMask&primeZ), xA, yA, zA)
1568 | 	} else {
1569 | 		aB := T(xAFlipMask0+yAFlipMask0) + a0
1570 | 		if aB > 0 {
1571 | 			xB := x0 - T(xNMask|1)
1572 | 			yB := y0 - T(yNMask|1)
1573 | 			zB := z0
1574 | 			value += (aB * aB) * (aB * aB) * gradCoord3D(seed, i+(^xNMask&primeX), j+(^yNMask&primeY), k+(zNMask&primeZ), xB, yB, zB)
1575 | 		}
1576 | 
1577 | 		aC := T(zAFlipMask1) + a1
1578 | 		if aC > 0 {
1579 | 			xC := x1
1580 | 			yC := y1
1581 | 			zC := T(zNMask|1) + z1
1582 | 			value += (aC * aC) * (aC * aC) * gradCoord3D(seed2, i+primeX, j+primeY, k+(zNMask&(primeZ2)), xC, yC, zC)
1583 | 			skipD = true
1584 | 		}
1585 | 	}
1586 | 
1587 | 	if !skip5 {
1588 | 		a5 := T(yAFlipMask1+zAFlipMask1) + a1
1589 | 		if a5 > 0 {
1590 | 			x5 := x1
1591 | 			y5 := T(yNMask|1) + y1
1592 | 			z5 := T(zNMask|1) + z1
1593 | 			value += (a5 * a5) * (a5 * a5) * gradCoord3D(seed2, i+primeX, j+(yNMask&(primeY2)), k+(zNMask&(primeZ2)), x5, y5, z5)
1594 | 		}
1595 | 	}
1596 | 
1597 | 	if !skip9 {
1598 | 		a9 := T(xAFlipMask1+zAFlipMask1) + a1
1599 | 		if a9 > 0 {
1600 | 			x9 := T(xNMask|1) + x1
1601 | 			y9 := y1
1602 | 			z9 := T(zNMask|1) + z1
1603 | 			value += (a9 * a9) * (a9 * a9) * gradCoord3D(seed2, i+(xNMask&(primeX2)), j+primeY, k+(zNMask&(primeZ2)), x9, y9, z9)
1604 | 		}
1605 | 	}
1606 | 
1607 | 	if !skipD {
1608 | 		aD := T(xAFlipMask1+yAFlipMask1) + a1
1609 | 		if aD > 0 {
1610 | 			xD := T(xNMask|1) + x1
1611 | 			yD := T(yNMask|1) + y1
1612 | 			zD := z1
1613 | 			value += (aD * aD) * (aD * aD) * gradCoord3D(seed2, i+(xNMask&(primeX2)), j+(yNMask&(primeY2)), k+primeZ, xD, yD, zD)
1614 | 		}
1615 | 	}
1616 | 
1617 | 	return value * 9.046026385208288
1618 | }
1619 | 
1620 | // Cellular Noise
1621 | 
1622 | func singleCellular2D[T Float](state *State[T], seed int, x, y T) T {
1623 | 	xr := fastRound(x)
1624 | 	yr := fastRound(y)
1625 | 
1626 | 	// One of the more painful aspects of Go generics..
1627 | 	var dist0, dist1 T
1628 | 	switch dptr := any(&dist0).(type) {
1629 | 	case *float32:
1630 | 		*dptr = math.MaxFloat32
1631 | 	case *float64:
1632 | 		*dptr = math.MaxFloat64
1633 | 	}
1634 | 	dist1 = dist0
1635 | 
1636 | 	var closestHash uint32
1637 | 	// jitter := 0.5 * state.CellularJitterMod
1638 | 	jitter := 0.43701595 * state.CellularJitterMod
1639 | 
1640 | 	xPrimed := (xr - 1) * primeX
1641 | 	yPrimedBase := (yr - 1) * primeY
1642 | 
1643 | 	switch state.CellularDistanceFunc {
1644 | 	default:
1645 | 		for xi := xr - 1; xi <= xr+1; xi++ {
1646 | 			yPrimed := yPrimedBase
1647 | 
1648 | 			for yi := yr - 1; yi <= yr+1; yi++ {
1649 | 				hash := hash2D(seed, xPrimed, yPrimed)
1650 | 				idx := hash & (255 << 1)
1651 | 
1652 | 				vecX := (T(xi) - x) + T(randVecs2D[idx])*jitter
1653 | 				vecY := (T(yi) - y) + T(randVecs2D[idx|1])*jitter
1654 | 
1655 | 				newDistance := vecX*vecX + vecY*vecY
1656 | 
1657 | 				dist1 = fastMax(fastMin(dist1, newDistance), dist0)
1658 | 				if newDistance < dist0 {
1659 | 					dist0 = newDistance
1660 | 					closestHash = hash
1661 | 				}
1662 | 				yPrimed += primeY
1663 | 			}
1664 | 			xPrimed += primeX
1665 | 		}
1666 | 	case CellularDistanceManhattan:
1667 | 		for xi := xr - 1; xi <= xr+1; xi++ {
1668 | 			yPrimed := yPrimedBase
1669 | 
1670 | 			for yi := yr - 1; yi <= yr+1; yi++ {
1671 | 				hash := hash2D(seed, xPrimed, yPrimed)
1672 | 				idx := hash & (255 << 1)
1673 | 
1674 | 				vecX := (T(xi) - x) + T(randVecs2D[idx])*jitter
1675 | 				vecY := (T(yi) - y) + T(randVecs2D[idx|1])*jitter
1676 | 				newDistance := fastAbs(vecX) + fastAbs(vecY)
1677 | 
1678 | 				dist1 = fastMax(fastMin(dist1, newDistance), dist0)
1679 | 				if newDistance < dist0 {
1680 | 					dist0 = newDistance
1681 | 					closestHash = hash
1682 | 				}
1683 | 				yPrimed += primeY
1684 | 			}
1685 | 			xPrimed += primeX
1686 | 		}
1687 | 	case CellularDistanceHybrid:
1688 | 		for xi := xr - 1; xi <= xr+1; xi++ {
1689 | 			yPrimed := yPrimedBase
1690 | 			for yi := yr - 1; yi <= yr+1; yi++ {
1691 | 				hash := hash2D(seed, xPrimed, yPrimed)
1692 | 				idx := hash & (255 << 1)
1693 | 
1694 | 				vecX := (T(xi) - x) + T(randVecs2D[idx])*jitter
1695 | 				vecY := (T(yi) - y) + T(randVecs2D[idx|1])*jitter
1696 | 
1697 | 				newDistance := (fastAbs(vecX) + fastAbs(vecY)) + (vecX*vecX + vecY*vecY)
1698 | 
1699 | 				dist1 = fastMax(fastMin(dist1, newDistance), dist0)
1700 | 				if newDistance < dist0 {
1701 | 					dist0 = newDistance
1702 | 					closestHash = hash
1703 | 				}
1704 | 				yPrimed += primeY
1705 | 			}
1706 | 			xPrimed += primeX
1707 | 		}
1708 | 	}
1709 | 
1710 | 	if state.CellularDistanceFunc == CellularDistanceEuclidean && state.CellularReturnType >= CellularReturnDistance {
1711 | 		dist0 = fastSqrt(dist0)
1712 | 		if state.CellularReturnType >= CellularReturnDistance2 {
1713 | 			dist1 = fastSqrt(dist1)
1714 | 		}
1715 | 	}
1716 | 
1717 | 	switch state.CellularReturnType {
1718 | 	case CellularReturnCellValue:
1719 | 		return T(closestHash) * (1 / 2147483648.0)
1720 | 	case CellularReturnDistance:
1721 | 		return dist0 - 1
1722 | 	case CellularReturnDistance2:
1723 | 		return dist1 - 1
1724 | 	case CellularReturnDistance2Add:
1725 | 		return (dist1+dist0)*0.5 - 1
1726 | 	case CellularReturnDistance2Sub:
1727 | 		return dist1 - dist0 - 1
1728 | 	case CellularReturnDistance2Mul:
1729 | 		return dist1*dist0*0.5 - 1
1730 | 	case CellularReturnDistance2Div:
1731 | 		return dist0/dist1 - 1
1732 | 	default:
1733 | 		return 0
1734 | 	}
1735 | }
1736 | 
1737 | func singleCellular3D[T Float](state *State[T], seed int, x, y, z T) T {
1738 | 	xr := fastRound(x)
1739 | 	yr := fastRound(y)
1740 | 	zr := fastRound(z)
1741 | 
1742 | 	var dist0, dist1 T
1743 | 	switch dptr := any(&dist0).(type) {
1744 | 	case *float32:
1745 | 		*dptr = math.MaxFloat32
1746 | 	case *float64:
1747 | 		*dptr = math.MaxFloat64
1748 | 	}
1749 | 	dist1 = dist0
1750 | 
1751 | 	var closestHash uint32
1752 | 	jitter := 0.39614353 * state.CellularJitterMod
1753 | 
1754 | 	xPrimed := (xr - 1) * primeX
1755 | 	yPrimedBase := (yr - 1) * primeY
1756 | 	zPrimedBase := (zr - 1) * primeZ
1757 | 
1758 | 	switch state.CellularDistanceFunc {
1759 | 	default:
1760 | 		for xi := xr - 1; xi <= xr+1; xi++ {
1761 | 			yPrimed := yPrimedBase
1762 | 
1763 | 			for yi := yr - 1; yi <= yr+1; yi++ {
1764 | 				zPrimed := zPrimedBase
1765 | 
1766 | 				for zi := zr - 1; zi <= zr+1; zi++ {
1767 | 					hash := hash3D(seed, xPrimed, yPrimed, zPrimed)
1768 | 					idx := hash & (255 << 2)
1769 | 
1770 | 					vecX := (T(xi) - x) + T(randVecs3D[idx])*jitter
1771 | 					vecY := (T(yi) - y) + T(randVecs3D[idx|1])*jitter
1772 | 					vecZ := (T(zi) - z) + T(randVecs3D[idx|2])*jitter
1773 | 
1774 | 					newDistance := vecX*vecX + vecY*vecY + vecZ*vecZ
1775 | 
1776 | 					dist1 = fastMax(fastMin(dist1, newDistance), dist0)
1777 | 					if newDistance < dist0 {
1778 | 						dist0 = newDistance
1779 | 						closestHash = hash
1780 | 					}
1781 | 					zPrimed += primeZ
1782 | 				}
1783 | 				yPrimed += primeY
1784 | 			}
1785 | 			xPrimed += primeX
1786 | 		}
1787 | 	case CellularDistanceManhattan:
1788 | 		for xi := xr - 1; xi <= xr+1; xi++ {
1789 | 			yPrimed := yPrimedBase
1790 | 
1791 | 			for yi := yr - 1; yi <= yr+1; yi++ {
1792 | 				zPrimed := zPrimedBase
1793 | 
1794 | 				for zi := zr - 1; zi <= zr+1; zi++ {
1795 | 					hash := hash3D(seed, xPrimed, yPrimed, zPrimed)
1796 | 					idx := hash & (255 << 2)
1797 | 
1798 | 					vecX := (T(xi) - x) + T(randVecs3D[idx])*jitter
1799 | 					vecY := (T(yi) - y) + T(randVecs3D[idx|1])*jitter
1800 | 					vecZ := (T(zi) - z) + T(randVecs3D[idx|2])*jitter
1801 | 
1802 | 					newDistance := fastAbs(vecX) + fastAbs(vecY) + fastAbs(vecZ)
1803 | 
1804 | 					dist1 = fastMax(fastMin(dist1, newDistance), dist0)
1805 | 					if newDistance < dist0 {
1806 | 						dist0 = newDistance
1807 | 						closestHash = hash
1808 | 					}
1809 | 					zPrimed += primeZ
1810 | 				}
1811 | 				yPrimed += primeY
1812 | 			}
1813 | 			xPrimed += primeX
1814 | 		}
1815 | 	case CellularDistanceHybrid:
1816 | 		for xi := xr - 1; xi <= xr+1; xi++ {
1817 | 			yPrimed := yPrimedBase
1818 | 
1819 | 			for yi := yr - 1; yi <= yr+1; yi++ {
1820 | 				zPrimed := zPrimedBase
1821 | 
1822 | 				for zi := zr - 1; zi <= zr+1; zi++ {
1823 | 					hash := hash3D(seed, xPrimed, yPrimed, zPrimed)
1824 | 					idx := hash & (255 << 2)
1825 | 
1826 | 					vecX := (T(xi) - x) + T(randVecs3D[idx])*jitter
1827 | 					vecY := (T(yi) - y) + T(randVecs3D[idx|1])*jitter
1828 | 					vecZ := (T(zi) - z) + T(randVecs3D[idx|2])*jitter
1829 | 
1830 | 					newDistance := (fastAbs(vecX) + fastAbs(vecY) + fastAbs(vecZ)) + (vecX*vecX + vecY*vecY + vecZ*vecZ)
1831 | 
1832 | 					dist1 = fastMax(fastMin(dist1, newDistance), dist0)
1833 | 					if newDistance < dist0 {
1834 | 						dist0 = newDistance
1835 | 						closestHash = hash
1836 | 					}
1837 | 					zPrimed += primeZ
1838 | 				}
1839 | 				yPrimed += primeY
1840 | 			}
1841 | 			xPrimed += primeX
1842 | 		}
1843 | 	}
1844 | 
1845 | 	if state.CellularDistanceFunc == CellularDistanceEuclidean && state.CellularReturnType >= CellularReturnDistance {
1846 | 		dist0 = fastSqrt(dist0)
1847 | 		if state.CellularReturnType >= CellularReturnDistance2 {
1848 | 			dist1 = fastSqrt(dist1)
1849 | 		}
1850 | 	}
1851 | 
1852 | 	switch state.CellularReturnType {
1853 | 	case CellularReturnCellValue:
1854 | 		return T(closestHash) * (1 / 2147483648.0)
1855 | 	case CellularReturnDistance:
1856 | 		return dist0 - 1
1857 | 	case CellularReturnDistance2:
1858 | 		return dist1 - 1
1859 | 	case CellularReturnDistance2Add:
1860 | 		return (dist1+dist0)*0.5 - 1
1861 | 	case CellularReturnDistance2Sub:
1862 | 		return dist1 - dist0 - 1
1863 | 	case CellularReturnDistance2Mul:
1864 | 		return dist1*dist0*0.5 - 1
1865 | 	case CellularReturnDistance2Div:
1866 | 		return dist0/dist1 - 1
1867 | 	default:
1868 | 		return 0
1869 | 	}
1870 | }
1871 | 
1872 | // Perlin Noise
1873 | 
1874 | func singlePerlin2D[T Float](state *State[T], seed int, x, y T) T {
1875 | 	x0 := fastFloor(x)
1876 | 	y0 := fastFloor(y)
1877 | 
1878 | 	xd0 := x - T(x0)
1879 | 	yd0 := y - T(y0)
1880 | 	xd1 := xd0 - 1
1881 | 	yd1 := yd0 - 1
1882 | 
1883 | 	xs := interpQuintic(xd0)
1884 | 	ys := interpQuintic(yd0)
1885 | 
1886 | 	x0 *= primeX
1887 | 	y0 *= primeY
1888 | 	x1 := x0 + primeX
1889 | 	y1 := y0 + primeY
1890 | 
1891 | 	xf0 := lerp(gradCoord2D(seed, x0, y0, xd0, yd0), gradCoord2D(seed, x1, y0, xd1, yd0), xs)
1892 | 	xf1 := lerp(gradCoord2D(seed, x0, y1, xd0, yd1), gradCoord2D(seed, x1, y1, xd1, yd1), xs)
1893 | 
1894 | 	return lerp(xf0, xf1, ys) * 1.4247691104677813
1895 | }
1896 | 
1897 | func singlePerlin3D[T Float](state *State[T], seed int, x, y, z T) T {
1898 | 	x0 := fastFloor(x)
1899 | 	y0 := fastFloor(y)
1900 | 	z0 := fastFloor(z)
1901 | 
1902 | 	xd0 := x - T(x0)
1903 | 	yd0 := y - T(y0)
1904 | 	zd0 := z - T(z0)
1905 | 	xd1 := xd0 - 1
1906 | 	yd1 := yd0 - 1
1907 | 	zd1 := zd0 - 1
1908 | 
1909 | 	xs := interpQuintic(xd0)
1910 | 	ys := interpQuintic(yd0)
1911 | 	zs := interpQuintic(zd0)
1912 | 
1913 | 	x0 *= primeX
1914 | 	y0 *= primeY
1915 | 	z0 *= primeZ
1916 | 	x1 := x0 + primeX
1917 | 	y1 := y0 + primeY
1918 | 	z1 := z0 + primeZ
1919 | 
1920 | 	xf00 := lerp(gradCoord3D(seed, x0, y0, z0, xd0, yd0, zd0), gradCoord3D(seed, x1, y0, z0, xd1, yd0, zd0), xs)
1921 | 	xf10 := lerp(gradCoord3D(seed, x0, y1, z0, xd0, yd1, zd0), gradCoord3D(seed, x1, y1, z0, xd1, yd1, zd0), xs)
1922 | 	xf01 := lerp(gradCoord3D(seed, x0, y0, z1, xd0, yd0, zd1), gradCoord3D(seed, x1, y0, z1, xd1, yd0, zd1), xs)
1923 | 	xf11 := lerp(gradCoord3D(seed, x0, y1, z1, xd0, yd1, zd1), gradCoord3D(seed, x1, y1, z1, xd1, yd1, zd1), xs)
1924 | 
1925 | 	yf0 := lerp(xf00, xf10, ys)
1926 | 	yf1 := lerp(xf01, xf11, ys)
1927 | 
1928 | 	return lerp(yf0, yf1, zs) * 0.964921414852142333984375
1929 | }
1930 | 
1931 | // Value Cubic
1932 | 
1933 | func singleValueCubic2D[T Float](state *State[T], seed int, x, y T) T {
1934 | 	x1 := fastFloor(x)
1935 | 	y1 := fastFloor(y)
1936 | 
1937 | 	xs := x - T(x1)
1938 | 	ys := y - T(y1)
1939 | 
1940 | 	x1 *= primeX
1941 | 	y1 *= primeY
1942 | 
1943 | 	x0 := x1 - primeX
1944 | 	y0 := y1 - primeY
1945 | 	x2 := x1 + primeX
1946 | 	y2 := y1 + primeY
1947 | 	x3 := x1 + primeX2
1948 | 	y3 := y1 + primeY2
1949 | 
1950 | 	return cubicLerp(
1951 | 		cubicLerp(valCoord2D[T](seed, x0, y0), valCoord2D[T](seed, x1, y0), valCoord2D[T](seed, x2, y0), valCoord2D[T](seed, x3, y0), xs),
1952 | 		cubicLerp(valCoord2D[T](seed, x0, y1), valCoord2D[T](seed, x1, y1), valCoord2D[T](seed, x2, y1), valCoord2D[T](seed, x3, y1), xs),
1953 | 		cubicLerp(valCoord2D[T](seed, x0, y2), valCoord2D[T](seed, x1, y2), valCoord2D[T](seed, x2, y2), valCoord2D[T](seed, x3, y2), xs),
1954 | 		cubicLerp(valCoord2D[T](seed, x0, y3), valCoord2D[T](seed, x1, y3), valCoord2D[T](seed, x2, y3), valCoord2D[T](seed, x3, y3), xs), ys) * (1 / (1.5 * 1.5))
1955 | }
1956 | 
1957 | func singleValueCubic3D[T Float](state *State[T], seed int, x, y, z T) T {
1958 | 	x1 := fastFloor(x)
1959 | 	y1 := fastFloor(y)
1960 | 	z1 := fastFloor(z)
1961 | 
1962 | 	xs := x - T(x1)
1963 | 	ys := y - T(y1)
1964 | 	zs := z - T(z1)
1965 | 
1966 | 	x1 *= primeX
1967 | 	y1 *= primeY
1968 | 	z1 *= primeZ
1969 | 
1970 | 	x0 := x1 - primeX
1971 | 	y0 := y1 - primeY
1972 | 	z0 := z1 - primeZ
1973 | 	x2 := x1 + primeX
1974 | 	y2 := y1 + primeY
1975 | 	z2 := z1 + primeZ
1976 | 	x3 := x1 + primeX2
1977 | 	y3 := y1 + primeY2
1978 | 	z3 := z1 + primeZ2
1979 | 
1980 | 	return cubicLerp(
1981 | 		cubicLerp(
1982 | 			cubicLerp(valCoord3D[T](seed, x0, y0, z0), valCoord3D[T](seed, x1, y0, z0), valCoord3D[T](seed, x2, y0, z0), valCoord3D[T](seed, x3, y0, z0), xs),
1983 | 			cubicLerp(valCoord3D[T](seed, x0, y1, z0), valCoord3D[T](seed, x1, y1, z0), valCoord3D[T](seed, x2, y1, z0), valCoord3D[T](seed, x3, y1, z0), xs),
1984 | 			cubicLerp(valCoord3D[T](seed, x0, y2, z0), valCoord3D[T](seed, x1, y2, z0), valCoord3D[T](seed, x2, y2, z0), valCoord3D[T](seed, x3, y2, z0), xs),
1985 | 			cubicLerp(valCoord3D[T](seed, x0, y3, z0), valCoord3D[T](seed, x1, y3, z0), valCoord3D[T](seed, x2, y3, z0), valCoord3D[T](seed, x3, y3, z0), xs),
1986 | 			ys),
1987 | 		cubicLerp(
1988 | 			cubicLerp(valCoord3D[T](seed, x0, y0, z1), valCoord3D[T](seed, x1, y0, z1), valCoord3D[T](seed, x2, y0, z1), valCoord3D[T](seed, x3, y0, z1), xs),
1989 | 			cubicLerp(valCoord3D[T](seed, x0, y1, z1), valCoord3D[T](seed, x1, y1, z1), valCoord3D[T](seed, x2, y1, z1), valCoord3D[T](seed, x3, y1, z1), xs),
1990 | 			cubicLerp(valCoord3D[T](seed, x0, y2, z1), valCoord3D[T](seed, x1, y2, z1), valCoord3D[T](seed, x2, y2, z1), valCoord3D[T](seed, x3, y2, z1), xs),
1991 | 			cubicLerp(valCoord3D[T](seed, x0, y3, z1), valCoord3D[T](seed, x1, y3, z1), valCoord3D[T](seed, x2, y3, z1), valCoord3D[T](seed, x3, y3, z1), xs),
1992 | 			ys),
1993 | 		cubicLerp(
1994 | 			cubicLerp(valCoord3D[T](seed, x0, y0, z2), valCoord3D[T](seed, x1, y0, z2), valCoord3D[T](seed, x2, y0, z2), valCoord3D[T](seed, x3, y0, z2), xs),
1995 | 			cubicLerp(valCoord3D[T](seed, x0, y1, z2), valCoord3D[T](seed, x1, y1, z2), valCoord3D[T](seed, x2, y1, z2), valCoord3D[T](seed, x3, y1, z2), xs),
1996 | 			cubicLerp(valCoord3D[T](seed, x0, y2, z2), valCoord3D[T](seed, x1, y2, z2), valCoord3D[T](seed, x2, y2, z2), valCoord3D[T](seed, x3, y2, z2), xs),
1997 | 			cubicLerp(valCoord3D[T](seed, x0, y3, z2), valCoord3D[T](seed, x1, y3, z2), valCoord3D[T](seed, x2, y3, z2), valCoord3D[T](seed, x3, y3, z2), xs),
1998 | 			ys),
1999 | 		cubicLerp(
2000 | 			cubicLerp(valCoord3D[T](seed, x0, y0, z3), valCoord3D[T](seed, x1, y0, z3), valCoord3D[T](seed, x2, y0, z3), valCoord3D[T](seed, x3, y0, z3), xs),
2001 | 			cubicLerp(valCoord3D[T](seed, x0, y1, z3), valCoord3D[T](seed, x1, y1, z3), valCoord3D[T](seed, x2, y1, z3), valCoord3D[T](seed, x3, y1, z3), xs),
2002 | 			cubicLerp(valCoord3D[T](seed, x0, y2, z3), valCoord3D[T](seed, x1, y2, z3), valCoord3D[T](seed, x2, y2, z3), valCoord3D[T](seed, x3, y2, z3), xs),
2003 | 			cubicLerp(valCoord3D[T](seed, x0, y3, z3), valCoord3D[T](seed, x1, y3, z3), valCoord3D[T](seed, x2, y3, z3), valCoord3D[T](seed, x3, y3, z3), xs),
2004 | 			ys),
2005 | 		zs) * (1 / (1.5 * 1.5 * 1.5))
2006 | }
2007 | 
2008 | // Value noise
2009 | 
2010 | func singleValue2D[T Float](state *State[T], seed int, x, y T) T {
2011 | 	x0 := fastFloor(x)
2012 | 	y0 := fastFloor(y)
2013 | 
2014 | 	xs := interpHermite(x - T(x0))
2015 | 	ys := interpHermite(y - T(y0))
2016 | 
2017 | 	x0 *= primeX
2018 | 	y0 *= primeY
2019 | 	x1 := x0 + primeX
2020 | 	y1 := y0 + primeY
2021 | 
2022 | 	xf0 := lerp(valCoord2D[T](seed, x0, y0), valCoord2D[T](seed, x1, y0), xs)
2023 | 	xf1 := lerp(valCoord2D[T](seed, x0, y1), valCoord2D[T](seed, x1, y1), xs)
2024 | 
2025 | 	return lerp(xf0, xf1, ys)
2026 | }
2027 | 
2028 | func singleValue3D[T Float](state *State[T], seed int, x, y, z T) T {
2029 | 	x0 := fastFloor(x)
2030 | 	y0 := fastFloor(y)
2031 | 	z0 := fastFloor(z)
2032 | 
2033 | 	xs := interpHermite(x - T(x0))
2034 | 	ys := interpHermite(y - T(y0))
2035 | 	zs := interpHermite(z - T(z0))
2036 | 
2037 | 	x0 *= primeX
2038 | 	y0 *= primeY
2039 | 	z0 *= primeZ
2040 | 	x1 := x0 + primeX
2041 | 	y1 := y0 + primeY
2042 | 	z1 := z0 + primeZ
2043 | 
2044 | 	xf00 := lerp(valCoord3D[T](seed, x0, y0, z0), valCoord3D[T](seed, x1, y0, z0), xs)
2045 | 	xf10 := lerp(valCoord3D[T](seed, x0, y1, z0), valCoord3D[T](seed, x1, y1, z0), xs)
2046 | 	xf01 := lerp(valCoord3D[T](seed, x0, y0, z1), valCoord3D[T](seed, x1, y0, z1), xs)
2047 | 	xf11 := lerp(valCoord3D[T](seed, x0, y1, z1), valCoord3D[T](seed, x1, y1, z1), xs)
2048 | 
2049 | 	yf0 := lerp(xf00, xf10, ys)
2050 | 	yf1 := lerp(xf01, xf11, ys)
2051 | 
2052 | 	return lerp(yf0, yf1, zs)
2053 | }
2054 | 
2055 | // Domain Warp
2056 | 
2057 | func doSingleDomainWarp2D[T Float](state *State[T], seed int, amp, freq, x, y T, xp, yp *T) {
2058 | 	switch state.DomainWarpType {
2059 | 	case DomainWarpOpenSimplex2:
2060 | 		singleDomainWarpSimplexGradient(seed, amp*38.283687591552734375, freq, x, y, xp, yp, false)
2061 | 	case DomainWarpOpenSimplex2Reduced:
2062 | 		singleDomainWarpSimplexGradient(seed, amp*16.0, freq, x, y, xp, yp, true)
2063 | 	case DomainWarpBasicGrid:
2064 | 		singleDomainWarpBasicGrid2D(seed, amp, freq, x, y, xp, yp)
2065 | 	}
2066 | }
2067 | 
2068 | func doSingleDomainWarp3D[T Float](state *State[T], seed int, amp, freq, x, y, z T, xp, yp, zp *T) {
2069 | 	switch state.DomainWarpType {
2070 | 	case DomainWarpOpenSimplex2:
2071 | 		singleDomainWarpOpenSimplex2Gradient(seed, amp*32.69428253173828125, freq, x, y, z, xp, yp, zp, false)
2072 | 	case DomainWarpOpenSimplex2Reduced:
2073 | 		singleDomainWarpOpenSimplex2Gradient(seed, amp*7.71604938271605, freq, x, y, z, xp, yp, zp, true)
2074 | 	case DomainWarpBasicGrid:
2075 | 		singleDomainWarpBasicGrid3D(seed, amp, freq, x, y, z, xp, yp, zp)
2076 | 	}
2077 | }
2078 | 
2079 | // Domain Warp Single Wrapper
2080 | 
2081 | func domainWarpSingle2D[T Float](state *State[T], x, y *T) {
2082 | 	seed := state.Seed
2083 | 	amp := state.DomainWarpAmp * calculateFractalBounding(state)
2084 | 	freq := state.Frequency
2085 | 
2086 | 	xs := *x
2087 | 	ys := *y
2088 | 	transformDomainWarpCoordinate2D(state, &xs, &ys)
2089 | 
2090 | 	doSingleDomainWarp2D(state, seed, amp, freq, xs, ys, x, y)
2091 | }
2092 | 
2093 | func domainWarpSingle3D[T Float](state *State[T], x, y, z *T) {
2094 | 	seed := state.Seed
2095 | 	amp := state.DomainWarpAmp * calculateFractalBounding(state)
2096 | 	freq := state.Frequency
2097 | 
2098 | 	xs := *x
2099 | 	ys := *y
2100 | 	zs := *z
2101 | 	transformDomainWarpCoordinate3D(state, &xs, &ys, &zs)
2102 | 
2103 | 	doSingleDomainWarp3D(state, seed, amp, freq, xs, ys, zs, x, y, z)
2104 | }
2105 | 
2106 | // Domain Warp Fractal Progressive
2107 | 
2108 | func domainWarpFractalProgressive2D[T Float](state *State[T], x, y *T) {
2109 | 	seed := state.Seed
2110 | 	amp := state.DomainWarpAmp * calculateFractalBounding(state)
2111 | 	freq := state.Frequency
2112 | 
2113 | 	for i := 0; i < state.Octaves; i++ {
2114 | 		xs := *x
2115 | 		ys := *y
2116 | 		transformDomainWarpCoordinate2D(state, &xs, &ys)
2117 | 
2118 | 		doSingleDomainWarp2D(state, seed, amp, freq, xs, ys, x, y)
2119 | 
2120 | 		seed++
2121 | 		amp *= state.Gain
2122 | 		freq *= state.Lacunarity
2123 | 	}
2124 | }
2125 | 
2126 | func domainWarpFractalProgressive3D[T Float](state *State[T], x, y, z *T) {
2127 | 	seed := state.Seed
2128 | 	amp := state.DomainWarpAmp * calculateFractalBounding(state)
2129 | 	freq := state.Frequency
2130 | 
2131 | 	for i := 0; i < state.Octaves; i++ {
2132 | 		xs := *x
2133 | 		ys := *y
2134 | 		zs := *z
2135 | 		transformDomainWarpCoordinate3D(state, &xs, &ys, &zs)
2136 | 
2137 | 		doSingleDomainWarp3D(state, seed, amp, freq, xs, ys, zs, x, y, z)
2138 | 
2139 | 		seed++
2140 | 		amp *= state.Gain
2141 | 		freq *= state.Lacunarity
2142 | 	}
2143 | }
2144 | 
2145 | // Domain Warp Fractal Independent
2146 | 
2147 | func domainWarpFractalIndependent2D[T Float](state *State[T], x, y *T) {
2148 | 	xs := *x
2149 | 	ys := *y
2150 | 	transformDomainWarpCoordinate2D(state, &xs, &ys)
2151 | 
2152 | 	seed := state.Seed
2153 | 	amp := state.DomainWarpAmp * calculateFractalBounding(state)
2154 | 	freq := state.Frequency
2155 | 
2156 | 	for i := 0; i < state.Octaves; i++ {
2157 | 		doSingleDomainWarp2D(state, seed, amp, freq, xs, ys, x, y)
2158 | 
2159 | 		seed++
2160 | 		amp *= state.Gain
2161 | 		freq *= state.Lacunarity
2162 | 	}
2163 | }
2164 | 
2165 | func domainWarpFractalIndependent3D[T Float](state *State[T], x, y, z *T) {
2166 | 	xs := *x
2167 | 	ys := *y
2168 | 	zs := *z
2169 | 	transformDomainWarpCoordinate3D(state, &xs, &ys, &zs)
2170 | 
2171 | 	seed := state.Seed
2172 | 	amp := state.DomainWarpAmp * calculateFractalBounding(state)
2173 | 	freq := state.Frequency
2174 | 
2175 | 	for i := 0; i < state.Octaves; i++ {
2176 | 		doSingleDomainWarp3D(state, seed, amp, freq, xs, ys, zs, x, y, z)
2177 | 
2178 | 		seed++
2179 | 		amp *= state.Gain
2180 | 		freq *= state.Lacunarity
2181 | 	}
2182 | }
2183 | 
2184 | // Domain Warp Basic Grid
2185 | 
2186 | func singleDomainWarpBasicGrid2D[T Float](seed int, warpAmp, frequency, x, y T, xp, yp *T) {
2187 | 	xf := x * frequency
2188 | 	yf := y * frequency
2189 | 
2190 | 	x0 := fastFloor(xf)
2191 | 	y0 := fastFloor(yf)
2192 | 
2193 | 	xs := interpHermite(xf - T(x0))
2194 | 	ys := interpHermite(yf - T(y0))
2195 | 
2196 | 	x0 *= primeX
2197 | 	y0 *= primeY
2198 | 	x1 := x0 + primeX
2199 | 	y1 := y0 + primeY
2200 | 
2201 | 	idx0 := hash2D(seed, x0, y0) & (255 << 1)
2202 | 	idx1 := hash2D(seed, x1, y0) & (255 << 1)
2203 | 
2204 | 	lx0x := lerp(T(randVecs2D[idx0]), T(randVecs2D[idx1]), xs)
2205 | 	ly0x := lerp(T(randVecs2D[idx0|1]), T(randVecs2D[idx1|1]), xs)
2206 | 
2207 | 	idx0 = hash2D(seed, x0, y1) & (255 << 1)
2208 | 	idx1 = hash2D(seed, x1, y1) & (255 << 1)
2209 | 
2210 | 	lx1x := lerp(T(randVecs2D[idx0]), T(randVecs2D[idx1]), xs)
2211 | 	ly1x := lerp(T(randVecs2D[idx0|1]), T(randVecs2D[idx1|1]), xs)
2212 | 
2213 | 	*xp += lerp(lx0x, lx1x, ys) * warpAmp
2214 | 	*yp += lerp(ly0x, ly1x, ys) * warpAmp
2215 | }
2216 | 
2217 | func singleDomainWarpBasicGrid3D[T Float](seed int, warpAmp, frequency, x, y, z T, xp, yp, zp *T) {
2218 | 	xf := x * frequency
2219 | 	yf := y * frequency
2220 | 	zf := z * frequency
2221 | 
2222 | 	x0 := fastFloor(xf)
2223 | 	y0 := fastFloor(yf)
2224 | 	z0 := fastFloor(zf)
2225 | 
2226 | 	xs := interpHermite(xf - T(x0))
2227 | 	ys := interpHermite(yf - T(y0))
2228 | 	zs := interpHermite(zf - T(z0))
2229 | 
2230 | 	x0 *= primeX
2231 | 	y0 *= primeY
2232 | 	z0 *= primeZ
2233 | 	x1 := x0 + primeX
2234 | 	y1 := y0 + primeY
2235 | 	z1 := z0 + primeZ
2236 | 
2237 | 	idx0 := hash3D(seed, x0, y0, z0) & (255 << 2)
2238 | 	idx1 := hash3D(seed, x1, y0, z0) & (255 << 2)
2239 | 
2240 | 	lx0x := lerp(T(randVecs3D[idx0]), T(randVecs3D[idx1]), xs)
2241 | 	ly0x := lerp(T(randVecs3D[idx0|1]), T(randVecs3D[idx1|1]), xs)
2242 | 	lz0x := lerp(T(randVecs3D[idx0|2]), T(randVecs3D[idx1|2]), xs)
2243 | 
2244 | 	idx0 = hash3D(seed, x0, y1, z0) & (255 << 2)
2245 | 	idx1 = hash3D(seed, x1, y1, z0) & (255 << 2)
2246 | 
2247 | 	lx1x := lerp(T(randVecs3D[idx0]), T(randVecs3D[idx1]), xs)
2248 | 	ly1x := lerp(T(randVecs3D[idx0|1]), T(randVecs3D[idx1|1]), xs)
2249 | 	lz1x := lerp(T(randVecs3D[idx0|2]), T(randVecs3D[idx1|2]), xs)
2250 | 
2251 | 	lx0y := lerp(lx0x, lx1x, ys)
2252 | 	ly0y := lerp(ly0x, ly1x, ys)
2253 | 	lz0y := lerp(lz0x, lz1x, ys)
2254 | 
2255 | 	idx0 = hash3D(seed, x0, y0, z1) & (255 << 2)
2256 | 	idx1 = hash3D(seed, x1, y0, z1) & (255 << 2)
2257 | 
2258 | 	lx0x = lerp(T(randVecs3D[idx0]), T(randVecs3D[idx1]), xs)
2259 | 	ly0x = lerp(T(randVecs3D[idx0|1]), T(randVecs3D[idx1|1]), xs)
2260 | 	lz0x = lerp(T(randVecs3D[idx0|2]), T(randVecs3D[idx1|2]), xs)
2261 | 
2262 | 	idx0 = hash3D(seed, x0, y1, z1) & (255 << 2)
2263 | 	idx1 = hash3D(seed, x1, y1, z1) & (255 << 2)
2264 | 
2265 | 	lx1x = lerp(T(randVecs3D[idx0]), T(randVecs3D[idx1]), xs)
2266 | 	ly1x = lerp(T(randVecs3D[idx0|1]), T(randVecs3D[idx1|1]), xs)
2267 | 	lz1x = lerp(T(randVecs3D[idx0|2]), T(randVecs3D[idx1|2]), xs)
2268 | 
2269 | 	*xp += lerp(lx0y, lerp(lx0x, lx1x, ys), zs) * warpAmp
2270 | 	*yp += lerp(ly0y, lerp(ly0x, ly1x, ys), zs) * warpAmp
2271 | 	*zp += lerp(lz0y, lerp(lz0x, lz1x, ys), zs) * warpAmp
2272 | }
2273 | 
2274 | // Domain Warp Simplex/OpenSimplex2
2275 | 
2276 | func singleDomainWarpSimplexGradient[T Float](seed int, warpAmp, frequency, x, y T, xr, yr *T, outGradOnly bool) {
2277 | 	const SQRT3 float64 = 1.7320508075688772935274463415059
2278 | 	const G2 float64 = (3 - SQRT3) / 6
2279 | 
2280 | 	x *= frequency
2281 | 	y *= frequency
2282 | 
2283 | 	i := fastFloor(x)
2284 | 	j := fastFloor(y)
2285 | 	xi := x - T(i)
2286 | 	yi := y - T(j)
2287 | 
2288 | 	t := T(xi+yi) * T(G2)
2289 | 	x0 := xi - t
2290 | 	y0 := yi - t
2291 | 
2292 | 	i *= primeX
2293 | 	j *= primeY
2294 | 
2295 | 	var vx, vy T
2296 | 	a := 0.5 - x0*x0 - y0*y0
2297 | 	if a > 0 {
2298 | 		aaaa := (a * a) * (a * a)
2299 | 		var xo, yo T
2300 | 		if outGradOnly {
2301 | 			gradCoordOut2D(seed, i, j, &xo, &yo)
2302 | 		} else {
2303 | 			gradCoordDual2D(seed, i, j, x0, y0, &xo, &yo)
2304 | 		}
2305 | 		vx += aaaa * xo
2306 | 		vy += aaaa * yo
2307 | 	}
2308 | 
2309 | 	c := T(2*(1-2*G2)*(1/G2-2))*t + (T(-2*(1-2*G2)*(1-2*G2)) + a)
2310 | 	if c > 0 {
2311 | 		x2 := x0 + (2*T(G2) - 1)
2312 | 		y2 := y0 + (2*T(G2) - 1)
2313 | 		cccc := (c * c) * (c * c)
2314 | 		var xo, yo T
2315 | 		if outGradOnly {
2316 | 			gradCoordOut2D(seed, i+primeX, j+primeY, &xo, &yo)
2317 | 		} else {
2318 | 			gradCoordDual2D(seed, i+primeX, j+primeY, x2, y2, &xo, &yo)
2319 | 		}
2320 | 		vx += cccc * xo
2321 | 		vy += cccc * yo
2322 | 	}
2323 | 
2324 | 	if y0 > x0 {
2325 | 		x1 := x0 + T(G2)
2326 | 		y1 := y0 + T(G2-1)
2327 | 		b := 0.5 - x1*x1 - y1*y1
2328 | 		if b > 0 {
2329 | 			bbbb := (b * b) * (b * b)
2330 | 			var xo, yo T
2331 | 			if outGradOnly {
2332 | 				gradCoordOut2D(seed, i, j+primeY, &xo, &yo)
2333 | 			} else {
2334 | 				gradCoordDual2D(seed, i, j+primeY, x1, y1, &xo, &yo)
2335 | 			}
2336 | 			vx += bbbb * xo
2337 | 			vy += bbbb * yo
2338 | 		}
2339 | 	} else {
2340 | 		x1 := x0 + T(G2-1)
2341 | 		y1 := y0 + T(G2)
2342 | 		b := 0.5 - x1*x1 - y1*y1
2343 | 		if b > 0 {
2344 | 			bbbb := (b * b) * (b * b)
2345 | 			var xo, yo T
2346 | 			if outGradOnly {
2347 | 				gradCoordOut2D(seed, i+primeX, j, &xo, &yo)
2348 | 			} else {
2349 | 				gradCoordDual2D(seed, i+primeX, j, x1, y1, &xo, &yo)
2350 | 			}
2351 | 			vx += bbbb * xo
2352 | 			vy += bbbb * yo
2353 | 		}
2354 | 	}
2355 | 
2356 | 	*xr += vx * warpAmp
2357 | 	*yr += vy * warpAmp
2358 | }
2359 | 
2360 | func singleDomainWarpOpenSimplex2Gradient[T Float](seed int, warpAmp, frequency, x, y, z T, xr, yr, zr *T, outGradOnly bool) {
2361 | 	x *= frequency
2362 | 	y *= frequency
2363 | 	z *= frequency
2364 | 
2365 | 	i := fastRound(x)
2366 | 	j := fastRound(y)
2367 | 	k := fastRound(z)
2368 | 	x0 := x - T(i)
2369 | 	y0 := y - T(j)
2370 | 	z0 := z - T(k)
2371 | 
2372 | 	xNSign := int(-x0-1.0) | 1
2373 | 	yNSign := int(-y0-1.0) | 1
2374 | 	zNSign := int(-z0-1.0) | 1
2375 | 
2376 | 	ax0 := T(xNSign) * -x0
2377 | 	ay0 := T(yNSign) * -y0
2378 | 	az0 := T(zNSign) * -z0
2379 | 
2380 | 	i *= primeX
2381 | 	j *= primeY
2382 | 	k *= primeZ
2383 | 
2384 | 	var vx, vy, vz T
2385 | 	a := (0.6 - x0*x0) - (y0*y0 + z0*z0)
2386 | 	for l := 0; l < 2; l++ {
2387 | 		if a > 0 {
2388 | 			aaaa := (a * a) * (a * a)
2389 | 			var xo, yo, zo T
2390 | 			if outGradOnly {
2391 | 				gradCoordOut3D(seed, i, j, k, &xo, &yo, &zo)
2392 | 			} else {
2393 | 				gradCoordDual3D(seed, i, j, k, x0, y0, z0, &xo, &yo, &zo)
2394 | 			}
2395 | 			vx += aaaa * xo
2396 | 			vy += aaaa * yo
2397 | 			vz += aaaa * zo
2398 | 		}
2399 | 
2400 | 		b := a + 1
2401 | 		i1 := i
2402 | 		j1 := j
2403 | 		k1 := k
2404 | 		x1 := x0
2405 | 		y1 := y0
2406 | 		z1 := z0
2407 | 		if ax0 >= ay0 && ax0 >= az0 {
2408 | 			x1 += T(xNSign)
2409 | 			b -= T(xNSign) * 2 * x1
2410 | 			i1 -= xNSign * primeX
2411 | 		} else if ay0 > ax0 && ay0 >= az0 {
2412 | 			y1 += T(yNSign)
2413 | 			b -= T(yNSign) * 2 * y1
2414 | 			j1 -= yNSign * primeY
2415 | 		} else {
2416 | 			z1 += T(zNSign)
2417 | 			b -= T(zNSign) * 2 * z1
2418 | 			k1 -= zNSign * primeZ
2419 | 		}
2420 | 
2421 | 		if b > 0 {
2422 | 			bbbb := (b * b) * (b * b)
2423 | 			var xo, yo, zo T
2424 | 			if outGradOnly {
2425 | 				gradCoordOut3D(seed, i1, j1, k1, &xo, &yo, &zo)
2426 | 			} else {
2427 | 				gradCoordDual3D(seed, i1, j1, k1, x1, y1, z1, &xo, &yo, &zo)
2428 | 			}
2429 | 			vx += bbbb * xo
2430 | 			vy += bbbb * yo
2431 | 			vz += bbbb * zo
2432 | 		}
2433 | 
2434 | 		if l == 1 {
2435 | 			break
2436 | 		}
2437 | 
2438 | 		ax0 = 0.5 - ax0
2439 | 		ay0 = 0.5 - ay0
2440 | 		az0 = 0.5 - az0
2441 | 
2442 | 		x0 = T(xNSign) * ax0
2443 | 		y0 = T(yNSign) * ay0
2444 | 		z0 = T(zNSign) * az0
2445 | 
2446 | 		a += (0.75 - ax0) - (ay0 + az0)
2447 | 
2448 | 		i += (xNSign >> 1) & primeX
2449 | 		j += (yNSign >> 1) & primeY
2450 | 		k += (zNSign >> 1) & primeZ
2451 | 
2452 | 		xNSign = -xNSign
2453 | 		yNSign = -yNSign
2454 | 		zNSign = -zNSign
2455 | 
2456 | 		seed += 1293373
2457 | 	}
2458 | 
2459 | 	*xr += vx * warpAmp
2460 | 	*yr += vy * warpAmp
2461 | 	*zr += vz * warpAmp
2462 | }
2463 | 
2464 | // vim: ts=4
2465 | 


--------------------------------------------------------------------------------
/HLSL/README.md:
--------------------------------------------------------------------------------
 1 | ## Getting Started
 2 | 
 3 | Here's an example for creating a 128x128 array of OpenSimplex2 noise
 4 | 
 5 | ```hlsl
 6 | // Create and configure noise state
 7 | fnl_state noise = fnlCreateState();
 8 | noise.noise_type = FNL_NOISE_OPENSIMPLEX2;
 9 | 
10 | // Gather noise data
11 | float noiseData[128 * 128];
12 | int index = 0;
13 | 
14 | for (int y = 0; y < 128; y++)
15 | {
16 |     for (int x = 0; x < 128; x++) 
17 |     {
18 |         noiseData[index++] = fnlGetNoise2D(noise, x, y);
19 |     }
20 | }
21 | 
22 | // Do something with this data...
23 | ```
24 | 


--------------------------------------------------------------------------------
/Haxe/README.md:
--------------------------------------------------------------------------------
 1 | ## Getting Started
 2 | 
 3 | Here's an example for creating a 128x128 array of OpenSimplex2 noise
 4 | 
 5 | ```haxe
 6 | // Create and configure FastNoise object
 7 | var noise = new FastNoiseLite.Noise();
 8 | noise.noiseType = FastNoiseLite.NoiseType.OpenSimplex2;
 9 | 
10 | // Gather noise data
11 | var width = 128;
12 | var height = 128;
13 | var noiseData: Array<Float> = [];
14 | 
15 | for (x in 0...width) {
16 |     for (y in 0...height) {
17 |         noiseData[x + width * y] = noise.getNoise2D(x, y);
18 |     }
19 | }
20 | 
21 | // Do something with this data...
22 | ```
23 | 


--------------------------------------------------------------------------------
/Java/README.md:
--------------------------------------------------------------------------------
 1 | ## Getting Started
 2 | 
 3 | Here's an example for creating a 128x128 array of OpenSimplex2 noise
 4 | 
 5 | ```java
 6 | // Create and configure FastNoise object
 7 | FastNoiseLite noise = new FastNoiseLite();
 8 | noise.SetNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
 9 | 
10 | // Gather noise data
11 | float[][] noiseData = new float[128][128];
12 | 
13 | for (int x = 0; x < 128; x++)
14 | {
15 |     for (int y = 0; y < 128; y++)
16 |     {
17 |         noiseData[x][y] = noise.GetNoise(x, y);
18 |     }
19 | }
20 | 
21 | // Do something with this data...
22 | ```


--------------------------------------------------------------------------------
/JavaScript/README.md:
--------------------------------------------------------------------------------
 1 | [![npm](https://img.shields.io/npm/v/fastnoise-lite?logo=npm "npm")](https://www.npmjs.com/package/fastnoise-lite) • [GitHub](https://github.com/Auburn/FastNoiseLite)
 2 | 
 3 | # FastNoise Lite
 4 | 
 5 | FastNoise Lite is an extremely portable open source noise generation library with a large selection of noise algorithms. This library focuses on high performance while avoiding platform/language specific features, allowing for easy ports to as many possible languages.
 6 | 
 7 | ## Features
 8 | 
 9 | - 2D & 3D sampling
10 | - OpenSimplex2 noise
11 | - OpenSimplex2S noise
12 | - Cellular (Voronoi) noise
13 | - Perlin noise
14 | - Value noise
15 | - Value Cubic noise
16 | - OpenSimplex2-based domain warp
17 | - Basic Grid Gradient domain warp
18 | - Multiple fractal options for all of the above
19 | 
20 | ## Getting Started
21 | 
22 | ### Using FastNoise Lite with npm
23 | 
24 | To begin install the npm package **fastnoise-lite** with
25 | 
26 | 
27 | Note FastNoise Lite does **not** support the node.js require(''); function.
28 | Instead, enable ES6 modules and **import**.
29 | 
30 | ```javascript
31 | import FastNoiseLite from "fastnoise-lite";
32 | 
33 | let noise = new FastNoiseLite();
34 | ```
35 | 
36 | ### Creating a 128x128 Array of OpenSimplex2 Noise
37 | 
38 | ```javascript
39 | // Create and configure FastNoiseLite object
40 | let noise = new FastNoiseLite();
41 | noise.SetNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
42 | 
43 | // Gather noise data
44 | let noiseData = [];
45 | 
46 | for (let x = 0; x < 128; x++) {
47 |     noiseData[x] = [];
48 | 
49 |     for (let y = 0; y < 128; y++) {        
50 |         noiseData[x][y] = noise.GetNoise(x,y);
51 |     }
52 | }
53 | 
54 | // Do something with this data...
55 | ```
56 | 
57 | ### Internal Method Overloading
58 | 
59 | Since JavaScript does not support method overloading it has been simulated to make the user experience more continuous
60 | between language versions.
61 | 
62 | Some of the code has been changed to use switch statements since it provided a minor performance boost in some small 
63 | frequently used places eg the _Hash methods.
64 | 
65 | Here is a template for the method overloading:
66 | 
67 | ```javascript
68 | class FastNoiseLite {
69 |     /**
70 |      * JSdoc
71 |      */
72 |     Method() {
73 |         let R2 = (Param1, Param2) => {
74 |             // do something 2D
75 |         }
76 | 
77 |         let R3 = (Param1, Param2, Param3) => {
78 |             // do something 3D
79 |         }
80 | 
81 |         if (arguments.lenght === 2) {
82 |             return R2(arguments[0], arguments[1]);
83 |         }
84 | 
85 |         if (arguments.length === 3) {
86 |             return R3(arguments[0], arguments[1], arguments[2])
87 |         }
88 |     }
89 | 
90 | }
91 | ```
92 | 
93 | ### DM dev_storm on discord or email w/ any questions or need any support or ask someone in our discord :D
94 | 


--------------------------------------------------------------------------------
/JavaScript/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "fastnoise-lite",
 3 |   "type": "module",
 4 |   "version": "1.1.1",
 5 |   "description": "FastNoise Lite is an extremely portable open source noise generation library with a large selection of noise algorithms",
 6 |   "main": "FastNoiseLite.js",
 7 |   "scripts": {
 8 |     "test": "echo \"Error: no test specified\" && exit 1"
 9 |   },
10 |   "repository": {
11 |     "type": "git",
12 |     "url": "git+https://github.com/Auburn/FastNoiseLite.git"
13 |   },
14 |   "keywords": [
15 |     "noise",
16 |     "fastnoise",
17 |     "procedural",
18 |     "simplex",
19 |     "opensimplex",
20 |     "cellular",
21 |     "voronoi",
22 |     "perlin",
23 |     "value",
24 |     "cubic",
25 |     "fractal",
26 |     "domain-warping",
27 |     "2D",
28 |     "3D",
29 |     "heightmap",
30 |     "terrain",
31 |     "texture",
32 |     "random",
33 |     "generative"
34 |   ],
35 |   "contributors": ["Jordan Peck", "Patrick U"],
36 |   "license": "MIT",
37 |   "bugs": {
38 |     "url": "https://github.com/Auburn/FastNoiseLite/issues"
39 |   },
40 |   "homepage": "https://github.com/Auburn/FastNoiseLite#readme"
41 | }
42 | 


--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
 1 | MIT License
 2 | 
 3 | Copyright(c) 2020 Jordan Peck (jordan.me2@gmail.com)
 4 | Copyright(c) 2020 Contributors
 5 | 
 6 | Permission is hereby granted, free of charge, to any person obtaining a copy
 7 | of this software and associated documentation files (the "Software"), to deal
 8 | in the Software without restriction, including without limitation the rights
 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 | 
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 | 
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.


--------------------------------------------------------------------------------
/Odin/README.md:
--------------------------------------------------------------------------------
1 | # Usage
2 | 
3 | Copy the FastNoiseLite.odin file into a 'fast_noise_lite' directory in your project or in the odin/shared directory.


--------------------------------------------------------------------------------
/Pascal/README.md:
--------------------------------------------------------------------------------
 1 | ## Getting Started
 2 | 
 3 | Here's an example for creating a 128x128 array of OpenSimplex2 noise
 4 | 
 5 | ```pascal
 6 | 
 7 | program NoiseTest;
 8 | 
 9 | {$mode objfpc}{$H+}
10 | 
11 | uses 
12 | 	cmem, fastnoiselite;
13 | 
14 | var
15 | 	noise : FNL_State;
16 | 	noiseVal : Single;
17 | 	x,y : Integer;
18 | 
19 | begin
20 |   noise := fnlCreateState();
21 |   noise.frequency:=0.001;
22 |   noise.noise_type:=FNL_NOISE_PERLIN;
23 |   noise.cellular_distance_func:=FNL_CELLULAR_DISTANCE_EUCLIDEAN;
24 |   noise.domain_warp_type:=FNL_DOMAIN_WARP_OPENSIMPLEX2;
25 |   noise.domain_warp_amp:=12.0;
26 |   noise.fractal_type:= FNL_FRACTAL_PINGPONG;
27 |   noise.weighted_strength:=0.8;   
28 |   for x := 0 to 128 do
29 |    for y := 0 to 128 do  
30 |    begin
31 |      noiseVal := (fnlGetNoise2D(@noise,x+offsetX,y) + 1.0) / 2.0; // 0..1
32 |    end;
33 | end.
34 | 
35 | 
36 | ```


--------------------------------------------------------------------------------
/PowerShell/README.md:
--------------------------------------------------------------------------------
 1 | ## Getting Started
 2 | 
 3 | First, you'll want to copy all the code from the PSFastNoiseLite file into your own PowerShell code. Because PSFastNoiseLite is designed as a class, it's easier to do this than modularizing. Copy from line 38 onward.
 4 | 
 5 | Here's an example for creating a 128x128 array of OpenSimplex2 noise:
 6 | 
 7 | ```PowerShell
 8 | # CREATE AND CONFIGURE A FAST NOISE OBJECT
 9 | [FastNoiseLite]$Noise = [FastNoiseLite]::new()
10 | $Noise.SetNoiseType([FnlNoiseType]::OpenSimplex2)
11 | 
12 | # GATHER NOISE DATA
13 | $TestNoise = New-Object 'Single[,]' 128, 128
14 | 
15 | For([Int]$X = 0; $X -LT 128; $X++) {
16 |     For([Int]$Y = 0; $Y -LT 128; $Y++) {
17 |         $TestNoise[$X, $Y] = $Noise.GetNoise($X, $Y)
18 |     }
19 | }
20 | 
21 | # DO SOMETHING WITH THIS DATA...
22 | # WRITE TO CONSOLE
23 | # Write-Host "$($TestNoise)"
24 | ```


--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
  1 | [![discord](https://img.shields.io/discord/703636892901441577?logo=discord "Discord")](https://discord.gg/SHVaVfV)
  2 | 
  3 | # FastNoise Lite
  4 | 
  5 | [Web Preview App](https://auburn.github.io/FastNoiseLite)
  6 | 
  7 | FastNoise Lite is an extremely portable open source noise generation library with a large selection of noise algorithms. This library focuses on high performance while avoiding platform/language specific features, allowing for easy ports to as many possible languages.
  8 | 
  9 | This project is an evolution of the [original FastNoise](https://github.com/Auburn/FastNoiseLite/tree/FastNoise-Legacy) library and shares the same goal: An easy to use library that can quickly be integrated into a project and provides performant modern noise generation. See a breakdown of changes from the transition to FastNoise Lite [here](https://github.com/Auburn/FastNoiseLite/pull/49)
 10 | 
 11 | If you are looking for a more extensive noise generation library consider using [FastNoise2](https://github.com/Auburn/FastNoise2). It provides large performance gains thanks to SIMD and uses a node graph structure to allow complex noise configurations with lots of flexibility.
 12 | 
 13 | ## Features
 14 | 
 15 | - 2D & 3D sampling
 16 | - OpenSimplex2 noise
 17 | - OpenSimplex2S noise
 18 | - Cellular (Voronoi) noise
 19 | - Perlin noise
 20 | - Value noise
 21 | - Value Cubic noise
 22 | - OpenSimplex2-based domain warp
 23 | - Basic Grid Gradient domain warp
 24 | - Multiple fractal options for all of the above
 25 | - Supports floats and/or doubles
 26 | 
 27 | ### Supported Languages
 28 | 
 29 | - [C#](/CSharp/)
 30 | - [C++98](/Cpp/)
 31 | - [C99](/C/)
 32 | - [HLSL](/HLSL/)
 33 | - [GLSL](/GLSL/)
 34 | - [Go](/Go/)
 35 | - [Java](/Java/)
 36 | - [JavaScript](/JavaScript/)  
 37 |   [![npm](https://img.shields.io/npm/v/fastnoise-lite?logo=npm "npm")](https://www.npmjs.com/package/fastnoise-lite)
 38 | - [Rust](/Rust/)  
 39 |   [![crates.io](https://img.shields.io/crates/v/fastnoise-lite?logo=rust "crates.io")](https://crates.io/crates/fastnoise-lite)
 40 | - [Fortran](/Fortran/)
 41 | - [Zig](/Zig/)
 42 | - [PowerShell](/PowerShell/)
 43 | - [Odin](/Odin/)
 44 | - [Haxe](/Haxe/)
 45 | - [Pascal](/Pascal/)
 46 | - [GML](/GML/)
 47 | 
 48 | If you want to port FastNoise Lite to a new language create a pull request or discuss it on the discord linked above
 49 | 
 50 | ### [Getting Started](https://github.com/Auburn/FastNoiseLite/wiki#getting-started)
 51 | ### [Documentation](https://github.com/Auburn/FastNoiseLite/wiki/Documentation)
 52 | 
 53 | ## FastNoise Lite Web Preview App
 54 | 
 55 | Link: [https://auburn.github.io/FastNoiseLite](https://auburn.github.io/FastNoiseLite)
 56 | 
 57 | A compact testing application is available for testing all features included in FastNoise Lite with a visual representation. This can be used for development purposes, testing noise settings and generating noise textures for export.
 58 | 
 59 | Source code can be found in the [WebPreviewApp](/WebPreviewApp/) directory.
 60 | 
 61 | ![Simplex FBm](https://user-images.githubusercontent.com/1349548/275292148-242e95c7-94e7-4801-bc4a-d683a8822382.png)
 62 | 
 63 | ## Performance Comparisons
 64 | 
 65 | Benchmarked using C++ version with [NoiseBenchmarking](https://github.com/Auburn/NoiseBenchmarking)
 66 | 
 67 | - CPU: Intel 7820X @ 4.9Ghz
 68 | - OS: Win10 x64
 69 | - Compiler: clang-cl 10.0.0 -m64 /O2
 70 | 
 71 | Million points of noise generated per second (higher = better)
 72 | 
 73 | | 3D                 | Value  | Perlin | (*Open)Simplex | Cellular |
 74 | |--------------------|--------|--------|----------------|----------|
 75 | | FastNoise Lite     | 64.13  | 47.93  | 36.83*         | 12.49    |
 76 | | FastNoise (Legacy) | 49.34  | 37.75  | 44.74          | 13.27    |
 77 | | FastNoise 2 (AVX2) | 494.49 | 261.10 | 268.44         | 52.43    |
 78 | | libnoise           |        | 27.35  |                | 0.65     |
 79 | | stb perlin         |        | 34.32  |                |          |
 80 | 
 81 | | 2D                 | Value  | Perlin | Simplex | Cellular |
 82 | |--------------------|--------|--------|---------|----------|
 83 | | FastNoise Lite     | 114.01 | 92.83  | 71.30   | 39.15    |
 84 | | FastNoise (Legacy) | 102.12 | 87.99  | 65.29   | 36.84    |
 85 | | FastNoise 2 (AVX2) | 776.33 | 624.27 | 466.03  | 194.30   |
 86 | 
 87 | ## Credits:
 88 | 
 89 | - [OpenSimplex2](https://github.com/KdotJPG/OpenSimplex2) for the OpenSimplex2 noise algorithm
 90 | - [@KdotJPG](https://github.com/KdotJPG) for implementing all the OpenSimplex algorithms and the Java port
 91 | - [CubicNoise](https://github.com/jobtalle/CubicNoise) for the Value (Cubic) noise algorithm
 92 | - [@Rover656](https://github.com/Rover656) for creating the preview GUI and porting FastNoise Lite to C and HLSL.
 93 | - [@snowfoxsh](https://github.com/snowfoxsh) for creating the JavaScript port.
 94 | - [@dotlogix](https://github.com/dotlogix) for creating the GLSL port.
 95 | - [@ForeverZer0](https://github.com/ForeverZer0) for creating the Zig and Go ports.
 96 | - [@Keavon](https://github.com/Keavon) for creating the Rust port.
 97 | - [@jordan4ibanez](https://github.com/jordan4ibanez) for creating the Fortran port.
 98 | - [@gregoryfmartin](https://github.com/gregoryfmartin) for creating the Powershell port.
 99 | - [@itsdanott](https://github.com/itsdanott) for creating the Odin port.
100 | - [@Zylann](https://github.com/Zylann) for creating the Haxe port.
101 | - [@CptnRoughnight](https://github.com/CptnRoughnight) for creating the Pascal port.
102 | - [@Tinkerer_Red]([https://github.com/CptnRoughnight](https://github.com/tinkerer-red)) for creating the GameMaker port.
103 | 
104 | ## Contributing
105 | 
106 | New ports of FastNoise Lite are always welcome, create a PR or come discuss the port with me on the discord linked above.
107 | I'm not an expert or even familiar with every language FastNoise lite has been ported to, so if you see something that could be improved please contribute or create a GitHub issue.
108 | 
109 | 
110 | # Examples
111 | 
112 | ![Ridged Fractal](https://user-images.githubusercontent.com/1349548/275292765-498f804b-96f8-4187-860f-7d6c49f6fc88.png)
113 | 
114 | ![Cellular](https://user-images.githubusercontent.com/1349548/275292225-4e5a0379-834d-4e6e-ab2d-2c0e8e2ee209.png)
115 | 
116 | ![Cellular Fractal](https://user-images.githubusercontent.com/1349548/275292294-ebb3bb00-757f-46c3-9e18-3bdc73f96719.png)
117 | 
118 | ![Cellular Value Warped](https://user-images.githubusercontent.com/1349548/275292149-42a42aa7-d1b1-4c2f-856f-02fd80e84c78.png)
119 | 
120 | ![Value Warped](https://user-images.githubusercontent.com/1349548/275293046-724b3aa4-1a6f-4b08-b421-8d32b6a69311.png)
121 | 


--------------------------------------------------------------------------------
/Rust/Cargo.lock:
--------------------------------------------------------------------------------
 1 | # This file is automatically @generated by Cargo.
 2 | # It is not intended for manual editing.
 3 | version = 3
 4 | 
 5 | [[package]]
 6 | name = "autocfg"
 7 | version = "1.1.0"
 8 | source = "registry+https://github.com/rust-lang/crates.io-index"
 9 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
10 | 
11 | [[package]]
12 | name = "fastnoise-lite"
13 | version = "1.1.1"
14 | dependencies = [
15 |  "num-traits",
16 | ]
17 | 
18 | [[package]]
19 | name = "libm"
20 | version = "0.2.8"
21 | source = "registry+https://github.com/rust-lang/crates.io-index"
22 | checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
23 | 
24 | [[package]]
25 | name = "num-traits"
26 | version = "0.2.18"
27 | source = "registry+https://github.com/rust-lang/crates.io-index"
28 | checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
29 | dependencies = [
30 |  "autocfg",
31 |  "libm",
32 | ]
33 | 


--------------------------------------------------------------------------------
/Rust/Cargo.toml:
--------------------------------------------------------------------------------
 1 | [package]
 2 | name = "fastnoise-lite"
 3 | version = "1.1.1"
 4 | edition = "2021"
 5 | license = "MIT"
 6 | description = "FastNoise Lite is an extremely portable open source noise generation library with a large selection of noise algorithms"
 7 | repository = "https://github.com/Auburn/FastNoiseLite"
 8 | readme = "README.md"
 9 | authors = ["Jordan Peck", "Keavon Chambers"]
10 | categories = [
11 | 	"algorithms",
12 | 	"game-development",
13 | 	"graphics",
14 | 	"multimedia::images",
15 | 	"rendering",
16 | ]
17 | keywords = ["noise", "simplex", "perlin", "procedural", "terrain"]
18 | 
19 | [features]
20 | default = ["std"]
21 | f64 = []
22 | std = ["num-traits/std"]
23 | libm = ["num-traits/libm"]
24 | 
25 | [dependencies]
26 | num-traits = { version = "0.2.18", optional = true, default-features = false }
27 | 


--------------------------------------------------------------------------------
/Rust/README.md:
--------------------------------------------------------------------------------
 1 | [![GitHub](https://img.shields.io/github/v/release/Auburn/FastNoiseLite?logo=github&label=GitHub&color=blue
 2 |  "GitHub")](https://github.com/Auburn/FastNoiseLite) [![crates.io](https://img.shields.io/crates/v/fastnoise-lite?logo=rust&color=blue "crates.io")](https://crates.io/crates/fastnoise-lite) [![docs.rs](https://img.shields.io/docsrs/fastnoise-lite/latest?logo=docs.rs&label=docs.rs&color=blue "docs.rs")](https://docs.rs/fastnoise-lite/latest/fastnoise_lite/)
 3 | 
 4 | # FastNoise Lite
 5 | 
 6 | FastNoise Lite is an extremely portable open source noise generation library with a large selection of noise algorithms. This library focuses on high performance while avoiding platform/language specific features, allowing for easy ports to as many possible languages.
 7 | 
 8 | ## Features
 9 | 
10 | - 2D & 3D sampling
11 | - OpenSimplex2 noise
12 | - OpenSimplex2S noise
13 | - Cellular (Voronoi) noise
14 | - Perlin noise
15 | - Value noise
16 | - Value Cubic noise
17 | - OpenSimplex2-based domain warp
18 | - Basic Grid Gradient domain warp
19 | - Multiple fractal options for all of the above
20 | - Supports `f32` or `f64` precision floats for X/Y sampling positions (see "Feature Flags" below)
21 | - `no_std` (see "Feature Flags" below)
22 | 
23 | ## Feature Flags
24 | 
25 | Optionally enable these in your `Cargo.toml` file with your `fastnoise-lite` dependency.
26 | 
27 | - `"f64"`: Uses `f64`, instead of the default `f32`, X/Y coordinate sampling inputs.
28 | - `"std"`: Uses Rust's standard library for floating point operations (`sqrt()`, `trunc()`, and `abs()`). Either this or `"libm"` must be enabled. This is enabled by default if no feature flags are specified (but note that specifying `"f64"` will mean this is no longer default, and must be specified too).
29 | - `"libm"`: Enables `no_std` support. Either this or `"std"` must be enabled. Uses the [libm](https://crates.io/crates/libm) optional dependency (through the [num-traits](https://crates.io/crates/num-traits) optional dependency) to allow floating point operations (`sqrt()`, `trunc()`, and `abs()`) without relying on the Rust standard library's implementations. FNL is dependency-free except when using this feature flag, which pulls in these optional dependencies.
30 | 
31 | ## Getting Started
32 | 
33 | - First, construct a [`FastNoiseLite` struct](https://docs.rs/fastnoise-lite/latest/fastnoise_lite/struct.FastNoiseLite.html) using [`FastNoiseLite::new()`](https://docs.rs/fastnoise-lite/latest/fastnoise_lite/struct.FastNoiseLite.html#method.new) or [`FastNoiseLite::with_seed(seed)`](https://docs.rs/fastnoise-lite/latest/fastnoise_lite/struct.FastNoiseLite.html#method.with_seed).
34 | - Next, you may call the various setter functions to configure the object's noise generation settings to your needs from their defaults.
35 | - Optionally, you may use [`domain_warp_2d(x, y)`](https://docs.rs/fastnoise-lite/latest/fastnoise_lite/struct.FastNoiseLite.html#method.domain_warp_2d) and [`domain_warp_3d(x, y, z)`](https://docs.rs/fastnoise-lite/latest/fastnoise_lite/struct.FastNoiseLite.html#method.domain_warp_3d) to translate your original sampling coordinates into domain-warped coordinates before using them to sample the noise in the next step.
36 | - Finally, sample the noise value at X/Y(/Z) coordinates for each pixel of your output data by calling [`get_noise_2d(x, y)`](https://docs.rs/fastnoise-lite/latest/fastnoise_lite/struct.FastNoiseLite.html#method.get_noise_2d) or [`get_noise_3d(x, y, z)`](https://docs.rs/fastnoise-lite/latest/fastnoise_lite/struct.FastNoiseLite.html#method.get_noise_3d). You may need to remap the output range from -1..1 to your desired range.
37 | 
38 | Additional documentation is available in the project's [Getting Started](https://github.com/Auburn/FastNoiseLite/wiki#getting-started) and [Documentation](https://github.com/Auburn/FastNoiseLite/wiki/Documentation) pages from its GitHub wiki.
39 | 
40 | Below is an example for creating a 128x128 array of OpenSimplex2 noise.
41 | 
42 | ```rs
43 | use fastnoise_lite::*;
44 | 
45 | // Create and configure the FastNoise object
46 | let mut noise = FastNoiseLite::new();
47 | noise.set_noise_type(Some(NoiseType::OpenSimplex2));
48 | 
49 | const WIDTH: usize = 128;
50 | const HEIGHT: usize = 128;
51 | let mut noise_data = [[0.; HEIGHT]; WIDTH];
52 | 
53 | // Sample noise pixels
54 | for x in 0..WIDTH {
55 |     for y in 0..HEIGHT {
56 |         // Domain warp can optionally be employed to transform the coordinates before sampling:
57 |         // let (x, y) = noise.domain_warp_2d(x as f32, y as f32);
58 |         
59 |         let negative_1_to_1 = noise.get_noise_2d(x as f32, y as f32);
60 |         // You may want to remap the -1..1 range data to the 0..1 range:
61 |         noise_data[x][y] = (neg_1_to_1 + 1.) / 2.;
62 |         
63 |         // (Uses of `as f32` above should become `as f64` if you're using FNL with the "f64" feature flag)
64 |     }
65 | }
66 | 
67 | // Do something with this data...
68 | ```
69 | 


--------------------------------------------------------------------------------
/WebPreviewApp/CMakeLists.txt:
--------------------------------------------------------------------------------
 1 | cmake_minimum_required(VERSION 3.12)
 2 | 
 3 | project(FastNoiseLitePreview VERSION 1.1.1)
 4 | SET(CMAKE_CXX_STANDARD 17)
 5 | 
 6 | include(FetchContent)
 7 | 
 8 | FetchContent_Declare(
 9 |     imgui_application
10 |     GIT_REPOSITORY https://github.com/auburn/imgui_application
11 |     GIT_TAG 00c4079834123e27850c6ec818b21fdf2797e5b5
12 | )
13 | FetchContent_MakeAvailable(imgui_application)
14 | 
15 | FetchContent_Declare(
16 |     emscripten-browser-file
17 |     GIT_REPOSITORY https://github.com/Armchair-Software/emscripten-browser-file
18 |     GIT_TAG 2ff8f8f791c0e7177b40e621ee3f758e03b31bf5
19 | )
20 | FetchContent_MakeAvailable(emscripten-browser-file)
21 | # ----------------------------------------------------------
22 | 
23 | add_executable(${CMAKE_PROJECT_NAME}
24 |     "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp"
25 | )
26 | 
27 | target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC
28 |     ${IMGUI_APPLICATION_INCLUDE_DIRECTORIES}
29 |     ${emscripten-browser-file_SOURCE_DIR}
30 |     ../Cpp
31 | )
32 | 
33 | target_compile_definitions(${CMAKE_PROJECT_NAME} PUBLIC
34 |     FNL_VERSION="v${CMAKE_PROJECT_VERSION}"
35 | )
36 | 
37 | if(EMSCRIPTEN)
38 | 
39 |     # IMPORTANT NOTE: due to `target_link_options` deduplication,
40 |     # we use "-sWASM=1 -sUSE_SDL=2 ..." which works well, instead of
41 |     # "-s WASM=1 -s USE_SDL=2 ..." (with spaces), which becomes
42 |     # "-s WASM=1 USE_SDL=2 ..." (duplicated but necessary '-s' removed).
43 | 
44 |     target_link_options(${CMAKE_PROJECT_NAME} PRIVATE
45 |         -sWASM=1
46 |         -sUSE_SDL=2
47 | 
48 |         -sUSE_WEBGL2=1
49 |         #-sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2 # Only target for WebGL2 (drop support for WebGL1 to save code size)
50 | 
51 |         -sEXPORTED_RUNTIME_METHODS=[ccall]
52 |         -sEXPORTED_FUNCTIONS=[_main,_malloc,_free]
53 | 
54 |         -sALLOW_MEMORY_GROWTH=1
55 |         -sDISABLE_EXCEPTION_CATCHING=1 -sNO_EXIT_RUNTIME=0 -sASSERTIONS=1
56 | 
57 |         -sNO_FILESYSTEM=1
58 | 
59 |         -sSINGLE_FILE
60 | 
61 |         --shell-file ${IMGUI_APPLICATION_SHELL_MINIMAL}
62 |     )
63 | 
64 |     target_link_libraries(${CMAKE_PROJECT_NAME}
65 |         imgui_application
66 |     )
67 | 
68 |     set(CMAKE_EXECUTABLE_SUFFIX ".html")
69 | 
70 | else()
71 | 
72 |     target_link_libraries(${CMAKE_PROJECT_NAME}
73 |         imgui_application GL
74 |     )
75 | 
76 | endif()


--------------------------------------------------------------------------------
/WebPreviewApp/build.ps1:
--------------------------------------------------------------------------------
 1 | $scriptPath = $PSScriptRoot
 2 | $emsdkVer = "3.1.52"
 3 | $emsdkPath = Join-Path -Path $PSScriptRoot -ChildPath "emsdk" | Join-Path -ChildPath $emsdkVer
 4 | 
 5 | if (Test-Path -Path $emsdkPath -PathType Container) {
 6 |     Write-Host "Found existing emsdk"
 7 |     & "$emsdkPath\emsdk_env.ps1"
 8 | } else {
 9 |     Write-Host "Building emsdk"
10 |     git clone --branch $emsdkVer "https://github.com/emscripten-core/emsdk.git" $emsdkPath
11 |     & "$emsdkPath\emsdk.ps1" install $emsdkVer
12 |     & "$emsdkPath\emsdk.ps1" activate $emsdkVer
13 | }
14 | 
15 | emcc --version
16 | 
17 | emcmake cmake -Bbuild -DCMAKE_BUILD_TYPE=Release
18 | cmake --build build
19 | 


--------------------------------------------------------------------------------
/WebPreviewApp/main.cpp:
--------------------------------------------------------------------------------
  1 | #include <algorithm>
  2 | #include <chrono>
  3 | #include <cstdint>
  4 | #include <sstream>
  5 | 
  6 | #include <imgui_app/ImGui_Application.hpp>
  7 | #include <imgui_internal.h>
  8 | 
  9 | #include <EGL/egl.h>
 10 | #include <GLES2/gl2.h>
 11 | 
 12 | #include <emscripten.h>
 13 | #include <emscripten_browser_file.h>
 14 | 
 15 | #include "../Cpp/FastNoiseLite.h"
 16 | #include "FastNoiseLite.h"
 17 | 
 18 | class FastNoiseLitePreviewApp : public ImGui_Application
 19 | {
 20 | public:
 21 |     bool init() override
 22 |     {
 23 |         bool success = ImGui_Application::init();
 24 |         set_window_title("FastNoise Lite GUI");
 25 | 
 26 |         ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_DockingEnable;
 27 | 
 28 |         return success;
 29 |     }
 30 | 
 31 |     uint32_t noiseTex = 0;
 32 |     ImVec2 noiseTexSize;
 33 |     int noiseTexSizeGenX;
 34 |     int noiseTexSizeGenY;
 35 |     float noiseTexMin = -1;
 36 |     float noiseTexMax = 1;
 37 |     int previewSize[2] = { 768, 768 };
 38 |     bool preview3d = false;
 39 |     float previewScroll = 0;
 40 |     double previewPosZ = 0;
 41 |     bool previewDomainWarp = false;
 42 |     bool previewAutoSize = false;
 43 | 
 44 |     float previewGenTime = 0;
 45 |     float previewGenTimeFinal = 0;
 46 |     float previewMin = 0;
 47 |     float previewMinFinal = 0;
 48 |     float previewMax = 0;
 49 |     float previewMaxFinal = 0;
 50 |     float previewMean = 0;
 51 |     float previewMeanFinal = 0;
 52 |     bool previewTriggerSave = false;
 53 |     int previewPixelY = 0;
 54 |     unsigned char* previewPixelArray = nullptr;
 55 | 
 56 |     FastNoiseLite fnl;
 57 |     FastNoiseLite fnlWarp;
 58 | 
 59 |     int fnlNoiseType = 0;
 60 |     int fnlRotationType = 0;
 61 |     int fnlSeed = 1337;
 62 |     float fnlFrequency = 0.01f;
 63 | 
 64 |     int fnlFractalType = 0;
 65 |     int fnlFractalOctaves = 3;
 66 |     float fnlFractalLacunarity = 2.0f;
 67 |     float fnlFractalGain = 0.5f;
 68 |     float fnlFractalWeightedStrength = 0.0f;
 69 |     float fnlFractalPingPongStrength = 2.0f;
 70 | 
 71 |     int fnlCellularType = 1;
 72 |     int fnlCellularReturnType = 1;
 73 |     float fnlCellularJitter = 1.0f;
 74 | 
 75 |     int fnlDomainWarpSeed = 1337;
 76 |     float fnlDomainWarpFrequency = 0.01f;
 77 |     int fnlDomainWarpType = 0;
 78 |     int fnlDomainWarpRotationType = 0;
 79 |     float fnlDomainWarpAmplitude = 1.0f;
 80 | 
 81 |     int fnlDomainWarpFractalType = 0;
 82 |     int fnlDomainWarpFractalOctaves = 3;
 83 |     float fnlDomainWarpFractalLacunarity = 2.0f;
 84 |     float fnlDomainWarpFractalGain = 0.5f;
 85 | 
 86 |     void draw_ui() override
 87 |     {
 88 |         static const char* enumNoiseType[] = { "OpenSimplex2", "OpenSimplex2S", "Cellular", "Perlin", "Value Cubic", "Value" };
 89 |         static const char* enumRotationType[] = { "None", "Improve XY Planes", "Improve XZ Planes" };
 90 |         static const char* enumFractalType[] = { "None", "FBm", "Ridged", "Ping Pong" };
 91 |         static const char* enumCellularType[] = { "Euclidean", "Euclidean Sq", "Manhattan", "Hybrid" };
 92 |         static const char* enumCellularReturnType[] = { "Cell Value", "Distance", "Distance 2", "Distance 2 Add", "Distance 2 Sub", "Distance 2 Mul", "Distance 2 Div" };
 93 |         static const char* enumDomainWarpType[] = { "None", "OpenSimplex2", "OpenSimplex2 Reduced", "Basic Grid" };
 94 |         static const char* enumDomainWarpFractalType[] = { "None", "Progressive", "Independent" };
 95 | 
 96 |         SetupDocking();
 97 | 
 98 |         // ImGui::ShowDemoWindow();
 99 | 
100 |         bool texUpdate = false;
101 | 
102 |         ImGui::Begin("Settings");
103 |         ImGui::PushItemWidth(120);
104 | 
105 |         ImGui::BeginTabBar("Tabs");
106 |         if (ImGui::BeginTabItem("FastNoise Lite"))
107 |         {
108 |             /// General
109 |             ImGui::TextUnformatted("General");
110 | 
111 |             if (ImGui::Combo("Noise Type", &fnlNoiseType, enumNoiseType, IM_ARRAYSIZE(enumNoiseType)))
112 |             {
113 |                 fnl.SetNoiseType((FastNoiseLite::NoiseType)fnlNoiseType);
114 |                 texUpdate = true;
115 |             }
116 |             ImGui::BeginDisabled(!preview3d);
117 |             if (ImGui::Combo("Rotation Type 3D", &fnlRotationType, enumRotationType, IM_ARRAYSIZE(enumRotationType)))
118 |             {
119 |                 fnl.SetRotationType3D((FastNoiseLite::RotationType3D)fnlRotationType);
120 |                 texUpdate = true;
121 |             }
122 |             ImGui::EndDisabled();
123 |             if (ImGui::DragInt("Seed", &fnlSeed))
124 |             {
125 |                 fnl.SetSeed(fnlSeed);
126 |                 texUpdate = true;
127 |             }
128 |             if (ImGui::DragFloat("Frequency", &fnlFrequency, 0.0002f))
129 |             {
130 |                 fnl.SetFrequency(fnlFrequency);
131 |                 texUpdate = true;
132 |             }
133 | 
134 |             /// Fractal
135 |             ImGui::TextUnformatted("Fractal");
136 | 
137 |             if (ImGui::Combo("Type", &fnlFractalType, enumFractalType, IM_ARRAYSIZE(enumFractalType)))
138 |             {
139 |                 fnl.SetFractalType((FastNoiseLite::FractalType)fnlFractalType);
140 |                 texUpdate = true;
141 |             }
142 |             ImGui::BeginDisabled(fnlFractalType == 0);
143 |             if (ImGui::DragInt("Octaves", &fnlFractalOctaves, 0.1f, 1, 20))
144 |             {
145 |                 fnl.SetFractalOctaves(fnlFractalOctaves);
146 |                 texUpdate = true;
147 |             }
148 |             if (ImGui::DragFloat("Lacunarity", &fnlFractalLacunarity, 0.01f))
149 |             {
150 |                 fnl.SetFractalLacunarity(fnlFractalLacunarity);
151 |                 texUpdate = true;
152 |             }
153 |             if (ImGui::DragFloat("Gain", &fnlFractalGain, 0.01f))
154 |             {
155 |                 fnl.SetFractalGain(fnlFractalGain);
156 |                 texUpdate = true;
157 |             }
158 |             if (ImGui::DragFloat("Weighted Strength", &fnlFractalWeightedStrength, 0.01f))
159 |             {
160 |                 fnl.SetFractalWeightedStrength(fnlFractalWeightedStrength);
161 |                 texUpdate = true;
162 |             }
163 |             ImGui::BeginDisabled(fnlFractalType != (int)FastNoiseLite::FractalType_PingPong);
164 |             if (ImGui::DragFloat("Ping Pong Strength", &fnlFractalPingPongStrength, 0.01f))
165 |             {
166 |                 fnl.SetFractalPingPongStrength(fnlFractalPingPongStrength);
167 |                 texUpdate = true;
168 |             }
169 |             ImGui::EndDisabled();
170 |             ImGui::EndDisabled();
171 | 
172 |             /// Cellular
173 |             ImGui::TextUnformatted("Cellular");
174 | 
175 |             ImGui::BeginDisabled(fnlNoiseType != (int)FastNoiseLite::NoiseType_Cellular);
176 |             if (ImGui::Combo("Distance Function", &fnlCellularType, enumCellularType, IM_ARRAYSIZE(enumCellularType)))
177 |             {
178 |                 fnl.SetCellularDistanceFunction((FastNoiseLite::CellularDistanceFunction)fnlCellularType);
179 |                 texUpdate = true;
180 |             }
181 |             if (ImGui::Combo("Return Type", &fnlCellularReturnType, enumCellularReturnType, IM_ARRAYSIZE(enumCellularReturnType)))
182 |             {
183 |                 fnl.SetCellularReturnType((FastNoiseLite::CellularReturnType)fnlCellularReturnType);
184 |                 texUpdate = true;
185 |             }
186 |             if (ImGui::DragFloat("Jitter", &fnlCellularJitter, 0.01f))
187 |             {
188 |                 fnl.SetCellularJitter(fnlCellularJitter);
189 |                 texUpdate = true;
190 |             }
191 |             ImGui::EndDisabled();
192 | 
193 |             /// Domain Warp
194 |             ImGui::PushID("Domain Warp");
195 |             ImGui::TextUnformatted("Domain Warp");
196 | 
197 |             if (ImGui::Combo("Type", &fnlDomainWarpType, enumDomainWarpType, IM_ARRAYSIZE(enumDomainWarpType)))
198 |             {
199 |                 fnlWarp.SetDomainWarpType((FastNoiseLite::DomainWarpType)(fnlDomainWarpType - 1));
200 |                 texUpdate = true;
201 |             }
202 |             ImGui::BeginDisabled(fnlDomainWarpType == 0);
203 |             ImGui::BeginDisabled(!preview3d);
204 |             if (ImGui::Combo("Rotation Type 3D", &fnlDomainWarpRotationType, enumRotationType, IM_ARRAYSIZE(enumRotationType)))
205 |             {
206 |                 fnlWarp.SetRotationType3D((FastNoiseLite::RotationType3D)fnlDomainWarpRotationType);
207 |                 texUpdate = true;
208 |             }
209 |             ImGui::EndDisabled();
210 |             if (ImGui::DragFloat("Amplitude", &fnlDomainWarpAmplitude, 0.5f))
211 |             {
212 |                 fnlWarp.SetDomainWarpAmp(fnlDomainWarpAmplitude);
213 |                 texUpdate = true;
214 |             }
215 |             if (ImGui::DragInt("Seed", &fnlDomainWarpSeed))
216 |             {
217 |                 fnlWarp.SetSeed(fnlDomainWarpSeed);
218 |                 texUpdate = true;
219 |             }
220 |             if (ImGui::DragFloat("Frequency", &fnlDomainWarpFrequency, 0.001f))
221 |             {
222 |                 fnlWarp.SetFrequency(fnlDomainWarpFrequency);
223 |                 texUpdate = true;
224 |             }
225 | 
226 |             /// Domain Warp Fractal
227 |             ImGui::PushID("Domain Warp Fractal");
228 |             ImGui::TextUnformatted("Domain Warp Fractal");
229 | 
230 |             if (ImGui::Combo("Type", &fnlDomainWarpFractalType, enumDomainWarpFractalType, IM_ARRAYSIZE(enumDomainWarpFractalType)))
231 |             {
232 |                 fnlWarp.SetFractalType((FastNoiseLite::FractalType)(fnlDomainWarpFractalType ? fnlDomainWarpFractalType + 3 : 0));
233 |                 texUpdate = true;
234 |             }
235 |             ImGui::BeginDisabled(fnlDomainWarpFractalType == 0);
236 |             if (ImGui::DragInt("Octaves", &fnlDomainWarpFractalOctaves, 0.1f, 1, 20))
237 |             {
238 |                 fnlWarp.SetFractalOctaves(fnlDomainWarpFractalOctaves);
239 |                 texUpdate = true;
240 |             }
241 |             if (ImGui::DragFloat("Lacunarity", &fnlDomainWarpFractalLacunarity, 0.01f))
242 |             {
243 |                 fnlWarp.SetFractalLacunarity(fnlDomainWarpFractalLacunarity);
244 |                 texUpdate = true;
245 |             }
246 |             if (ImGui::DragFloat("Gain", &fnlDomainWarpFractalGain, 0.01f))
247 |             {
248 |                 fnlWarp.SetFractalGain(fnlDomainWarpFractalGain);
249 |                 texUpdate = true;
250 |             }
251 |             ImGui::EndDisabled();
252 |             ImGui::EndDisabled();
253 |             ImGui::PopID();
254 |             ImGui::PopID();
255 | 
256 |             ImGui::NewLine();
257 |             ImGui::TextUnformatted(FNL_VERSION);
258 | 
259 |             ImGui::EndTabItem();
260 |         }
261 |         if (ImGui::BeginTabItem("Preview Settings"))
262 |         {
263 |             int sizeXY[] = { (int)noiseTexSize.x, (int)noiseTexSize.y };
264 | 
265 |             ImGui::Checkbox("Auto Size", &previewAutoSize);
266 |             ImGui::BeginDisabled(previewAutoSize);
267 |             ImGui::DragInt2("Size", previewSize, 1, 32, 4096);
268 |             ImGui::EndDisabled();
269 |             if (ImGui::DragFloat("Black Point", &noiseTexMin, 0.01f))
270 |             {
271 |                 texUpdate = true;
272 |             }
273 |             if (ImGui::DragFloat("White Point", &noiseTexMax, 0.01f))
274 |             {
275 |                 texUpdate = true;
276 |             }
277 |             if (ImGui::Checkbox("3D", &preview3d))
278 |             {
279 |                 texUpdate = true;
280 |             }
281 |             if (preview3d)
282 |             {
283 |                 ImGui::Indent();
284 |                 ImGui::DragFloat("Scroll Speed", &previewScroll, 0.02f);
285 | 
286 |                 ImGui::BeginDisabled(previewScroll != 0);
287 |                 float floatPosZ = (float)previewPosZ;
288 |                 if (ImGui::DragFloat("Z Position", &floatPosZ))
289 |                 {
290 |                     previewPosZ = floatPosZ;
291 |                     texUpdate = true;
292 |                 }
293 |                 ImGui::EndDisabled();
294 | 
295 |                 ImGui::Unindent();
296 |             }
297 | 
298 |             ImGui::NewLine();
299 |             if (ImGui::Button("Save Preview"))
300 |             {
301 |                 previewTriggerSave = true;
302 |             }
303 | 
304 |             ImGui::EndTabItem();
305 |         }
306 |         ImGui::EndTabBar();
307 |         ImGui::PopItemWidth();
308 |         ImGui::End();
309 | 
310 |         ImGui::Begin("Noise Texture");
311 | 
312 |         if (previewAutoSize)
313 |         {
314 |             ImVec2 autoSize = ImGui::GetContentRegionAvail();
315 |             previewSize[0] = autoSize.x;
316 |             previewSize[1] = autoSize.y;
317 |         }
318 |         if (previewPixelY == 0)
319 |         {
320 |             if (noiseTexSizeGenX != previewSize[0] || noiseTexSizeGenY != previewSize[1])
321 |             {
322 |                 texUpdate = true;
323 |             }
324 |             if (preview3d && previewScroll != 0)
325 |             {
326 |                 previewPosZ += previewScroll;
327 |                 texUpdate = true;
328 |             }
329 |         }
330 | 
331 |         UpdateTexture(texUpdate);
332 | 
333 |         if (previewTriggerSave && previewPixelArray && previewPixelY == 0)
334 |         {
335 |             previewTriggerSave = false;
336 |             std::string bmpFile = EncodeBMP((int)noiseTexSize.x, (int)noiseTexSize.y, previewPixelArray).str();
337 |             emscripten_browser_file::download("FastNoiseLite.bmp", "image/bmp", bmpFile);
338 |         }
339 | 
340 |         ImGui::Image((void*)(intptr_t)noiseTex, noiseTexSize);
341 |         ImGui::End();
342 | 
343 |         ImGui::BeginViewportSideBar("status", ImGui::GetMainViewport(), ImGuiDir_Down, 32, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
344 |         float textOffset = 0;
345 |         ImGui::Text("Preview Stats: %0.02fms", previewGenTimeFinal);
346 |         ImGui::SameLine(textOffset += 200);
347 |         ImGui::Text("Min: %0.04f", previewMinFinal);
348 |         ImGui::SameLine(textOffset += 100);
349 |         ImGui::Text("Max: %0.04f", previewMaxFinal);
350 |         ImGui::SameLine(textOffset += 100);
351 |         ImGui::Text("Mean: %0.04f", previewMeanFinal);
352 | 
353 |         ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::CalcTextSize("GitHub").x - 15);
354 |         ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 2);
355 |         if (ImGui::Button("GitHub"))
356 |         {
357 |             emscripten_run_script("window.open('https://github.com/Auburn/FastNoiseLite', '_blank').focus();");
358 |         }
359 |         ImGui::PopStyleVar();
360 |         ImGui::End();
361 |     }
362 | 
363 |     void SetupDocking()
364 |     {
365 |         static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_PassthruCentralNode;
366 | 
367 |         // We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
368 |         // because it would be confusing to have two docking targets within each others.
369 |         ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking;
370 | 
371 |         ImGuiViewport* viewport = ImGui::GetMainViewport();
372 |         ImGui::SetNextWindowPos(viewport->Pos);
373 |         ImGui::SetNextWindowSize(viewport->Size);
374 |         ImGui::SetNextWindowViewport(viewport->ID);
375 |         ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
376 |         ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
377 |         window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
378 |         window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
379 | 
380 |         // When using ImGuiDockNodeFlags_PassthruCentralNode, DockSpace() will render our background and handle the pass-thru hole, so we ask Begin() to not render a background.
381 |         if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
382 |             window_flags |= ImGuiWindowFlags_NoBackground;
383 | 
384 |         // Important: note that we proceed even if Begin() returns false (aka window is collapsed).
385 |         // This is because we want to keep our DockSpace() active. If a DockSpace() is inactive,
386 |         // all active windows docked into it will lose their parent and become undocked.
387 |         // We cannot preserve the docking relationship between an active window and an inactive docking, otherwise
388 |         // any change of dockspace/settings would lead to windows being stuck in limbo and never being visible.
389 |         ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
390 |         ImGui::Begin("DockSpace", nullptr, window_flags);
391 |         ImGui::PopStyleVar();
392 |         ImGui::PopStyleVar(2);
393 | 
394 |         // DockSpace
395 |         ImGuiIO& io = ImGui::GetIO();
396 |         if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
397 |         {
398 |             ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
399 |             ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
400 | 
401 |             static auto first_time = true;
402 |             if (first_time)
403 |             {
404 |                 first_time = false;
405 | 
406 |                 ImGui::DockBuilderRemoveNode(dockspace_id); // clear any previous layout
407 |                 ImGui::DockBuilderAddNode(dockspace_id, dockspace_flags | ImGuiDockNodeFlags_DockSpace);
408 |                 ImGui::DockBuilderSetNodeSize(dockspace_id, viewport->Size);
409 | 
410 |                 float split = 280 / viewport->Size.x;
411 | 
412 |                 // split the dockspace into 2 nodes -- DockBuilderSplitNode takes in the following args in the following order
413 |                 //   window ID to split, direction, fraction (between 0 and 1), the final two setting let's us choose which id we want (which ever one we DON'T set as NULL, will be returned by the function)
414 |                 //                                                              out_id_at_dir is the id of the node in the direction we specified earlier, out_id_at_opposite_dir is in the opposite direction
415 |                 auto dock_id_left = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, split, nullptr, &dockspace_id);
416 | 
417 |                 // we now dock our windows into the docking node we made above
418 |                 ImGui::DockBuilderDockWindow("Noise Texture", dockspace_id);
419 |                 ImGui::DockBuilderDockWindow("Settings", dock_id_left);
420 |                 ImGui::DockBuilderGetNode(dockspace_id)->SetLocalFlags(ImGuiDockNodeFlags_NoTabBar);
421 |                 ImGui::DockBuilderGetNode(dock_id_left)->SetLocalFlags(ImGuiDockNodeFlags_NoTabBar);
422 |                 ImGui::DockBuilderFinish(dockspace_id);
423 |             }
424 |         }
425 | 
426 |         ImGui::End();
427 |     }
428 | 
429 |     std::stringstream EncodeBMP(size_t width, size_t height, unsigned char* data)
430 |     {
431 |         std::stringstream file;
432 | 
433 |         struct BmpHeader
434 |         {
435 |             // File header (14)
436 |             // char b = 'B';
437 |             // char m = 'M';
438 |             uint32_t fileSize;
439 |             uint32_t reserved = 0;
440 |             uint32_t dataOffset = 14u + 12u + (256u * 3u);
441 |             // Bmp Info Header (12)
442 |             uint32_t headerSize = 12u;
443 |             uint16_t sizeX;
444 |             uint16_t sizeY;
445 |             uint16_t colorPlanes = 1u;
446 |             uint16_t bitDepth = 8u;
447 |         };
448 | 
449 |         int paddedSizeX = (int)width;
450 |         int padding = paddedSizeX % 4;
451 |         if (padding)
452 |         {
453 |             padding = 4 - padding;
454 |             paddedSizeX += padding;
455 |         }
456 | 
457 |         BmpHeader header;
458 |         header.fileSize = header.dataOffset + (uint32_t)(paddedSizeX * height);
459 |         header.sizeX = (uint16_t)width;
460 |         header.sizeY = (uint16_t)height;
461 | 
462 |         file << 'B' << 'M';
463 |         file.write(reinterpret_cast<char*>(&header), sizeof(BmpHeader));
464 | 
465 |         // Colour map
466 |         for (int i = 0; i < 256; i++)
467 |         {
468 |             char b3[] = { (char)i, (char)i, (char)i };
469 |             file.write(b3, 3);
470 |         }
471 | 
472 |         int idx = 0;
473 | 
474 |         for (size_t y = 0; y < height; y++)
475 |         {
476 |             for (size_t x = 0; x < height; x++)
477 |             {
478 |                 file.write(reinterpret_cast<char*>(data + idx), 1);
479 |                 idx += 4;
480 |             }
481 | 
482 |             if (padding)
483 |             {
484 |                 int zero = 0;
485 |                 file.write(reinterpret_cast<char*>(&zero), padding);
486 |             }
487 |         }
488 | 
489 |         return file;
490 |     }
491 | 
492 |     void UpdateTexture(bool newPreview)
493 |     {
494 |         if (previewPixelY == 0 && !newPreview)
495 |         {
496 |             return;
497 |         }
498 | 
499 |         if (newPreview)
500 |         {
501 |             if (previewPixelArray)
502 |             {
503 |                 delete[] previewPixelArray;
504 |             }
505 |             previewPixelY = 0;
506 |             previewGenTime = 0;
507 | 
508 |             noiseTexSizeGenX = previewSize[0];
509 |             noiseTexSizeGenY = previewSize[1];
510 | 
511 |             previewMin = INFINITY;
512 |             previewMax = -INFINITY;
513 |             previewMean = 0;
514 |             previewPixelArray = new unsigned char[noiseTexSizeGenX * noiseTexSizeGenY * 4];
515 |         }
516 | 
517 |         int index = noiseTexSizeGenX * previewPixelY * 4;
518 |         float scale = 255 / (noiseTexMax - noiseTexMin);
519 | 
520 |         auto timer = std::chrono::high_resolution_clock::now();
521 | 
522 |         for (int y = previewPixelY; y < noiseTexSizeGenY; y++)
523 |         {
524 |             previewPixelY = y + 1;
525 |             for (int x = 0; x < noiseTexSizeGenX; x++)
526 |             {
527 |                 float noise;
528 |                 double posX = (double)(x - noiseTexSizeGenX / 2);
529 |                 double posY = (double)(y - noiseTexSizeGenY / 2);
530 | 
531 |                 if (preview3d)
532 |                 {
533 |                     double posZ = previewPosZ;
534 |                     if (fnlDomainWarpType > 0)
535 |                     {
536 |                         fnlWarp.DomainWarp(posX, posY, posZ);
537 |                     }
538 |                     noise = fnl.GetNoise(posX, posY, posZ);
539 |                 }
540 |                 else
541 |                 {
542 |                     if (fnlDomainWarpType > 0)
543 |                     {
544 |                         fnlWarp.DomainWarp(posX, posY);
545 |                     }
546 |                     noise = fnl.GetNoise(posX, posY);
547 |                 }
548 | 
549 |                 unsigned char cNoise = (unsigned char)std::max(0.0f, std::min(255.0f, (noise - noiseTexMin) * scale));
550 |                 previewPixelArray[index++] = cNoise;
551 |                 previewPixelArray[index++] = cNoise;
552 |                 previewPixelArray[index++] = cNoise;
553 |                 previewPixelArray[index++] = 255;
554 | 
555 |                 previewMin = std::min(previewMin, noise);
556 |                 previewMax = std::max(previewMax, noise);
557 |                 previewMean += noise;
558 |             }
559 | 
560 |             if ((y % 8) == 0 && std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - timer).count() >= 80)
561 |             {
562 |                 break;
563 |             }
564 |         }
565 | 
566 |         previewGenTime += std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - timer).count() / 1000000.f;
567 | 
568 |         if (previewPixelY >= noiseTexSizeGenY)
569 |         {
570 |             noiseTexSize.x = noiseTexSizeGenX;
571 |             noiseTexSize.y = noiseTexSizeGenY;
572 |             previewPixelY = 0;
573 |             previewMeanFinal = previewMean / (noiseTexSize.x * noiseTexSize.y);
574 |             previewMinFinal = previewMin;
575 |             previewMaxFinal = previewMax;
576 |             previewGenTimeFinal = previewGenTime;
577 | 
578 |             if (noiseTex != 0)
579 |             {
580 |                 glDeleteTextures(1, &noiseTex);
581 |             }
582 | 
583 |             // Create a OpenGL texture identifier
584 |             glGenTextures(1, &noiseTex);
585 |             glBindTexture(GL_TEXTURE_2D, noiseTex);
586 | 
587 |             // Setup filtering parameters for display
588 |             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
589 |             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
590 |             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // This is required on WebGL for non power-of-two textures
591 |             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Same
592 | 
593 |             // Upload pixels into texture
594 |             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, noiseTexSizeGenX, noiseTexSizeGenY, 0, GL_RGBA, GL_UNSIGNED_BYTE, previewPixelArray);
595 |         }
596 |     }
597 | };
598 | 
599 | int main()
600 | {
601 |     FastNoiseLitePreviewApp app;
602 | 
603 |     if (!app.init())
604 |         return 1;
605 | 
606 |     app.run_main_loop();
607 | 
608 |     return 0;
609 | }
610 |                                                                                                                                                                                                                                                                                      
611 | 


--------------------------------------------------------------------------------
/Zig/README.md:
--------------------------------------------------------------------------------
 1 | # Install
 2 | 
 3 | Simply copy the `fastnoise.zig` file directly into your project.
 4 | 
 5 | # Getting Started
 6 | 
 7 | The noise generator is implemented as a `comptime` function which returns a type, supporting both 32/64-bit floating-point types.
 8 | The generator does no allocations, nor is allocation required for initialization. 
 9 | 
10 | While the initial state of the generator is valid, you will likely want to pass in some configuration...
11 | ```zig
12 | const fastnoise = @import("fastnoise.zig");
13 | 
14 | const noise = fastnoise.Noise(f32) {
15 |   .seed = 1337,
16 |   .noise_type = .cellular,
17 |   .frequency = 0.025,
18 |   .gain = 0.40,
19 |   .fractal_type = .fbm,
20 |   .lacunarity = 0.40,
21 |   .cellular_distance = .euclidean,
22 |   .cellular_return = .distance2,
23 |   .cellular_jitter_mod = 0.88,
24 | };
25 | 
26 | const size = 128;
27 | var values: [size * size]f32 = undefined;
28 | for (0..values.len) |i| values[i] = noise.genNoise2D(@floatFromInt(i % size), @floatFromInt(i / size));
29 | 
30 | // Use noise values for whatever you please.
31 | ```
32 | 
33 | All functions of the generator are "pure" in that they do not alter its internal state, so you are free to initialize it as `const` if you will not be changing any of its fields afterwards.
34 | 


--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/Auburn/FastNoiseLite
2 | 
3 | go 1.18
4 | 


--------------------------------------------------------------------------------