├── .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 | [](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 | [](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 | [](https://www.npmjs.com/package/fastnoise-lite) 38 | - [Rust](/Rust/) 39 | [](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 |  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 |  113 | 114 |  115 | 116 |  117 | 118 |  119 | 120 |  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 | [](https://github.com/Auburn/FastNoiseLite) [](https://crates.io/crates/fastnoise-lite) [](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 | --------------------------------------------------------------------------------