├── examples ├── .eslintrc.json ├── assets │ ├── js │ │ ├── noiseWorker.js │ │ ├── noiseImageGeneration.js │ │ └── index.js │ └── css │ │ └── style.css └── index.html ├── src ├── .eslintrc.json ├── algorithms │ ├── index.mjs │ ├── perlin.mjs │ └── openSimplex.mjs ├── index.d.ts ├── util │ └── random.mjs ├── index.mjs └── ___test___ │ └── index.test.js ├── webpack ├── webpack.production.js ├── webpack.development.js └── webpack.common.js ├── .eslintrc.json ├── LICENSE ├── package.json ├── .gitignore ├── .npmignore └── README.md /examples/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "worker": true, 5 | "es2021": true 6 | }, 7 | "globals": { 8 | "noise": "readonly" 9 | } 10 | } -------------------------------------------------------------------------------- /src/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "commonjs": true, 4 | "es2021": true, 5 | "node": true, 6 | "jest": true 7 | }, 8 | "parserOptions": { 9 | "sourceType": "module" 10 | } 11 | } -------------------------------------------------------------------------------- /webpack/webpack.production.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge'); 2 | const common = require('./webpack.common.js'); 3 | 4 | module.exports = merge(common, { 5 | mode: 'production', 6 | optimization: { 7 | minimize: false, 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /src/algorithms/index.mjs: -------------------------------------------------------------------------------- 1 | import perlin from './perlin.mjs'; 2 | import openSimplexUnoptimized from './openSimplexUnoptimized.mjs'; 3 | 4 | export const defaultAlgorithm = 'open-simplex'; 5 | 6 | export default { 7 | perlin, 8 | 'open-simplex': openSimplexUnoptimized, 9 | }; -------------------------------------------------------------------------------- /webpack/webpack.development.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge'); 2 | const common = require('./webpack.common.js'); 3 | 4 | module.exports = merge(common, { 5 | mode: 'development', 6 | devtool: 'inline-source-map', 7 | devServer: { 8 | static: './examples', 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /examples/assets/js/noiseWorker.js: -------------------------------------------------------------------------------- 1 | importScripts('https://unpkg.com/asm-noise'); 2 | importScripts('./noiseImageGeneration.js'); 3 | /*global generateNoiseImageSync */ 4 | addEventListener('message', (ev) => { 5 | const { seed, algorithm, ...settings } = ev.data; 6 | noise.config({ seed, algorithm }); 7 | const { dt, noiseValues, imgData } = generateNoiseImageSync(settings); 8 | console.log(dt); 9 | postMessage({ dt, noiseValues, imgData }, [noiseValues.buffer, imgData.data.buffer]); 10 | }); 11 | -------------------------------------------------------------------------------- /webpack/webpack.common.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: './src/index.mjs', 5 | output: { 6 | path: path.resolve(__dirname, '../dist'), 7 | filename: 'asm-noise.js', 8 | library: 'noise', 9 | libraryExport: 'default', 10 | libraryTarget: 'umd', 11 | globalObject: 'this', 12 | }, 13 | module: { 14 | rules: [ 15 | { 16 | test: /\.m?js$/, 17 | exclude: /(node_modules|bower_components)/, 18 | use: { 19 | loader: 'babel-loader', 20 | options: { 21 | presets: ['@babel/preset-env'], 22 | }, 23 | }, 24 | }, 25 | ], 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es2021": true, 4 | "node": true 5 | }, 6 | "extends": "eslint:recommended", 7 | "parserOptions": { 8 | "ecmaVersion": 12 9 | }, 10 | "rules": { 11 | "indent": [ 12 | "error", 13 | 2 14 | ], 15 | "camelcase": "error", 16 | "semi": "warn", 17 | "comma-dangle": [ 18 | "error", 19 | { 20 | "arrays": "always-multiline", 21 | "objects": "always-multiline", 22 | "imports": "never", 23 | "exports": "never", 24 | "functions": "never" 25 | } 26 | ], 27 | "quotes": [ 28 | "warn", 29 | "single" 30 | ], 31 | "no-unused-vars": [ 32 | "error", 33 | { 34 | "argsIgnorePattern": "^_" 35 | } 36 | ], 37 | "object-curly-spacing": [ 38 | "error", 39 | "always" 40 | ] 41 | } 42 | } -------------------------------------------------------------------------------- /examples/assets/css/style.css: -------------------------------------------------------------------------------- 1 | @import url("https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css"); 2 | @import url("https://unpkg.com/bulma-slider@2.0.4/dist/css/bulma-slider.min.css"); 3 | 4 | * { 5 | padding: 0px; 6 | margin: 0px; 7 | } 8 | 9 | html, 10 | body { 11 | overflow: hidden; 12 | width: 100vw; 13 | height: 100vh; 14 | } 15 | 16 | main { 17 | display: flex; 18 | align-items: center; 19 | } 20 | 21 | canvas { 22 | display: block; 23 | margin: auto; 24 | } 25 | 26 | #ui { 27 | position: absolute; 28 | } 29 | 30 | #ui-handle { 31 | cursor: move; 32 | } 33 | 34 | #ui-toggle { 35 | cursor: pointer; 36 | } 37 | 38 | @media screen and (max-width: 769px) { 39 | 40 | html, 41 | body { 42 | overflow: auto; 43 | } 44 | 45 | main { 46 | display: inline; 47 | } 48 | 49 | #ui { 50 | position: static; 51 | } 52 | 53 | #ui-handle { 54 | display: none; 55 | } 56 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Wesley Clements 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), 4 | to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 5 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 10 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 11 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 | 13 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for index.js 2 | // Project: asm-noise 3 | // Definitions by: Wesley Clements 4 | declare interface ASMNoiseOptions { 5 | seed?: number; 6 | algorithm?: 'perlin' | 'open-simplex'; 7 | octaves?: number; 8 | lacunarity?: number; 9 | persistence?: number; 10 | offset?: { 11 | x: number; 12 | y: number; 13 | z: number; 14 | w: number; 15 | }; 16 | } 17 | 18 | declare module 'asm-noise' { 19 | function noise(x: number, y: number): number; 20 | function noise(x: number, y: number, z: number): number; 21 | function noise(x: number, y: number, z: number, w: number): number; 22 | namespace noise { 23 | export let seed: number; 24 | export let algorithms: ['open-simplex', 'perlin']; 25 | export let algorithm: 'perlin' | 'open-simplex'; 26 | export let octaves: number; 27 | export let lacunarity: number; 28 | export let persistence: number; 29 | export let offset: { 30 | x: number; 31 | y: number; 32 | z: number; 33 | w: number; 34 | }; 35 | export function config(options: ASMNoiseOptions); 36 | } 37 | export default noise; 38 | } 39 | -------------------------------------------------------------------------------- /src/util/random.mjs: -------------------------------------------------------------------------------- 1 | const heap = new BigInt64Array(2); 2 | const seed = 0; 3 | const current = 1; 4 | 5 | function nextBigInt64() { 6 | heap[current] = heap[current] * 6364136223846793005n + 1442695040888963407n; 7 | return heap[current]; 8 | } 9 | 10 | function nextBigUint64() { 11 | return BigInt.asUintN(64, nextBigInt64()); 12 | } 13 | 14 | function nextInt8() { 15 | return Number(BigInt.asIntN(8, nextBigInt64())); 16 | } 17 | function nextUint8() { 18 | return Number(BigInt.asUintN(8, nextBigInt64())); 19 | } 20 | 21 | function nextInt16() { 22 | return Number(BigInt.asIntN(16, nextBigInt64())); 23 | } 24 | function nextUint16() { 25 | return Number(BigInt.asUintN(16, nextBigInt64())); 26 | } 27 | 28 | function nextInt32() { 29 | return Number(BigInt.asIntN(32, nextBigInt64())); 30 | } 31 | 32 | function nextUint32() { 33 | return Number(BigInt.asUintN(32, nextBigInt64())); 34 | } 35 | 36 | function next() { 37 | return nextUint32() / 0xffffffff; 38 | } 39 | 40 | function nextGaussian() { 41 | return Math.sqrt(-2.0 * Math.log(next())) * Math.cos(2.0 * Math.PI * next()); 42 | } 43 | 44 | function nextBool() { 45 | return (nextBigInt64() & 0x1n) === 0n; 46 | } 47 | 48 | export default { 49 | set seed(value) { 50 | if (typeof value !== 'bigint') value = BigInt(value); 51 | heap[current] = value; 52 | heap[seed] = nextBigInt64(); 53 | }, 54 | get seed() { 55 | return heap[seed]; 56 | }, 57 | nextInt8, 58 | nextUint8, 59 | nextInt16, 60 | nextUint16, 61 | nextInt32, 62 | nextUint32, 63 | nextBigInt64, 64 | nextBigUint64, 65 | next, 66 | nextGaussian, 67 | nextBool, 68 | }; 69 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asm-noise", 3 | "version": "1.0.6", 4 | "description": "An implementation of noise algorithms in asm.js.", 5 | "main": "./dist/asm-noise.js", 6 | "module": "./src/index.mjs", 7 | "unpkg": "./dist/asm-noise.js", 8 | "types": "./src/index.d.ts", 9 | "scripts": { 10 | "start": "webpack-dev-server --open --config webpack/webpack.development.js", 11 | "build": "webpack --config webpack/webpack.production.js", 12 | "deploy": "npx gh-pages -d examples", 13 | "prepublish": "npm run build", 14 | "benchmark": "node ./benchmark/index.mjs", 15 | "test": "jest" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/WesleyClements/asm-noise.git" 20 | }, 21 | "keywords": [ 22 | "fast", 23 | "noise", 24 | "perlin", 25 | "OpenSimplex", 26 | "function", 27 | "asm", 28 | "asm.js", 29 | "procedural", 30 | "generation", 31 | "generator", 32 | "generate", 33 | "2D", 34 | "3D", 35 | "4D" 36 | ], 37 | "author": "Wesley Clements ", 38 | "license": "MIT", 39 | "bugs": { 40 | "url": "https://github.com/WesleyClements/asm-noise/issues" 41 | }, 42 | "homepage": "https://github.com/WesleyClements/asm-noise#readme", 43 | "devDependencies": { 44 | "@babel/core": "^7.17.8", 45 | "@babel/preset-env": "^7.16.11", 46 | "@types/jest": "^27.4.1", 47 | "babel-loader": "^8.2.3", 48 | "benchmark": "^2.1.4", 49 | "eslint": "^8.11.0", 50 | "gh-pages": "^3.2.3", 51 | "jest": "^27.5.1", 52 | "webpack": "^5.70.0", 53 | "webpack-cli": "^4.9.2", 54 | "webpack-dev-server": "^4.7.4", 55 | "webpack-merge": "^5.8.0" 56 | } 57 | } -------------------------------------------------------------------------------- /examples/assets/js/noiseImageGeneration.js: -------------------------------------------------------------------------------- 1 | /* exported generateNoiseImageSync */ 2 | var generateNoiseImageSync = (() => { 3 | const getValueIndex = (resolution, resolutionX, i, j) => { 4 | return Math.floor(i * resolution) + Math.floor(j * resolution) * resolutionX; 5 | }; 6 | return ({ dimensions, scale, resolution, width, height }) => { 7 | const resolutionX = Math.floor(width * resolution) + 1; 8 | const resolutionY = Math.floor(height * resolution) + 1; 9 | 10 | const points = new Array(resolutionX * resolutionY); 11 | for (let i = 0; i < resolutionX; ++i) { 12 | for (let j = 0; j < resolutionY; ++j) { 13 | const index = i + j * resolutionX; 14 | points[index] = [(i / resolution) * scale, (j / resolution) * scale]; 15 | if (dimensions > 2) points[index].push((i / resolution) * scale); 16 | if (dimensions > 3) points[index].push((j / resolution) * scale); 17 | } 18 | } 19 | 20 | const noiseValues = new Float64Array(resolutionX * resolutionY); 21 | const start = (performance ?? Date).now(); 22 | for (let i = 0; i < resolutionX; ++i) { 23 | for (let j = 0; j < resolutionY; ++j) { 24 | const index = i + j * resolutionX; 25 | noiseValues[index] = noise(...points[index]); 26 | } 27 | } 28 | const dt = (performance ?? Date).now() - start; 29 | 30 | const imgData = new Uint8ClampedArray(width * height * 4); 31 | for (let i = 0; i < imgData.length; i += 4) { 32 | const x = (i / 4) % width; 33 | const y = Math.floor(i / (4 * width)); 34 | const value = 255 * noiseValues[getValueIndex(resolution, resolutionX, x, y)]; 35 | imgData[i + 0] = value; 36 | imgData[i + 1] = value; 37 | imgData[i + 2] = value; 38 | imgData[i + 3] = 255; 39 | } 40 | 41 | return { dt, noiseValues, imgData: new ImageData(imgData, width, height) }; 42 | }; 43 | })(); 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | .vscode/ 107 | 108 | umd/ 109 | 110 | package-lock.json -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | 84 | # Gatsby files 85 | .cache/ 86 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 87 | # https://nextjs.org/blog/next-9-1#public-directory-support 88 | # public 89 | 90 | # vuepress build output 91 | .vuepress/dist 92 | 93 | # Serverless directories 94 | .serverless/ 95 | 96 | # FuseBox cache 97 | .fusebox/ 98 | 99 | # DynamoDB Local files 100 | .dynamodb/ 101 | 102 | # TernJS port file 103 | .tern-port 104 | 105 | .vscode/ 106 | 107 | webpack/ 108 | 109 | package-lock.json -------------------------------------------------------------------------------- /src/index.mjs: -------------------------------------------------------------------------------- 1 | import algorithms, { defaultAlgorithm } from './algorithms/index.mjs'; 2 | 3 | const GOLDEN_RATIO = (1 + Math.sqrt(5)) / 2; 4 | 5 | const algorithmMap = new Map(Object.entries(algorithms)); 6 | const algorithmArray = Array.from(algorithmMap.keys()).sort(); 7 | 8 | const settings = { 9 | algorithm: defaultAlgorithm, 10 | octaves: 8, 11 | lacunarity: GOLDEN_RATIO, 12 | persistence: GOLDEN_RATIO - 1, 13 | offset: new Proxy( 14 | { 15 | x: 5393 * GOLDEN_RATIO, 16 | y: 4691 * GOLDEN_RATIO, 17 | z: 10093 * GOLDEN_RATIO, 18 | w: 9241 * GOLDEN_RATIO, 19 | }, 20 | { 21 | set(obj, prop, value) { 22 | if (!['x','y','z','w'].includes(prop)) Reflect.set(obj, prop, value); 23 | if (typeof value !== 'number') throw TypeError(`offset.${prop} must be a number`); 24 | if (Number.isNaN(value)) throw RangeError(`offset.${prop} cannot be NaN`); 25 | obj[prop] = value; 26 | }, 27 | } 28 | ), 29 | }; 30 | 31 | const getNoiseFunc = (dimensions) => { 32 | switch (dimensions) { 33 | case 2: 34 | return algorithmMap.get(settings.algorithm).noise2D; 35 | case 3: 36 | return algorithmMap.get(settings.algorithm).noise3D; 37 | default: 38 | return algorithmMap.get(settings.algorithm).noise4D; 39 | } 40 | }; 41 | 42 | const noise = Object.defineProperties( 43 | function noise(x, y, z, w) { 44 | const dimensions = arguments.length; 45 | if (dimensions < 2) return; 46 | const noiseFunc = getNoiseFunc(dimensions); 47 | return noiseFunc( 48 | settings.octaves, 49 | settings.lacunarity, 50 | settings.persistence, 51 | settings.offset.x, 52 | settings.offset.y, 53 | x, 54 | y, 55 | z, 56 | w 57 | ); 58 | }, 59 | { 60 | config: { 61 | value(options) { 62 | if (options == null) return; 63 | Object.entries(options) 64 | .filter(([key]) => Reflect.has(settings, key)) 65 | .forEach(([key, value]) => this[key] = value); 66 | return; 67 | }, 68 | }, 69 | algorithms: { 70 | get: () => Array.from(algorithmArray), 71 | }, 72 | algorithm: { 73 | get: () => settings.algorithm, 74 | set(value) { 75 | if (typeof value !== 'string') throw TypeError('algorithm must be a string'); 76 | if (!algorithmMap.has(value)) throw Error(`invalid algorithm: ${value}`); 77 | settings.algorithm = value; 78 | }, 79 | }, 80 | seed: { 81 | get: () => algorithmMap.get(settings.algorithm).seed, 82 | set(value) { 83 | algorithmMap.get(settings.algorithm).seed = value; 84 | }, 85 | }, 86 | octaves: { 87 | get: () => settings.octaves, 88 | set(value) { 89 | if (typeof value !== 'number') throw TypeError('octave must be a number'); 90 | if (Number.isNaN(value)) throw RangeError('octave cannot be NaN'); 91 | if (!Number.isInteger(value)) throw RangeError('octave must be integer'); 92 | if (value < 1) throw RangeError('octave must greater than 0'); 93 | settings.octaves = value; 94 | }, 95 | }, 96 | lacunarity: { 97 | get: () => settings.lacunarity, 98 | set(value) { 99 | if (typeof value !== 'number') throw TypeError('lacunarity must be a number'); 100 | if (Number.isNaN(value)) throw RangeError('lacunarity cannot be NaN'); 101 | if (value === 0) throw RangeError('lacunarity must not be 0'); 102 | settings.lacunarity = value; 103 | }, 104 | }, 105 | persistence: { 106 | get: () => settings.persistence, 107 | set(value) { 108 | if (typeof value !== 'number') throw TypeError('persistence must be a number'); 109 | if (Number.isNaN(value)) throw RangeError('persistence cannot be NaN'); 110 | if (value === 0) throw RangeError('persistence must not be 0'); 111 | settings.persistence = value; 112 | }, 113 | }, 114 | offset: { 115 | get: () => settings.offset, 116 | set(value) { 117 | if (typeof value != 'object') throw TypeError('offset must be a object'); 118 | if (value === null) throw TypeError('offset must not be null'); 119 | Object.entries(value) 120 | .filter(([key]) => Reflect.has(settings, key)) 121 | .forEach(([key, value]) => settings.offset[key] = value); 122 | }, 123 | }, 124 | } 125 | ); 126 | 127 | void setTimeout(() => { 128 | const primeNoise = noise => noise(...Array(9).fill(1)); 129 | algorithmMap.forEach(({ noise2D, noise3D, noise4D }) => { 130 | [noise2D, noise3D, noise4D].forEach(primeNoise); 131 | }); 132 | }, 0); 133 | 134 | export default noise; 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # asm-noise 2 | 3 | [![npm version](https://badge.fury.io/js/asm-noise.svg)](https://badge.fury.io/js/asm-noise) 4 | 5 | An implementation of noise algorithms in asm.js. 6 | Due to asm.js being deprecated, this package has no advantages to native JavaScript code. 7 | Check out [`simplex-noise`](https://www.npmjs.com/package/simplex-noise)! 8 | 9 | ## Table of Contents 10 | 11 | 1. [Installation](#installation) 12 | 1. [Usage](#usage) 13 | 1. [Options](#options) 14 | 1. [Roadmap](#roadmap) 15 | 1. [Contributing](#contributing) 16 | 1. [Acknowledgments](#acknowledgments) 17 | 1. [License](#license) 18 | 19 | ## [Installation](#installation) 20 | 21 | Using npm: 22 | 23 | ```shell 24 | npm install asm-noise 25 | ``` 26 | 27 | Using unpkg CDN: 28 | 29 | ```html 30 | 31 | ``` 32 | 33 | ## [Usage](#usage) 34 | 35 | Supports both CommonJS and ES Modules. 36 | 37 | ```javascript 38 | var noise = require('asm-noise'); 39 | ``` 40 | 41 | ```javascript 42 | import noise from 'asm-noise'; 43 | ``` 44 | 45 | When linked directly in HTML using CDN, functionality is exposed globally through `window.noise` . 46 | 47 | ```html 48 | 49 | ``` 50 | 51 | Generate noise: 52 | 53 | ```javascript 54 | var value2D = noise(0.1, 0.2); 55 | var value3D = noise(0.1, 0.2, 0.3); 56 | var value4D = noise(0.1, 0.2, 0.3, 0.4); 57 | ``` 58 | 59 | ## [Options](#options) 60 | 61 | Noise generation options can be set directly 62 | 63 | ```javascript 64 | noise.algorithm = 'open-simplex'; 65 | noise.seed = Date.now(); 66 | noise.octaves = 8; 67 | noise.lacunarity = (1 + Math.sqrt(5)) / 2; 68 | noise.persistence = (Math.sqrt(5) - 1) / 2; 69 | noise.offset = { 70 | x: (5393 * (1 + Math.sqrt(5))) / 2, 71 | y: (4691 * (1 + Math.sqrt(5))) / 2, 72 | z: (10093 * (1 + Math.sqrt(5))) / 2, 73 | w: (9241 * (1 + Math.sqrt(5))) / 2, 74 | }; 75 | ``` 76 | 77 | or by passing an options object to `noise.config` 78 | 79 | ```javascript 80 | noise.config({ ...options... }); 81 | ``` 82 | 83 | ### `algorithm` 84 | 85 | Type: `String` 86 | 87 | Noise generation algorithm to be used. 88 | Possible values: `open-simplex`, `perlin` 89 | 90 | Default: `'open-simplex'` 91 | 92 | ### `seed` 93 | 94 | Type: `Number` 95 | 96 | Default: `'open-simplex'` 97 | 98 | Value used to seed the internal state of the current noise generation algorithm. 99 | 100 | Default: `Date.now()` 101 | 102 | ### `octaves` 103 | 104 | Type: `Number` 105 | 106 | Number of itterations of noise to sum together when generating noise at single point. 107 | 108 | Default: `8` 109 | 110 | ### `lacunarity` 111 | 112 | Type: `Number` 113 | 114 | On the nth generation itteration, the generation point is scaled by this value raised to the nth power. 115 | 116 | Default: `(1 + Math.sqrt(5)) / 2` 117 | 118 | ### `persistence` 119 | 120 | Type: `Number` 121 | 122 | On the nth generation itteration, the nth noise value is scaled by this value raised to the nth power. 123 | 124 | Default: `(Math.sqrt(5) - 1) / 2` 125 | 126 | ### `offset` 127 | 128 | Type: `{ x: Number; y: Number; z: Number; w: Number; }` 129 | 130 | Contains axis specific values to add to the generation point every generation itteration. 131 | 132 | Default: 133 | 134 | ```javascript 135 | { 136 | x: (5393 * (1 + Math.sqrt(5))) / 2, 137 | y: (4691 * (1 + Math.sqrt(5))) / 2, 138 | z: (10093 * (1 + Math.sqrt(5))) / 2, 139 | w: (9241 * (1 + Math.sqrt(5))) / 2, 140 | } 141 | ``` 142 | 143 | ## [Roadmap](#roadmap) 144 | 145 | - Improve performance of algorithm implementations 146 | - Implement additional algorithms 147 | - Add batch generation 148 | 149 | ## [Contributing](#contributing) 150 | 151 | Pull requests are welcome. 152 | 153 | To implement a new noise generation algorithm: 154 | 155 | 1. Create a file in the `src` directory with the name of the algorithm. 156 | 1. This file should be an ES Module. 157 | 1. The deafult export of this file should be an object with following properties: 158 | 159 | - ```javascript 160 | seed: number; 161 | ``` 162 | - ```javascript 163 | noise2D: function(octaves, lacunarity, persistence, xOffset, yOffset, x, y) => number 164 | ``` 165 | - ```javascript 166 | noise3D: function(octaves, lacunarity, persistence, xOffset, yOffset, zOffset, x, y, z) => number 167 | ``` 168 | - ```javascript 169 | noise4D: function(octaves, lacunarity, persistence, xOffset, yOffset, zOffset, wOffset, x, y, z, w) => number 170 | ``` 171 | 172 | ## [Acknowledgments](#acknowledgments) 173 | 174 | Many thanks to [@KdotJPG](https://github.com/KdotJPG) for the creation of OpenSimplex noise algorithm. 175 | 176 | ## [License](#license) 177 | 178 | This project is licensed under the terms of the MIT license. 179 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | asm-noise 11 | 12 | 13 | 14 | 17 |
18 |
19 |
20 |
21 | 22 | 23 | 24 |
25 |

Noise

26 | 27 | 28 | 29 |
30 |
31 |
32 | 33 |
34 |
35 |
36 |
37 | 41 |
42 |
43 |
44 |
45 | 50 |
51 |
52 |
53 |
54 |
55 |
56 | 57 |
58 | 59 |
60 |
61 |
62 |
63 | 64 |
65 |
66 |
67 |
68 | 69 |
70 |
71 | 73 |
74 |
75 |
76 |
77 |
78 |
79 | 80 |
81 |
82 |
83 |
84 | 85 |
86 |
87 | 89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | 98 |
99 |
100 | 101 |
102 |
103 |
104 | 105 |
106 |
107 |
108 | 109 |
110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /src/___test___/index.test.js: -------------------------------------------------------------------------------- 1 | const noise = require('../../dist/asm-noise'); 2 | 3 | describe('noise', () => { 4 | const getTypesExcept = (type) => [undefined, null, true, 1, 1n, Symbol(), {}, () => {}].filter(value => typeof value !== type); 5 | 6 | const getRandomNumber = () => (2*Math.random() - 1) * Number.MAX_SAFE_INTEGER; 7 | 8 | it('should export a function', () => { 9 | expect(typeof noise).toBe('function'); 10 | }); 11 | 12 | it('should return a number when given 2 arguments', () => { 13 | noise.algorithms.forEach((algorithm) => { 14 | noise.algorithm = algorithm; 15 | Array(100).fill().forEach(() => { 16 | expect(noise(getRandomNumber(), getRandomNumber())).toEqual(expect.any(Number)); 17 | }); 18 | }); 19 | }); 20 | 21 | it('should return a number when given 3 arguments', () => { 22 | noise.algorithms.forEach((algorithm) => { 23 | noise.algorithm = algorithm; 24 | Array(100).fill().forEach(() => { 25 | expect(noise(getRandomNumber(), getRandomNumber(), getRandomNumber())).toEqual(expect.any(Number)); 26 | }); 27 | }); 28 | }); 29 | 30 | it('should return a number when given 4 arguments', () => { 31 | noise.algorithms.forEach((algorithm) => { 32 | noise.algorithm = algorithm; 33 | Array(100).fill().forEach(() => { 34 | expect(noise(getRandomNumber(), getRandomNumber(), getRandomNumber(), getRandomNumber())).toEqual(expect.any(Number)); 35 | }); 36 | }); 37 | }); 38 | 39 | describe('algorithm', () => { 40 | it('should be a property of noise', () => { 41 | expect(noise.algorithm).toEqual(expect.any(String)); 42 | }); 43 | it('throws a TypeError when set to a type other than string', () => { 44 | getTypesExcept('string').forEach(invalidType => { 45 | expect(() => noise.algorithm = invalidType).toThrow(TypeError); 46 | expect(noise.algorithm).not.toBe(invalidType); 47 | }); 48 | }); 49 | it('throws a Error when set to an invalid algorithm', () => { 50 | ['cat', 'dog'].forEach((invalidAlgorithm) => { 51 | expect(() => noise.algorithm = invalidAlgorithm).toThrow(Error); 52 | expect(noise.algorithm).not.toBe(invalidAlgorithm); 53 | }); 54 | }); 55 | it('can be set to any valid algorithm', () => { 56 | noise.algorithms.forEach((validAlgorithm) => { 57 | expect(() => noise.algorithm = validAlgorithm).not.toThrow(); 58 | expect(noise.algorithm).toBe(validAlgorithm); 59 | }); 60 | }); 61 | }); 62 | describe('seed', () => { 63 | it('should be a property of noise', () => { 64 | expect(noise.seed).toEqual(expect.any(Number)); 65 | }); 66 | it('gets set to a number', () => { 67 | Array(100).fill(() => getRandomNumber()) 68 | .map(generator => generator()) 69 | .forEach(seed => { 70 | noise.seed = seed; 71 | expect(noise.seed).toBe(seed); 72 | }); 73 | }); 74 | }); 75 | ['octaves', 'lacunarity', 'persistence'].forEach((prop) => { 76 | describe(prop, () => { 77 | it('should be a property of noise', () => { 78 | expect(noise[prop]).toEqual(expect.any(Number)); 79 | }); 80 | it; 81 | it('throws a TypeError when set to a type other than number', () => { 82 | getTypesExcept('number').forEach(invalidType => { 83 | expect(() => noise[prop] = invalidType).toThrow(TypeError); 84 | expect(noise[prop]).not.toBe(invalidType); 85 | }); 86 | }); 87 | it('throws a RangeError when set to NaN', () => { 88 | expect(() => noise[prop] = NaN).toThrow(RangeError); 89 | expect(noise[prop]).not.toBeNaN(); 90 | }); 91 | }); 92 | }); 93 | 94 | describe('octaves', () => {{ 95 | it('throws a RangeError when set to a number that is not an integer', () => { 96 | Array(100).fill(() => getRandomNumber()) 97 | .map(generator => generator()) 98 | .filter(num => !Number.isInteger(num)) 99 | .forEach((num) => { 100 | expect(() => noise.octaves = num).toThrow(RangeError); 101 | expect(noise.octaves).not.toBe(num); 102 | }); 103 | }); 104 | it('throws a RangeError when set to a number less than 1', () => { 105 | Array(100).fill(() => 1 - Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)) 106 | .map(generator => generator()) 107 | .forEach((num) => { 108 | expect(() => noise.octaves = num).toThrow(RangeError); 109 | expect(noise.octaves).not.toBe(num); 110 | }); 111 | }); 112 | }}); 113 | 114 | describe('lacunarity', () => {{ 115 | it('throws a RangeError when set to 0', () => { 116 | expect(() => noise.octaves = 0).toThrow(RangeError); 117 | expect(noise.octaves).not.toBe(0); 118 | }); 119 | }}); 120 | 121 | describe('persistence', () => {{ 122 | it('throws a RangeError when set to 0', () => { 123 | expect(() => noise.octaves = 0).toThrow(RangeError); 124 | expect(noise.octaves).not.toBe(0); 125 | }); 126 | }}); 127 | }); -------------------------------------------------------------------------------- /examples/assets/js/index.js: -------------------------------------------------------------------------------- 1 | /*global generateNoiseImageSync */ 2 | (() => { 3 | const noiseWorker = window.Worker ? new Worker("./assets/js/noiseWorker.js") : null; 4 | const main = document.querySelector("main"); 5 | 6 | const canvas = main.querySelector("canvas"); 7 | const ui = main.querySelector("#ui"); 8 | const uiToggle = ui.querySelector("#ui-toggle"); 9 | const uiContent = ui.querySelector("#ui-content"); 10 | 11 | // config inputs 12 | const algorithmSelect = ui.querySelector("#algorithm-select"); 13 | const dimensionSelect = ui.querySelector("#dimension-select"); 14 | const seedInput = ui.querySelector("input[name=seed]"); 15 | const scaleInput = ui.querySelector("input[name=scale]"); 16 | const scaleSlider = ui.querySelector("input[name=scale-slider]"); 17 | const resolutionInput = ui.querySelector("input[name=resolution]"); 18 | const resolutionSlider = ui.querySelector("input[name=resolution-slider]"); 19 | const generateBtn = ui.querySelector("#generate-btn"); 20 | const saveBtn = ui.querySelector("#save-btn"); 21 | 22 | const configInputs = [ 23 | algorithmSelect, 24 | dimensionSelect, 25 | seedInput, 26 | scaleInput, 27 | scaleSlider, 28 | resolutionInput, 29 | resolutionSlider, 30 | generateBtn, 31 | saveBtn, 32 | ]; 33 | 34 | const generationMetricsSpan = ui.querySelector("#generation-metrics"); 35 | 36 | let renderCount = 0; 37 | 38 | seedInput.value = noise.seed; 39 | 40 | const wait = (ms = 0) => new Promise((resolve) => setTimeout(() => resolve(), ms)); 41 | 42 | const updateCanvasDimensions = () => { 43 | canvas.width = canvas.height = innerWidth > innerHeight ? innerHeight : innerWidth; 44 | }; 45 | 46 | const calculateScale = (n) => 10 ** n; 47 | 48 | const configNoise = () => 49 | noise.config({ algorithm: algorithmSelect.value, seed: seedInput.value }); 50 | 51 | const getNoiseImageFromWorker = 52 | noiseWorker && 53 | (async (settings) => { 54 | return await new Promise((resolve) => { 55 | const onMessage = (e) => { 56 | noiseWorker.removeEventListener("message", onMessage); 57 | resolve(e.data); 58 | }; 59 | noiseWorker.addEventListener("message", onMessage); 60 | noiseWorker.postMessage(settings); 61 | }); 62 | }); 63 | 64 | const generateNoiseImage = async ({ dimensions, scale, resolution, width, height }) => { 65 | const settings = { 66 | seed: noise.seed, 67 | algorithm: noise.algorithm, 68 | dimensions, 69 | scale, 70 | resolution, 71 | width, 72 | height, 73 | }; 74 | const generate = getNoiseImageFromWorker ?? generateNoiseImageSync; 75 | const { dt, noiseValues, imgData } = await generate(settings); 76 | return { 77 | dt: dt.toLocaleString(undefined, { 78 | maximumFractionDigits: 2, 79 | }), 80 | noiseValues, 81 | imgData, 82 | }; 83 | }; 84 | 85 | const renderNoise = (() => { 86 | let renderHandle; 87 | let rendering = false; 88 | return () => { 89 | if (rendering) return; 90 | clearTimeout(renderHandle); 91 | renderHandle = setTimeout(async () => { 92 | rendering = true; 93 | 94 | generateBtn.classList.add("is-loading", "disabled"); 95 | 96 | // disable config inputs while rendering 97 | configInputs.forEach((configInput) => configInput.setAttribute("disabled", true)); 98 | 99 | // wait on a timeout to allow browser to do it's stuff 100 | await wait(); 101 | 102 | const { dt, noiseValues, imgData } = await generateNoiseImage({ 103 | dimensions: dimensionSelect.value, 104 | scale: calculateScale(scaleSlider.value), 105 | resolution: resolutionSlider.value / 100, 106 | width: canvas.width, 107 | height: canvas.height, 108 | }); 109 | 110 | // re-enble config inputs after rendering 111 | configInputs.forEach((configInput) => configInput.removeAttribute("disabled")); 112 | 113 | generateBtn.classList.remove("is-loading", "disabled"); 114 | [canvas, generationMetricsSpan].forEach((hiddenEl) => (hiddenEl.style.display = null)); 115 | 116 | generationMetricsSpan.textContent = `Generated ${noiseValues.length} noise values in ${dt}ms`; 117 | 118 | // render image to screen after the browser does it's stuff 119 | await wait(); 120 | const ctx = canvas.getContext("2d"); 121 | ctx.clearRect(0, 0, canvas.width, canvas.height); 122 | ctx.putImageData(imgData, 0, 0); 123 | 124 | rendering = false; 125 | renderCount++; 126 | }, 100); 127 | }; 128 | })(); 129 | 130 | window.addEventListener("resize", () => { 131 | updateCanvasDimensions(); 132 | if (renderCount) renderNoise(); 133 | }); 134 | 135 | ui.addEventListener("mousedown", (e) => { 136 | if (!e.target.closest("#ui-handle")) return; 137 | e.preventDefault(); 138 | 139 | const rect = ui.getBoundingClientRect(); 140 | const { width, height } = rect; 141 | const xOffset = 2 * (rect.x - e.x); 142 | const yOffset = 2 * (rect.y - e.y); 143 | 144 | const onMouseMove = (e) => { 145 | e.preventDefault(); 146 | ui.style.top = e.pageY + yOffset + "px"; 147 | ui.style.left = e.pageX + xOffset + "px"; 148 | ui.style.bottom = null; 149 | ui.style.right = null; 150 | }; 151 | const finalizeMove = (e) => { 152 | e.preventDefault(); 153 | let { x, y } = ui.getBoundingClientRect(); 154 | 155 | if (y < 0) { 156 | ui.style.top = 0; 157 | ui.style.bottom = null; 158 | } else if (y + height > innerHeight) { 159 | ui.style.top = null; 160 | ui.style.bottom = 0; 161 | } else { 162 | ui.style.bottom = null; 163 | } 164 | if (x < 0) { 165 | ui.style.left = 0; 166 | ui.style.right = null; 167 | } else if (x + width > innerWidth) { 168 | ui.style.left = null; 169 | ui.style.right = 0; 170 | } else { 171 | ui.style.right = null; 172 | } 173 | document.removeEventListener("mousemove", onMouseMove); 174 | window.removeEventListener("mouseup", finalizeMove); 175 | document.removeEventListener("blur", finalizeMove); 176 | }; 177 | document.addEventListener("mousemove", onMouseMove); 178 | window.addEventListener("mouseup", finalizeMove); 179 | document.addEventListener("blur", finalizeMove); 180 | }); 181 | 182 | (function () { 183 | let showUI = true; 184 | uiToggle.addEventListener("click", () => { 185 | showUI = !showUI; 186 | if (showUI) { 187 | uiToggle.innerHTML = ""; 188 | uiContent.removeAttribute("style"); 189 | } else { 190 | uiToggle.innerHTML = ""; 191 | uiContent.style.display = "none"; 192 | } 193 | }); 194 | })(); 195 | 196 | (function () { 197 | let configNoiseHandle; 198 | 199 | algorithmSelect.addEventListener("change", () => { 200 | clearTimeout(configNoiseHandle); 201 | configNoise(); 202 | }); 203 | seedInput.addEventListener("keydown", () => { 204 | clearTimeout(configNoiseHandle); 205 | configNoiseHandle = setTimeout(() => { 206 | if (isNaN(seedInput.value)) { 207 | seedInput.value = noise.seed; 208 | return; 209 | } 210 | configNoise(); 211 | }, 300); 212 | }); 213 | })(); 214 | 215 | (function () { 216 | let updateScaleHandle; 217 | scaleInput.addEventListener("keydown", () => { 218 | clearTimeout(updateScaleHandle); 219 | updateScaleHandle = setTimeout(() => { 220 | if (isNaN(scaleInput.value) || scaleInput.value <= 0) { 221 | scaleInput.value = scaleSlider.value; 222 | return; 223 | } 224 | scaleSlider.value = Math.log10(scaleInput.value); 225 | }, 300); 226 | }); 227 | scaleSlider.addEventListener("input", () => { 228 | clearTimeout(updateScaleHandle); 229 | scaleInput.value = calculateScale(scaleSlider.value).toLocaleString(undefined, { 230 | maximumFractionDigits: 7, 231 | }); 232 | }); 233 | })(); 234 | 235 | (function () { 236 | let updateResolutionHandle; 237 | resolutionInput.addEventListener("keydown", () => { 238 | clearTimeout(updateResolutionHandle); 239 | if (!resolutionInput.value) return; 240 | updateResolutionHandle = setTimeout(() => { 241 | if (isNaN(resolutionInput.value) || resolutionInput.value <= 0) { 242 | resolutionInput.value = resolutionSlider.value + "%"; 243 | return; 244 | } 245 | resolutionSlider.value = scaleInput.value; 246 | resolutionInput.value += "%"; 247 | }, 300); 248 | }); 249 | resolutionSlider.addEventListener("input", () => { 250 | clearTimeout(updateResolutionHandle); 251 | resolutionInput.value = resolutionSlider.value + "%"; 252 | }); 253 | })(); 254 | 255 | generateBtn.addEventListener("click", renderNoise); 256 | saveBtn.addEventListener("click", () => { 257 | const link = document.createElement("a"); 258 | link.setAttribute("download", algorithmSelect.value + "-noise"); 259 | link.setAttribute("href", canvas.toDataURL("image/png")); 260 | link.click(); 261 | }); 262 | 263 | updateCanvasDimensions(); 264 | })(); 265 | -------------------------------------------------------------------------------- /src/algorithms/perlin.mjs: -------------------------------------------------------------------------------- 1 | import random from '../util/random.mjs'; 2 | 3 | function Perlin(stdlib, foreign, heap) { 4 | 'use asm'; 5 | 6 | var floor = stdlib.Math.floor; 7 | 8 | var _setSeed = foreign.setSeed; 9 | var nextU8 = foreign.nextUint8; 10 | 11 | var heapU8 = new stdlib.Uint8Array(heap); 12 | 13 | function setSeed(value) { 14 | value = value | 0; 15 | var i = 0; 16 | var r = 0; 17 | var t = 0; 18 | 19 | _setSeed(value | 0); 20 | 21 | for (i = 0; (i | 0) < 0x100; i = (i + 1) | 0) { 22 | heapU8[i] = i | 0; 23 | } 24 | for (i = 0; (i | 0) < 0x100; i = (i + 1) | 0) { 25 | r = nextU8() | 0; 26 | t = heapU8[i] | 0; 27 | heapU8[i] = heapU8[r] | 0; 28 | heapU8[r] = heapU8[t] | 0; 29 | } 30 | for (i = 0; (i | 0) < 0x100; i = (i + 1) | 0) { 31 | heapU8[(i + 0x100) | 0] = heapU8[i] | 0; 32 | } 33 | } 34 | 35 | function lerp(a, b, t) { 36 | a = +a; 37 | b = +b; 38 | t = +t; 39 | return +(a + (b - a) * t); 40 | } 41 | 42 | function fade(t) { 43 | t = +t; 44 | var result = 0.0; 45 | result = +(t * 6.0 - 15.0); 46 | result = +(t * result + 10.0); 47 | result = +(t * t * t * result); 48 | return +result; 49 | } 50 | 51 | function normalize(n) { 52 | n = +n; 53 | return (n + 1.0) / 2.0; 54 | } 55 | 56 | function noise2D(octaves, lacunarity, persistence, xOffset, yOffset, x, y) { 57 | octaves = octaves | 0; 58 | lacunarity = +lacunarity; 59 | persistence = +persistence; 60 | xOffset = +xOffset; 61 | yOffset = +yOffset; 62 | x = +x; 63 | y = +y; 64 | var total = 0.0; 65 | var frequency = 1.0; 66 | var amplitude = 1.0; 67 | var max = 0.0; 68 | var i = 0; 69 | for (i = 0; (i | 0) < (octaves | 0); i = (i + 1) | 0) { 70 | total = total + +eval2D(x * frequency, y * frequency) * amplitude; 71 | max = max + amplitude; 72 | frequency = frequency * lacunarity; 73 | amplitude = amplitude * persistence; 74 | x = x + xOffset; 75 | y = y + yOffset; 76 | } 77 | return total / max; 78 | } 79 | 80 | function grad2D(hash, x, y) { 81 | hash = hash | 0; 82 | x = +x; 83 | y = +y; 84 | var grad = 0.0; 85 | hash = hash & 0xf; 86 | switch (hash >> 2) { 87 | case 0b00: 88 | grad = (hash & 0b01 ? x : -x) + (hash & 0b10 ? y : -y); 89 | break; 90 | case 0b01: 91 | return hash & 0b01 ? x : -x; 92 | case 0b10: 93 | return hash & 0b10 ? y : -y; 94 | case 0b11: 95 | grad = (hash & 0b01 ? -x : x) + (hash & 0b10 ? -y : y); 96 | break; 97 | } 98 | return grad; 99 | } 100 | 101 | function eval2D(x, y) { 102 | x = +x; 103 | y = +y; 104 | var xi = 0; 105 | var yi = 0; 106 | var a = 0.0; 107 | var b = 0.0; 108 | 109 | var A = 0; 110 | var B = 0; 111 | 112 | xi = ~~floor(x) & 0xff; 113 | yi = ~~floor(y) & 0xff; 114 | x = x - floor(x); 115 | y = y - floor(y); 116 | a = +fade(x); 117 | b = +fade(y); 118 | 119 | A = (heapU8[xi] + yi) | 0; 120 | B = (heapU8[xi + 1] + yi) | 0; 121 | 122 | return +normalize( 123 | +lerp( 124 | +lerp(+grad2D(heapU8[A] | 0, x, y), +grad2D(heapU8[B] | 0, x - 1.0, y), a), 125 | +lerp(+grad2D(heapU8[A + 1] | 0, x, y - 1.0), +grad2D(heapU8[B + 1] | 0, x - 1.0, y - 1.0), a), 126 | b 127 | ) 128 | ); 129 | } 130 | 131 | function noise3D(octaves, lacunarity, persistence, xOffset, yOffset, zOffset, x, y, z) { 132 | octaves = octaves | 0; 133 | lacunarity = +lacunarity; 134 | persistence = +persistence; 135 | xOffset = +xOffset; 136 | yOffset = +yOffset; 137 | zOffset = +zOffset; 138 | x = +x; 139 | y = +y; 140 | z = +z; 141 | var total = 0.0; 142 | var frequency = 1.0; 143 | var amplitude = 1.0; 144 | var max = 0.0; 145 | var i = 0; 146 | for (i = 0; (i | 0) < (octaves | 0); i = (i + 1) | 0) { 147 | total = total + +eval3D(x * frequency, y * frequency, z * frequency) * amplitude; 148 | max = max + amplitude; 149 | frequency = frequency * lacunarity; 150 | amplitude = amplitude * persistence; 151 | x = x + xOffset; 152 | y = y + yOffset; 153 | z = z + zOffset; 154 | } 155 | return total / max; 156 | } 157 | 158 | function grad3D(hash, x, y, z) { 159 | hash = hash | 0; 160 | x = +x; 161 | y = +y; 162 | z = +z; 163 | var grad = 0.09; 164 | switch (hash & 0xf) { 165 | case 0: 166 | grad = x + y; 167 | break; 168 | case 1: 169 | grad = -x + y; 170 | break; 171 | case 2: 172 | grad = x - y; 173 | break; 174 | case 3: 175 | grad = -x - y; 176 | break; 177 | case 4: 178 | grad = x + z; 179 | break; 180 | case 5: 181 | grad = -x + z; 182 | break; 183 | case 6: 184 | grad = x - z; 185 | break; 186 | case 7: 187 | grad = -x - z; 188 | break; 189 | case 8: 190 | grad = y + z; 191 | break; 192 | case 9: 193 | grad = -y + z; 194 | break; 195 | case 10: 196 | grad = y - z; 197 | break; 198 | case 11: 199 | grad = -y - z; 200 | break; 201 | case 12: 202 | grad = y + x; 203 | break; 204 | case 13: 205 | grad = -x + y; 206 | break; 207 | case 14: 208 | grad = -y + z; 209 | break; 210 | case 15: 211 | grad = -y - z; 212 | break; 213 | } 214 | return grad; 215 | } 216 | 217 | function eval3D(x, y, z) { 218 | x = +x; 219 | y = +y; 220 | z = +z; 221 | var xi = 0; 222 | var yi = 0; 223 | var zi = 0; 224 | var a = 0.0; 225 | var b = 0.0; 226 | var c = 0.0; 227 | 228 | var A = 0; 229 | var B = 0; 230 | var AA = 0; 231 | var BA = 0; 232 | var AB = 0; 233 | var BB = 0; 234 | 235 | xi = ~~floor(x) & 0xff; 236 | yi = ~~floor(y) & 0xff; 237 | zi = ~~floor(z) & 0xff; 238 | x = x - floor(x); 239 | y = y - floor(y); 240 | z = z - floor(z); 241 | a = +fade(x); 242 | b = +fade(y); 243 | c = +fade(z); 244 | 245 | A = (heapU8[xi] + yi) | 0; 246 | B = (heapU8[xi + 1] + yi) | 0; 247 | AA = (heapU8[A] + zi) | 0; 248 | BA = (heapU8[B] + zi) | 0; 249 | AB = (heapU8[A + 1] + zi) | 0; 250 | BB = (heapU8[B + 1] + zi) | 0; 251 | 252 | return +normalize( 253 | +lerp( 254 | +lerp( 255 | +lerp(+grad3D(heapU8[AA] | 0, x, y, z), +grad3D(heapU8[BA] | 0, x - 1.0, y, z), a), 256 | +lerp(+grad3D(heapU8[AB] | 0, x, y - 1.0, z), +grad3D(heapU8[BB] | 0, x - 1.0, y - 1.0, z), a), 257 | b 258 | ), 259 | +lerp( 260 | +lerp(+grad3D(heapU8[AA + 1] | 0, x, y, z - 1.0), +grad3D(heapU8[BA + 1] | 0, x - 1.0, y, z - 1.0), a), 261 | +lerp( 262 | +grad3D(heapU8[AB + 1] | 0, x, y - 1.0, z - 1.0), 263 | +grad3D(heapU8[BB + 1] | 0, x - 1.0, y - 1.0, z - 1.0), 264 | a 265 | ), 266 | b 267 | ), 268 | c 269 | ) 270 | ); 271 | } 272 | 273 | function noise4D(octaves, lacunarity, persistence, xOffset, yOffset, zOffset, wOffset, x, y, z, w) { 274 | octaves = octaves | 0; 275 | lacunarity = +lacunarity; 276 | persistence = +persistence; 277 | xOffset = +xOffset; 278 | yOffset = +yOffset; 279 | zOffset = +zOffset; 280 | wOffset = +wOffset; 281 | x = +x; 282 | y = +y; 283 | z = +z; 284 | w = +w; 285 | var total = 0.0; 286 | var frequency = 1.0; 287 | var amplitude = 1.0; 288 | var max = 0.0; 289 | var i = 0; 290 | for (i = 0; (i | 0) < (octaves | 0); i = (i + 1) | 0) { 291 | total = total + +eval4D(x * frequency, y * frequency, z * frequency, w * frequency) * amplitude; 292 | max = max + amplitude; 293 | frequency = frequency * lacunarity; 294 | amplitude = amplitude * persistence; 295 | x = x + xOffset; 296 | y = y + yOffset; 297 | z = z + zOffset; 298 | w = w + wOffset; 299 | } 300 | return total / max; 301 | } 302 | 303 | function grad4D(hash, x, y, z, w) { 304 | hash = hash | 0; 305 | x = +x; 306 | y = +y; 307 | z = +z; 308 | w = +w; 309 | hash = hash & 0x1f; 310 | switch (hash >> 3) { 311 | case 0b01: 312 | return ((hash & 4) == 0 ? -w : w) + ((hash & 2) == 0 ? -x : x) + ((hash & 1) == 0 ? -y : y); 313 | case 0b10: 314 | return ((hash & 4) == 0 ? -z : z) + ((hash & 2) == 0 ? -w : w) + ((hash & 1) == 0 ? -x : x); 315 | case 0b11: 316 | return ((hash & 4) == 0 ? -y : y) + ((hash & 2) == 0 ? -z : z) + ((hash & 1) == 0 ? -w : w); 317 | } 318 | return ((hash & 4) == 0 ? -x : x) + ((hash & 2) == 0 ? -y : y) + ((hash & 1) == 0 ? -z : z); 319 | } 320 | 321 | function eval4D(x, y, z, w) { 322 | x = +x; 323 | y = +y; 324 | z = +z; 325 | w = +w; 326 | var xi = 0; 327 | var yi = 0; 328 | var zi = 0; 329 | var wi = 0; 330 | var a = 0.0; 331 | var b = 0.0; 332 | var c = 0.0; 333 | var d = 0.0; 334 | 335 | var A = 0; 336 | var B = 0; 337 | var AA = 0; 338 | var BA = 0; 339 | var AB = 0; 340 | var BB = 0; 341 | var AAA = 0; 342 | var BAA = 0; 343 | var ABA = 0; 344 | var BBA = 0; 345 | var AAB = 0; 346 | var BAB = 0; 347 | var ABB = 0; 348 | var BBB = 0; 349 | 350 | xi = ~~floor(x) & 0xff; 351 | yi = ~~floor(y) & 0xff; 352 | zi = ~~floor(z) & 0xff; 353 | wi = ~~floor(w) & 0xff; 354 | x = x - floor(x); 355 | y = y - floor(y); 356 | z = z - floor(z); 357 | w = w - floor(w); 358 | a = +fade(x); 359 | b = +fade(y); 360 | c = +fade(z); 361 | d = +fade(w); 362 | 363 | A = (heapU8[xi] + yi) | 0; 364 | B = (heapU8[xi + 1] + yi) | 0; 365 | AA = (heapU8[A] + zi) | 0; 366 | BA = (heapU8[B] + zi) | 0; 367 | AB = (heapU8[A + 1] + zi) | 0; 368 | BB = (heapU8[B + 1] + zi) | 0; 369 | AAA = (heapU8[AA] + wi) | 0; 370 | BAA = (heapU8[BA] + wi) | 0; 371 | ABA = (heapU8[AB] + wi) | 0; 372 | BBA = (heapU8[BB] + wi) | 0; 373 | AAB = (heapU8[AA + 1] + wi) | 0; 374 | BAB = (heapU8[BA + 1] + wi) | 0; 375 | ABB = (heapU8[AB + 1] + wi) | 0; 376 | BBB = (heapU8[BB + 1] + wi) | 0; 377 | return +normalize( 378 | +lerp( 379 | +lerp( 380 | +lerp( 381 | +lerp(+grad4D(heapU8[AAA] | 0, x, y, z, w), +grad4D(heapU8[BAA] | 0, x - 1.0, y, z, w), a), 382 | +lerp(+grad4D(heapU8[ABA] | 0, x, y - 1.0, z, w), +grad4D(heapU8[BBA] | 0, x - 1.0, y - 1.0, z, w), a), 383 | b 384 | ), 385 | +lerp( 386 | +lerp(+grad4D(heapU8[AAB] | 0, x, y, z - 1.0, w), +grad4D(heapU8[BAB] | 0, x - 1.0, y, z - 1.0, w), a), 387 | +lerp( 388 | +grad4D(heapU8[ABB] | 0, x, y - 1.0, z - 1.0, w), 389 | +grad4D(heapU8[BBB] | 0, x - 1.0, y - 1.0, z - 1.0, w), 390 | a 391 | ), 392 | b 393 | ), 394 | c 395 | ), 396 | +lerp( 397 | +lerp( 398 | +lerp( 399 | +grad4D(heapU8[AAA + 1] | 0, x, y, z, w - 1.0), 400 | +grad4D(heapU8[BAA + 1] | 0, x - 1.0, y, z, w - 1.0), 401 | a 402 | ), 403 | +lerp( 404 | +grad4D(heapU8[ABA + 1] | 0, x, y - 1.0, z, w - 1.0), 405 | +grad4D(heapU8[BBA + 1] | 0, x - 1.0, y - 1.0, z, w - 1.0), 406 | a 407 | ), 408 | b 409 | ), 410 | +lerp( 411 | +lerp( 412 | +grad4D(heapU8[AAB + 1] | 0, x, y, z - 1.0, w - 1.0), 413 | +grad4D(heapU8[BAB + 1] | 0, x - 1.0, y, z - 1.0, w - 1.0), 414 | a 415 | ), 416 | +lerp( 417 | +grad4D(heapU8[ABB + 1] | 0, x, y - 1.0, z - 1.0, w - 1.0), 418 | +grad4D(heapU8[BBB + 1] | 0, x - 1.0, y - 1.0, z - 1.0, w - 1.0), 419 | a 420 | ), 421 | b 422 | ), 423 | c 424 | ), 425 | d 426 | ) 427 | ); 428 | } 429 | 430 | return { 431 | setSeed: setSeed, 432 | noise2D: noise2D, 433 | noise3D: noise3D, 434 | noise4D: noise4D, 435 | }; 436 | } 437 | 438 | const heap = new ArrayBuffer(0x10000); 439 | const { setSeed, noise2D, noise3D, noise4D } = Perlin( 440 | { 441 | Math, 442 | Uint8Array, 443 | }, 444 | { 445 | setSeed: (value) => (random.seed = value), 446 | nextUint8: random.nextUint8, 447 | }, 448 | heap 449 | ); 450 | 451 | let seed = Date.now(); 452 | setSeed(seed); 453 | 454 | export default { 455 | set seed(value) { 456 | seed = value; 457 | setSeed(seed); 458 | }, 459 | get seed() { 460 | return seed; 461 | }, 462 | noise2D, 463 | noise3D, 464 | noise4D, 465 | }; 466 | -------------------------------------------------------------------------------- /src/algorithms/openSimplex.mjs: -------------------------------------------------------------------------------- 1 | import random from '../util/random'; 2 | 3 | function OpenSimplex(stdlib, foreign, heap) { 4 | 'use asm'; 5 | 6 | var imul = stdlib.Math.imul; 7 | var floor = stdlib.Math.floor; 8 | 9 | var _setSeed = foreign.setSeed; 10 | var nextU32 = foreign.nextUint32; 11 | 12 | var heapU16 = new stdlib.Uint16Array(heap); 13 | var heapU32 = new stdlib.Uint32Array(heap); 14 | var heapI32 = new stdlib.Int32Array(heap); 15 | var heapF64 = new stdlib.Float64Array(heap); 16 | 17 | var pSize = 0x800; 18 | var pMask = 0x7ff; 19 | 20 | var X = 0x00; 21 | var Y = 0x08; 22 | var Z = 0x10; 23 | var W = 0x18; 24 | 25 | var XI = 0x0; 26 | var YI = 0x4; 27 | var ZI = 0x8; 28 | var WI = 0xc; 29 | 30 | var contribution2D = 0x18; // 2 * 8 bytes + 2 * 4 bytes 31 | var contribution3D = 0x28; // 3 * 8 bytes + 3 * 4 bytes 32 | var contribution4D = 0x30; // 4 * 8 bytes + 4 * 4 bytes 33 | 34 | var perm = 0x0; // 2048 permutations * 2 byte 35 | 36 | var stretchConstant2D = 0x1000; 37 | var stretchConstant3D = 0x1008; 38 | var stretchConstant4D = 0x1010; 39 | 40 | var squishConstant2D = 0x1018; 41 | var squishConstant3D = 0x1020; 42 | var squishConstant4D = 0x1028; 43 | 44 | var gradients2D = 0x01030; // 2048 gradients * 2 dimensions * 8 bytes 45 | var gradients3D = 0x09030; // 2048 gradients * 3 dimensions * 8 bytes 46 | var gradients4D = 0x15030; // 2048 gradients * 4 dimensions * 8 bytes 47 | 48 | var lookUp2D = 0x25030; // 64 * 4 bytes 49 | var contributions2D = 0x25130; // 24 * (2 * 8 bytes + 2 * 4 bytes) 50 | 51 | var lookUp3D = 0x25370; // 2048 * 4 bytes 52 | var contributions3D = 0x27370; // 24 * (3 * 4 bytes + 3 * 8 bytes) * 8 53 | 54 | var lookUp4D = 0x29230; // 2048 * 4 bytes 55 | var contributions4D = 0x429230; // 24 * (3 * 4 bytes + 3 * 8 bytes) * 8 56 | 57 | function normalize(n) { 58 | n = +n; 59 | return (n + 1.0) / 2.0; 60 | } 61 | 62 | function setSeed(value) { 63 | value = +value; 64 | var i = 0; 65 | var r = 0; 66 | var temp = 0; 67 | 68 | _setSeed(value); 69 | 70 | for (i = 0; (i | 0) < (pSize | 0); i = (i + 1) | 0) { 71 | heapU16[(perm + (i << 1)) >> 1] = i; 72 | } 73 | for (i = 0; (i | 0) < (pSize | 0); i = (i + 1) | 0) { 74 | r = (nextU32() | 0) & pMask; 75 | temp = getPerm(i) | 0; 76 | heapU16[(perm + (i << 1)) >> 1] = getPerm(r) | 0; 77 | heapU16[(perm + (r << 1)) >> 1] = temp; 78 | } 79 | } 80 | 81 | function getPerm(i) { 82 | i = i | 0; 83 | return heapU16[(perm + (i << 1)) >> 1] | 0; 84 | } 85 | 86 | function noise2D(octaves, lacunarity, persistence, xOffset, yOffset, x, y) { 87 | octaves = octaves | 0; 88 | lacunarity = +lacunarity; 89 | persistence = +persistence; 90 | xOffset = +xOffset; 91 | yOffset = +yOffset; 92 | x = +x; 93 | y = +y; 94 | var total = 0.0; 95 | var frequency = 1.0; 96 | var amplitude = 1.0; 97 | var max = 0.0; 98 | var i = 0; 99 | for (i = 0; (i | 0) < (octaves | 0); i = (i + 1) | 0) { 100 | total = total + +eval2D(x * frequency, y * frequency) * amplitude; 101 | max = max + amplitude; 102 | frequency = frequency * lacunarity; 103 | amplitude = amplitude * persistence; 104 | x = x + xOffset; 105 | y = y + yOffset; 106 | } 107 | return total / max; 108 | } 109 | 110 | function grad2D(xsb, ysb, dx, dy) { 111 | xsb = xsb | 0; 112 | ysb = ysb | 0; 113 | dx = +dx; 114 | dy = +dy; 115 | var i = 0; 116 | i = (getPerm(xsb & pMask) | 0) ^ (ysb & pMask); 117 | i = getPerm(i) | 0; 118 | return +heapF64[(gradients2D + (i << 4) + X) >> 3] * dx + +heapF64[(gradients2D + (i << 4) + Y) >> 3] * dy; 119 | } 120 | 121 | function eval2D(x, y) { 122 | x = +x; 123 | y = +y; 124 | var stretchOffset = 0.0; 125 | var xs = 0.0; 126 | var ys = 0.0; 127 | var xsb = 0; 128 | var ysb = 0; 129 | var xins = 0.0; 130 | var yins = 0.0; 131 | var inSum = 0.0; 132 | var squishOffsetIns = 0.0; 133 | var dx0 = 0.0; 134 | var dy0 = 0.0; 135 | var hash = 0; 136 | var offset = 0; 137 | var i = 0; 138 | var c = 0; 139 | var dx = 0.0; 140 | var dy = 0.0; 141 | var px = 0; 142 | var py = 0; 143 | var attn = 0.0; 144 | var value = 0.0; 145 | 146 | stretchOffset = (x + y) * heapF64[stretchConstant2D >> 3]; 147 | xs = x + stretchOffset; 148 | ys = y + stretchOffset; 149 | 150 | xsb = ~~floor(xs); 151 | ysb = ~~floor(ys); 152 | 153 | xins = xs - +(xsb | 0); 154 | yins = ys - +(ysb | 0); 155 | 156 | inSum = xins + yins; 157 | 158 | squishOffsetIns = inSum * heapF64[squishConstant2D >> 3]; 159 | dx0 = xins + squishOffsetIns; 160 | dy0 = yins + squishOffsetIns; 161 | 162 | // prettier-ignore 163 | hash = 164 | ~~floor(xins - yins + 1.0) | 165 | (~~floor(inSum) << 1) | 166 | (~~floor(inSum + yins) << 2) | 167 | (~~floor(inSum + xins) << 4); 168 | 169 | offset = imul(contribution2D, heapU32[(lookUp2D + (hash << 2)) >> 2] | 0) << 2; 170 | 171 | for (i = 0; (i | 0) < 4; i = (i + 1) | 0) { 172 | c = imul(contribution2D, i); 173 | dx = dx0 + +heapF64[(contributions2D + offset + c + X) >> 3]; 174 | dy = dy0 + +heapF64[(contributions2D + offset + c + Y) >> 3]; 175 | attn = 2.0 - dx * dx - dy * dy; 176 | if (attn > 0.0) { 177 | px = xsb + heapI32[(contributions2D + offset + c + 0x10 + XI) >> 2]; 178 | py = ysb + heapI32[(contributions2D + offset + c + 0x10 + YI) >> 2]; 179 | 180 | attn = attn * attn; 181 | value = value + attn * attn * +grad2D(px, py, dx, dy); 182 | } 183 | } 184 | return +normalize(value); 185 | } 186 | 187 | function noise3D(octaves, lacunarity, persistence, xOffset, yOffset, zOffset, x, y, z) { 188 | octaves = octaves | 0; 189 | lacunarity = +lacunarity; 190 | persistence = +persistence; 191 | xOffset = +xOffset; 192 | yOffset = +yOffset; 193 | zOffset = +zOffset; 194 | x = +x; 195 | y = +y; 196 | z = +z; 197 | var total = 0.0; 198 | var frequency = 1.0; 199 | var amplitude = 1.0; 200 | var max = 0.0; 201 | var i = 0; 202 | for (i = 0; (i | 0) < (octaves | 0); i = (i + 1) | 0) { 203 | total = total + +eval3D(x * frequency, y * frequency, z * frequency) * amplitude; 204 | max = max + amplitude; 205 | frequency = frequency * lacunarity; 206 | amplitude = amplitude * persistence; 207 | x = x + xOffset; 208 | y = y + yOffset; 209 | z = z + zOffset; 210 | } 211 | return total / max; 212 | } 213 | 214 | function eval3D(x, y, z) { 215 | x = +x; 216 | y = +y; 217 | z = +z; 218 | var stretchOffset = 0.0; 219 | var xs = 0.0; 220 | var ys = 0.0; 221 | var zs = 0.0; 222 | 223 | stretchOffset = (x + y + z) * heapF64[stretchConstant3D >> 3]; 224 | xs = x + stretchOffset; 225 | ys = y + stretchOffset; 226 | zs = z + stretchOffset; 227 | 228 | return +eval3DBase(xs, ys, zs); 229 | } 230 | 231 | // function eval3DXYBeforeZ(x, y, z) { 232 | // x = +x; 233 | // y = +y; 234 | // z = +z; 235 | // var xy = 0.0; 236 | // var s2 = 0.0; 237 | // var zz = 0.0; 238 | // var xs = 0.0; 239 | // var ys = 0.0; 240 | // var zs = 0.0; 241 | // xy = x + y; 242 | // s2 = xy * -heapF64[stretchConstant2D >> 3]; 243 | // zz = z * 0.288675134594813; 244 | // xs = s2 - x + zz; 245 | // ys = s2 - y + zz; 246 | // zs = xy * 0.577350269189626 + zz; 247 | 248 | // return +eval3DBase(xs, ys, zs); 249 | // } 250 | 251 | // function eval3DXZBeforeY(x, y, z) { 252 | // x = +x; 253 | // y = +y; 254 | // z = +z; 255 | // var xz = 0.0; 256 | // var s2 = 0.0; 257 | // var yy = 0.0; 258 | // var xs = 0.0; 259 | // var ys = 0.0; 260 | // var zs = 0.0; 261 | // xz = x + z; 262 | // s2 = xz * -heapF64[stretchConstant2D >> 3]; 263 | // yy = y * 0.288675134594813; 264 | // xs = s2 - x + yy; 265 | // ys = xz * 0.577350269189626 + yy; 266 | // zs = s2 - z + yy; 267 | 268 | // return +eval3DBase(xs, ys, zs); 269 | // } 270 | 271 | function grad3D(xsb, ysb, zsb, dx, dy, dz) { 272 | xsb = xsb | 0; 273 | ysb = ysb | 0; 274 | zsb = zsb | 0; 275 | dx = +dx; 276 | dy = +dy; 277 | dz = +dz; 278 | var i = 0; 279 | i = (getPerm(xsb & pMask) | 0) ^ (ysb & pMask); 280 | i = (getPerm(i) | 0) ^ (zsb & pMask); 281 | i = getPerm(i) | 0; 282 | i = imul(i, 3); 283 | return ( 284 | +heapF64[(gradients3D + (i << 3) + X) >> 3] * dx + 285 | +heapF64[(gradients3D + (i << 3) + Y) >> 3] * dy + 286 | +heapF64[(gradients3D + (i << 3) + Z) >> 3] * dz 287 | ); 288 | } 289 | 290 | function eval3DBase(xs, ys, zs) { 291 | xs = +xs; 292 | ys = +ys; 293 | zs = +zs; 294 | var xsb = 0; 295 | var ysb = 0; 296 | var zsb = 0; 297 | var xins = 0.0; 298 | var yins = 0.0; 299 | var zins = 0.0; 300 | var inSum = 0.0; 301 | var squishOffsetIns = 0.0; 302 | var dx0 = 0.0; 303 | var dy0 = 0.0; 304 | var dz0 = 0.0; 305 | var hash = 0; 306 | var offset = 0; 307 | var length = 0; 308 | var i = 0; 309 | var c = 0; 310 | var dx = 0.0; 311 | var dy = 0.0; 312 | var dz = 0.0; 313 | var px = 0; 314 | var py = 0; 315 | var pz = 0; 316 | var attn = 0.0; 317 | var value = 0.0; 318 | 319 | xsb = ~~floor(xs); 320 | ysb = ~~floor(ys); 321 | zsb = ~~floor(zs); 322 | 323 | xins = xs - +(xsb | 0); 324 | yins = ys - +(ysb | 0); 325 | zins = zs - +(zsb | 0); 326 | 327 | inSum = xins + yins + zins; 328 | 329 | squishOffsetIns = inSum * heapF64[squishConstant3D >> 3]; 330 | dx0 = xins + squishOffsetIns; 331 | dy0 = yins + squishOffsetIns; 332 | dz0 = zins + squishOffsetIns; 333 | 334 | hash = 335 | ~~floor(yins - zins + 1.0) | 336 | (~~floor(xins - yins + 1.0) << 1) | 337 | (~~floor(xins - zins + 1.0) << 2) | 338 | (~~floor(inSum) << 3) | 339 | (~~floor(inSum + zins) << 5) | 340 | (~~floor(inSum + yins) << 7) | 341 | (~~floor(inSum + xins) << 9); 342 | 343 | offset = imul((1 + contribution3D) | 0, heapU32[(lookUp3D + (hash << 2)) >> 2] | 0) << 3; 344 | length = heapU32[(contributions3D + offset) >> 2] | 0; 345 | offset = (offset + 0x8) | 0; 346 | 347 | for (i = 0; (i | 0) < (length | 0); i = (i + 1) | 0) { 348 | c = imul(contribution3D, i); 349 | dx = dx0 + +heapF64[(contributions3D + offset + c + X) >> 3]; 350 | dy = dy0 + +heapF64[(contributions3D + offset + c + Y) >> 3]; 351 | dz = dz0 + +heapF64[(contributions3D + offset + c + Z) >> 3]; 352 | attn = 2.0 - dx * dx - dy * dy - dz * dz; 353 | if (attn > 0.0) { 354 | px = xsb + heapI32[(contributions3D + offset + c + 0x18 + XI) >> 2]; 355 | py = ysb + heapI32[(contributions3D + offset + c + 0x18 + YI) >> 2]; 356 | pz = zsb + heapI32[(contributions3D + offset + c + 0x18 + ZI) >> 2]; 357 | 358 | attn = attn * attn; 359 | value = value + attn * attn * +grad3D(px, py, pz, dx, dy, dz); 360 | } 361 | } 362 | return +normalize(value); 363 | } 364 | 365 | function noise4D(octaves, lacunarity, persistence, xOffset, yOffset, zOffset, wOffset, x, y, z, w) { 366 | octaves = octaves | 0; 367 | lacunarity = +lacunarity; 368 | persistence = +persistence; 369 | xOffset = +xOffset; 370 | yOffset = +yOffset; 371 | zOffset = +zOffset; 372 | wOffset = +wOffset; 373 | x = +x; 374 | y = +y; 375 | z = +z; 376 | w = +w; 377 | var total = 0.0; 378 | var frequency = 1.0; 379 | var amplitude = 1.0; 380 | var max = 0.0; 381 | var i = 0; 382 | for (i = 0; (i | 0) < (octaves | 0); i = (i + 1) | 0) { 383 | total = total + +eval4D(x * frequency, y * frequency, z * frequency, w * frequency) * amplitude; 384 | max = max + amplitude; 385 | frequency = frequency * lacunarity; 386 | amplitude = amplitude * persistence; 387 | x = x + xOffset; 388 | y = y + yOffset; 389 | z = z + zOffset; 390 | w = w + wOffset; 391 | } 392 | return total / max; 393 | } 394 | 395 | function eval4D(x, y, z, w) { 396 | x = +x; 397 | y = +y; 398 | z = +z; 399 | w = +w; 400 | var stretchOffset = 0.0; 401 | var xs = 0.0; 402 | var ys = 0.0; 403 | var zs = 0.0; 404 | var ws = 0.0; 405 | 406 | stretchOffset = (x + y + z + w) * heapF64[stretchConstant4D >> 3]; 407 | xs = x + stretchOffset; 408 | ys = y + stretchOffset; 409 | zs = z + stretchOffset; 410 | ws = w + stretchOffset; 411 | 412 | return +eval4DBase(xs, ys, zs, ws); 413 | } 414 | 415 | // function eval4DXYBeforeZW(x, y, z, w) { 416 | // x = +x; 417 | // y = +y; 418 | // z = +z; 419 | // w = +w; 420 | // var s2 = 0.0; 421 | // var t2 = 0.0; 422 | // var xs = 0.0; 423 | // var ys = 0.0; 424 | // var zs = 0.0; 425 | // var ws = 0.0; 426 | 427 | // s2 = (x + y) * -0.178275657951399372 + (z + w) * 0.215623393288842828; 428 | // t2 = (z + w) * -0.403949762580207112 + (x + y) * -0.375199083010075342; 429 | // xs = x + s2; 430 | // ys = y + s2; 431 | // zs = z + t2; 432 | // ws = w + t2; 433 | 434 | // return +eval4DBase(xs, ys, zs, ws); 435 | // } 436 | 437 | // function eval4DXZBeforeYW(x, y, z, w) { 438 | // x = +x; 439 | // y = +y; 440 | // z = +z; 441 | // w = +w; 442 | // var s2 = 0.0; 443 | // var t2 = 0.0; 444 | // var xs = 0.0; 445 | // var ys = 0.0; 446 | // var zs = 0.0; 447 | // var ws = 0.0; 448 | 449 | // s2 = (x + z) * -0.178275657951399372 + (y + w) * 0.215623393288842828; 450 | // t2 = (y + w) * -0.403949762580207112 + (x + z) * -0.375199083010075342; 451 | // xs = x + s2; 452 | // ys = y + t2; 453 | // zs = z + s2; 454 | // ws = w + t2; 455 | 456 | // return +eval4DBase(xs, ys, zs, ws); 457 | // } 458 | 459 | // function eval4DXYZBeforeW(x, y, z, w) { 460 | // x = +x; 461 | // y = +y; 462 | // z = +z; 463 | // w = +w; 464 | // var xyz = 0.0; 465 | // var ww = 0.0; 466 | // var s2 = 0.0; 467 | // var xs = 0.0; 468 | // var ys = 0.0; 469 | // var zs = 0.0; 470 | // var ws = 0.0; 471 | 472 | // xyz = x + y + z; 473 | // ww = w * 0.2236067977499788; 474 | // s2 = xyz * heapF64[stretchConstant3D >> 3] + ww; 475 | // xs = x + s2; 476 | // ys = y + s2; 477 | // zs = z + s2; 478 | // ws = -0.5 * xyz + ww; 479 | 480 | // return +eval4DBase(xs, ys, zs, ws); 481 | // } 482 | 483 | function grad4D(xsb, ysb, zsb, wsb, dx, dy, dz, dw) { 484 | xsb = xsb | 0; 485 | ysb = ysb | 0; 486 | zsb = zsb | 0; 487 | wsb = wsb | 0; 488 | dx = +dx; 489 | dy = +dy; 490 | dz = +dz; 491 | dw = +dw; 492 | var i = 0; 493 | i = (getPerm(xsb & pMask) | 0) ^ (ysb & pMask); 494 | i = (getPerm(i) | 0) ^ (zsb & pMask); 495 | i = (getPerm(i) | 0) ^ (wsb & pMask); 496 | i = getPerm(i) | 0; 497 | return ( 498 | +heapF64[(gradients4D + (i << 5) + X) >> 3] * dx + 499 | +heapF64[(gradients4D + (i << 5) + Y) >> 3] * dy + 500 | +heapF64[(gradients4D + (i << 5) + Z) >> 3] * dz + 501 | +heapF64[(gradients4D + (i << 5) + W) >> 3] * dw 502 | ); 503 | } 504 | 505 | function eval4DBase(xs, ys, zs, ws) { 506 | xs = +xs; 507 | ys = +ys; 508 | zs = +zs; 509 | ws = +ws; 510 | var xsb = 0; 511 | var ysb = 0; 512 | var zsb = 0; 513 | var wsb = 0; 514 | var xins = 0.0; 515 | var yins = 0.0; 516 | var zins = 0.0; 517 | var wins = 0.0; 518 | var inSum = 0.0; 519 | var squishOffsetIns = 0.0; 520 | var dx0 = 0.0; 521 | var dy0 = 0.0; 522 | var dz0 = 0.0; 523 | var dw0 = 0.0; 524 | var hash = 0; 525 | var offset = 0; 526 | var length = 0; 527 | var i = 0; 528 | var c = 0; 529 | var dx = 0.0; 530 | var dy = 0.0; 531 | var dz = 0.0; 532 | var dw = 0.0; 533 | var px = 0; 534 | var py = 0; 535 | var pz = 0; 536 | var pw = 0; 537 | var attn = 0.0; 538 | var value = 0.0; 539 | 540 | xsb = ~~floor(xs); 541 | ysb = ~~floor(ys); 542 | zsb = ~~floor(zs); 543 | wsb = ~~floor(ws); 544 | 545 | xins = xs - +(xsb | 0); 546 | yins = ys - +(ysb | 0); 547 | zins = zs - +(zsb | 0); 548 | wins = ws - +(wsb | 0); 549 | 550 | inSum = xins + yins + zins + wins; 551 | 552 | squishOffsetIns = inSum * heapF64[squishConstant4D >> 3]; 553 | dx0 = xins + squishOffsetIns; 554 | dy0 = yins + squishOffsetIns; 555 | dz0 = zins + squishOffsetIns; 556 | dw0 = wins + squishOffsetIns; 557 | 558 | hash = 559 | ~~floor(zins - wins + 1.0) | 560 | (~~floor(yins - zins + 1.0) << 1) | 561 | (~~floor(yins - wins + 1.0) << 2) | 562 | (~~floor(xins - yins + 1.0) << 3) | 563 | (~~floor(xins - zins + 1.0) << 4) | 564 | (~~floor(xins - wins + 1.0) << 5) | 565 | (~~floor(inSum) << 6) | 566 | (~~floor(inSum + wins) << 8) | 567 | (~~floor(inSum + zins) << 11) | 568 | (~~floor(inSum + yins) << 14) | 569 | (~~floor(inSum + xins) << 17); 570 | 571 | offset = imul((1 + (contribution4D << 1)) | 0, heapU32[(lookUp4D + (hash << 2)) >> 2] | 0) << 3; 572 | length = heapU32[(contributions4D + offset) >> 2] | 0; 573 | offset = (offset + 0x8) | 0; 574 | 575 | for (i = 0; (i | 0) < (length | 0); i = (i + 1) | 0) { 576 | c = imul(contribution4D, i); 577 | dx = dx0 + +heapF64[(contributions4D + offset + c + X) >> 3]; 578 | dy = dy0 + +heapF64[(contributions4D + offset + c + Y) >> 3]; 579 | dz = dz0 + +heapF64[(contributions4D + offset + c + Z) >> 3]; 580 | dw = dw0 + +heapF64[(contributions4D + offset + c + W) >> 3]; 581 | attn = 2.0 - dx * dx - dy * dy - dz * dz - dw * dw; 582 | if (attn > 0.0) { 583 | px = xsb + heapI32[(contributions4D + offset + c + 0x20 + XI) >> 2]; 584 | py = ysb + heapI32[(contributions4D + offset + c + 0x20 + YI) >> 2]; 585 | pz = zsb + heapI32[(contributions4D + offset + c + 0x20 + ZI) >> 2]; 586 | pw = wsb + heapI32[(contributions4D + offset + c + 0x20 + WI) >> 2]; 587 | 588 | attn = attn * attn; 589 | value = value + attn * attn * +grad4D(px, py, pz, pw, dx, dy, dz, dw); 590 | } 591 | } 592 | return +normalize(value); 593 | } 594 | 595 | return { 596 | setSeed: setSeed, 597 | noise2D: noise2D, 598 | noise3D: noise3D, 599 | noise4D: noise4D, 600 | }; 601 | } 602 | 603 | const heap = new ArrayBuffer(0x1000000); 604 | 605 | // set constants 606 | { 607 | const heapF64 = new Float64Array(heap, 0x800 * 2); 608 | heapF64[0 + 0] = (1 / Math.sqrt(2 + 1) - 1) / 2; // stretch constant 2d 609 | heapF64[3 + 0] = (Math.sqrt(2 + 1) - 1) / 2; // squish constant 2d 610 | heapF64[0 + 1] = (1 / Math.sqrt(3 + 1) - 1) / 3; // stretch constant 3d 611 | heapF64[3 + 1] = (Math.sqrt(3 + 1) - 1) / 3; // squish constant 3d 612 | heapF64[0 + 2] = (1 / Math.sqrt(4 + 1) - 1) / 4; // stretch constant 4d 613 | heapF64[3 + 2] = (Math.sqrt(4 + 1) - 1) / 4; // squish constant 4d 614 | } 615 | 616 | // create gradients 617 | { 618 | const heapF64 = new Float64Array(heap, 0x800 * 2 + 6 * 0x8); 619 | 620 | let offset = 0; 621 | { 622 | // prettier-ignore 623 | const gradients2D = [ 624 | 0.130526192220052, 0.99144486137381, 625 | 0.38268343236509, 0.923879532511287, 626 | 0.608761429008721, 0.793353340291235, 627 | 0.793353340291235, 0.608761429008721, 628 | 0.923879532511287, 0.38268343236509, 629 | 0.99144486137381, 0.130526192220051, 630 | 0.99144486137381, -0.130526192220051, 631 | 0.923879532511287, -0.38268343236509, 632 | 0.793353340291235, -0.60876142900872, 633 | 0.608761429008721, -0.793353340291235, 634 | 0.38268343236509, -0.923879532511287, 635 | 0.130526192220052, -0.99144486137381, 636 | -0.130526192220052, -0.99144486137381, 637 | -0.38268343236509, -0.923879532511287, 638 | -0.608761429008721, -0.793353340291235, 639 | -0.793353340291235, -0.608761429008721, 640 | -0.923879532511287, -0.38268343236509, 641 | -0.99144486137381, -0.130526192220052, 642 | -0.99144486137381, 0.130526192220051, 643 | -0.923879532511287, 0.38268343236509, 644 | -0.793353340291235, 0.608761429008721, 645 | -0.608761429008721, 0.793353340291235, 646 | -0.38268343236509, 0.923879532511287, 647 | -0.130526192220052, 0.99144486137381, 648 | ].map((n) => n / 7.69084574549313); 649 | 650 | for (let i = 0; i < 2 * 0x800; i++) { 651 | heapF64[offset + i] = gradients2D[i % gradients2D.length]; 652 | } 653 | offset += 2 * 0x800; 654 | } 655 | 656 | { 657 | // prettier-ignore 658 | const gradients3D = [ 659 | -1.4082482904633333, -1.4082482904633333, -2.6329931618533333, 660 | -0.07491495712999985, -0.07491495712999985, -3.29965982852, 661 | 0.24732126143473554, -1.6667938651159684, -2.838945207362466, 662 | -1.6667938651159684, 0.24732126143473554, -2.838945207362466, 663 | -1.4082482904633333, -2.6329931618533333, -1.4082482904633333, 664 | -0.07491495712999985, -3.29965982852, -0.07491495712999985, 665 | -1.6667938651159684, -2.838945207362466, 0.24732126143473554, 666 | 0.24732126143473554, -2.838945207362466, -1.6667938651159684, 667 | 1.5580782047233335, 0.33333333333333337, -2.8914115380566665, 668 | 2.8914115380566665, -0.33333333333333337, -1.5580782047233335, 669 | 1.8101897177633992, -1.2760767510338025, -2.4482280932803, 670 | 2.4482280932803, 1.2760767510338025, -1.8101897177633992, 671 | 1.5580782047233335, -2.8914115380566665, 0.33333333333333337, 672 | 2.8914115380566665, -1.5580782047233335, -0.33333333333333337, 673 | 2.4482280932803, -1.8101897177633992, 1.2760767510338025, 674 | 1.8101897177633992, -2.4482280932803, -1.2760767510338025, 675 | -2.6329931618533333, -1.4082482904633333, -1.4082482904633333, 676 | -3.29965982852, -0.07491495712999985, -0.07491495712999985, 677 | -2.838945207362466, 0.24732126143473554, -1.6667938651159684, 678 | -2.838945207362466, -1.6667938651159684, 0.24732126143473554, 679 | 0.33333333333333337, 1.5580782047233335, -2.8914115380566665, 680 | -0.33333333333333337, 2.8914115380566665, -1.5580782047233335, 681 | 1.2760767510338025, 2.4482280932803, -1.8101897177633992, 682 | -1.2760767510338025, 1.8101897177633992, -2.4482280932803, 683 | 0.33333333333333337, -2.8914115380566665, 1.5580782047233335, 684 | -0.33333333333333337, -1.5580782047233335, 2.8914115380566665, 685 | -1.2760767510338025, -2.4482280932803, 1.8101897177633992, 686 | 1.2760767510338025, -1.8101897177633992, 2.4482280932803, 687 | 3.29965982852, 0.07491495712999985, 0.07491495712999985, 688 | 2.6329931618533333, 1.4082482904633333, 1.4082482904633333, 689 | 2.838945207362466, -0.24732126143473554, 1.6667938651159684, 690 | 2.838945207362466, 1.6667938651159684, -0.24732126143473554, 691 | -2.8914115380566665, 1.5580782047233335, 0.33333333333333337, 692 | -1.5580782047233335, 2.8914115380566665, -0.33333333333333337, 693 | -2.4482280932803, 1.8101897177633992, -1.2760767510338025, 694 | -1.8101897177633992, 2.4482280932803, 1.2760767510338025, 695 | -2.8914115380566665, 0.33333333333333337, 1.5580782047233335, 696 | -1.5580782047233335, -0.33333333333333337, 2.8914115380566665, 697 | -1.8101897177633992, 1.2760767510338025, 2.4482280932803, 698 | -2.4482280932803, -1.2760767510338025, 1.8101897177633992, 699 | 0.07491495712999985, 3.29965982852, 0.07491495712999985, 700 | 1.4082482904633333, 2.6329931618533333, 1.4082482904633333, 701 | 1.6667938651159684, 2.838945207362466, -0.24732126143473554, 702 | -0.24732126143473554, 2.838945207362466, 1.6667938651159684, 703 | 0.07491495712999985, 0.07491495712999985, 3.29965982852, 704 | 1.4082482904633333, 1.4082482904633333, 2.6329931618533333, 705 | -0.24732126143473554, 1.6667938651159684, 2.838945207362466, 706 | 1.6667938651159684, -0.24732126143473554, 2.838945207362466, 707 | ].map((n) => n / 26.92263139946168); 708 | 709 | for (let i = 0; i < 3 * 0x800; i++) { 710 | heapF64[offset + i] = gradients3D[i % gradients3D.length]; 711 | } 712 | offset += 3 * 0x800; 713 | } 714 | 715 | { 716 | // prettier-ignore 717 | const gradients4D = [ 718 | -0.753341017856078, -0.37968289875261624, -0.37968289875261624, -0.37968289875261624, 719 | -0.7821684431180708, -0.4321472685365301, -0.4321472685365301, 0.12128480194602098, 720 | -0.7821684431180708, -0.4321472685365301, 0.12128480194602098, -0.4321472685365301, 721 | -0.7821684431180708, 0.12128480194602098, -0.4321472685365301, -0.4321472685365301, 722 | -0.8586508742123365, -0.508629699630796, 0.044802370851755174, 0.044802370851755174, 723 | -0.8586508742123365, 0.044802370851755174, -0.508629699630796, 0.044802370851755174, 724 | -0.8586508742123365, 0.044802370851755174, 0.044802370851755174, -0.508629699630796, 725 | -0.9982828964265062, -0.03381941603233842, -0.03381941603233842, -0.03381941603233842, 726 | -0.37968289875261624, -0.753341017856078, -0.37968289875261624, -0.37968289875261624, 727 | -0.4321472685365301, -0.7821684431180708, -0.4321472685365301, 0.12128480194602098, 728 | -0.4321472685365301, -0.7821684431180708, 0.12128480194602098, -0.4321472685365301, 729 | 0.12128480194602098, -0.7821684431180708, -0.4321472685365301, -0.4321472685365301, 730 | -0.508629699630796, -0.8586508742123365, 0.044802370851755174, 0.044802370851755174, 731 | 0.044802370851755174, -0.8586508742123365, -0.508629699630796, 0.044802370851755174, 732 | 0.044802370851755174, -0.8586508742123365, 0.044802370851755174, -0.508629699630796, 733 | -0.03381941603233842, -0.9982828964265062, -0.03381941603233842, -0.03381941603233842, 734 | -0.37968289875261624, -0.37968289875261624, -0.753341017856078, -0.37968289875261624, 735 | -0.4321472685365301, -0.4321472685365301, -0.7821684431180708, 0.12128480194602098, 736 | -0.4321472685365301, 0.12128480194602098, -0.7821684431180708, -0.4321472685365301, 737 | 0.12128480194602098, -0.4321472685365301, -0.7821684431180708, -0.4321472685365301, 738 | -0.508629699630796, 0.044802370851755174, -0.8586508742123365, 0.044802370851755174, 739 | 0.044802370851755174, -0.508629699630796, -0.8586508742123365, 0.044802370851755174, 740 | 0.044802370851755174, 0.044802370851755174, -0.8586508742123365, -0.508629699630796, 741 | -0.03381941603233842, -0.03381941603233842, -0.9982828964265062, -0.03381941603233842, 742 | -0.37968289875261624, -0.37968289875261624, -0.37968289875261624, -0.753341017856078, 743 | -0.4321472685365301, -0.4321472685365301, 0.12128480194602098, -0.7821684431180708, 744 | -0.4321472685365301, 0.12128480194602098, -0.4321472685365301, -0.7821684431180708, 745 | 0.12128480194602098, -0.4321472685365301, -0.4321472685365301, -0.7821684431180708, 746 | -0.508629699630796, 0.044802370851755174, 0.044802370851755174, -0.8586508742123365, 747 | 0.044802370851755174, -0.508629699630796, 0.044802370851755174, -0.8586508742123365, 748 | 0.044802370851755174, 0.044802370851755174, -0.508629699630796, -0.8586508742123365, 749 | -0.03381941603233842, -0.03381941603233842, -0.03381941603233842, -0.9982828964265062, 750 | -0.6740059517812944, -0.3239847771997537, -0.3239847771997537, 0.5794684678643381, 751 | -0.7504883828755602, -0.4004672082940195, 0.15296486218853164, 0.5029860367700724, 752 | -0.7504883828755602, 0.15296486218853164, -0.4004672082940195, 0.5029860367700724, 753 | -0.8828161875373585, 0.08164729285680945, 0.08164729285680945, 0.4553054119602712, 754 | -0.4553054119602712, -0.08164729285680945, -0.08164729285680945, 0.8828161875373585, 755 | -0.5029860367700724, -0.15296486218853164, 0.4004672082940195, 0.7504883828755602, 756 | -0.5029860367700724, 0.4004672082940195, -0.15296486218853164, 0.7504883828755602, 757 | -0.5794684678643381, 0.3239847771997537, 0.3239847771997537, 0.6740059517812944, 758 | -0.3239847771997537, -0.6740059517812944, -0.3239847771997537, 0.5794684678643381, 759 | -0.4004672082940195, -0.7504883828755602, 0.15296486218853164, 0.5029860367700724, 760 | 0.15296486218853164, -0.7504883828755602, -0.4004672082940195, 0.5029860367700724, 761 | 0.08164729285680945, -0.8828161875373585, 0.08164729285680945, 0.4553054119602712, 762 | -0.08164729285680945, -0.4553054119602712, -0.08164729285680945, 0.8828161875373585, 763 | -0.15296486218853164, -0.5029860367700724, 0.4004672082940195, 0.7504883828755602, 764 | 0.4004672082940195, -0.5029860367700724, -0.15296486218853164, 0.7504883828755602, 765 | 0.3239847771997537, -0.5794684678643381, 0.3239847771997537, 0.6740059517812944, 766 | -0.3239847771997537, -0.3239847771997537, -0.6740059517812944, 0.5794684678643381, 767 | -0.4004672082940195, 0.15296486218853164, -0.7504883828755602, 0.5029860367700724, 768 | 0.15296486218853164, -0.4004672082940195, -0.7504883828755602, 0.5029860367700724, 769 | 0.08164729285680945, 0.08164729285680945, -0.8828161875373585, 0.4553054119602712, 770 | -0.08164729285680945, -0.08164729285680945, -0.4553054119602712, 0.8828161875373585, 771 | -0.15296486218853164, 0.4004672082940195, -0.5029860367700724, 0.7504883828755602, 772 | 0.4004672082940195, -0.15296486218853164, -0.5029860367700724, 0.7504883828755602, 773 | 0.3239847771997537, 0.3239847771997537, -0.5794684678643381, 0.6740059517812944, 774 | -0.6740059517812944, -0.3239847771997537, 0.5794684678643381, -0.3239847771997537, 775 | -0.7504883828755602, -0.4004672082940195, 0.5029860367700724, 0.15296486218853164, 776 | -0.7504883828755602, 0.15296486218853164, 0.5029860367700724, -0.4004672082940195, 777 | -0.8828161875373585, 0.08164729285680945, 0.4553054119602712, 0.08164729285680945, 778 | -0.4553054119602712, -0.08164729285680945, 0.8828161875373585, -0.08164729285680945, 779 | -0.5029860367700724, -0.15296486218853164, 0.7504883828755602, 0.4004672082940195, 780 | -0.5029860367700724, 0.4004672082940195, 0.7504883828755602, -0.15296486218853164, 781 | -0.5794684678643381, 0.3239847771997537, 0.6740059517812944, 0.3239847771997537, 782 | -0.3239847771997537, -0.6740059517812944, 0.5794684678643381, -0.3239847771997537, 783 | -0.4004672082940195, -0.7504883828755602, 0.5029860367700724, 0.15296486218853164, 784 | 0.15296486218853164, -0.7504883828755602, 0.5029860367700724, -0.4004672082940195, 785 | 0.08164729285680945, -0.8828161875373585, 0.4553054119602712, 0.08164729285680945, 786 | -0.08164729285680945, -0.4553054119602712, 0.8828161875373585, -0.08164729285680945, 787 | -0.15296486218853164, -0.5029860367700724, 0.7504883828755602, 0.4004672082940195, 788 | 0.4004672082940195, -0.5029860367700724, 0.7504883828755602, -0.15296486218853164, 789 | 0.3239847771997537, -0.5794684678643381, 0.6740059517812944, 0.3239847771997537, 790 | -0.3239847771997537, -0.3239847771997537, 0.5794684678643381, -0.6740059517812944, 791 | -0.4004672082940195, 0.15296486218853164, 0.5029860367700724, -0.7504883828755602, 792 | 0.15296486218853164, -0.4004672082940195, 0.5029860367700724, -0.7504883828755602, 793 | 0.08164729285680945, 0.08164729285680945, 0.4553054119602712, -0.8828161875373585, 794 | -0.08164729285680945, -0.08164729285680945, 0.8828161875373585, -0.4553054119602712, 795 | -0.15296486218853164, 0.4004672082940195, 0.7504883828755602, -0.5029860367700724, 796 | 0.4004672082940195, -0.15296486218853164, 0.7504883828755602, -0.5029860367700724, 797 | 0.3239847771997537, 0.3239847771997537, 0.6740059517812944, -0.5794684678643381, 798 | -0.6740059517812944, 0.5794684678643381, -0.3239847771997537, -0.3239847771997537, 799 | -0.7504883828755602, 0.5029860367700724, -0.4004672082940195, 0.15296486218853164, 800 | -0.7504883828755602, 0.5029860367700724, 0.15296486218853164, -0.4004672082940195, 801 | -0.8828161875373585, 0.4553054119602712, 0.08164729285680945, 0.08164729285680945, 802 | -0.4553054119602712, 0.8828161875373585, -0.08164729285680945, -0.08164729285680945, 803 | -0.5029860367700724, 0.7504883828755602, -0.15296486218853164, 0.4004672082940195, 804 | -0.5029860367700724, 0.7504883828755602, 0.4004672082940195, -0.15296486218853164, 805 | -0.5794684678643381, 0.6740059517812944, 0.3239847771997537, 0.3239847771997537, 806 | -0.3239847771997537, 0.5794684678643381, -0.6740059517812944, -0.3239847771997537, 807 | -0.4004672082940195, 0.5029860367700724, -0.7504883828755602, 0.15296486218853164, 808 | 0.15296486218853164, 0.5029860367700724, -0.7504883828755602, -0.4004672082940195, 809 | 0.08164729285680945, 0.4553054119602712, -0.8828161875373585, 0.08164729285680945, 810 | -0.08164729285680945, 0.8828161875373585, -0.4553054119602712, -0.08164729285680945, 811 | -0.15296486218853164, 0.7504883828755602, -0.5029860367700724, 0.4004672082940195, 812 | 0.4004672082940195, 0.7504883828755602, -0.5029860367700724, -0.15296486218853164, 813 | 0.3239847771997537, 0.6740059517812944, -0.5794684678643381, 0.3239847771997537, 814 | -0.3239847771997537, 0.5794684678643381, -0.3239847771997537, -0.6740059517812944, 815 | -0.4004672082940195, 0.5029860367700724, 0.15296486218853164, -0.7504883828755602, 816 | 0.15296486218853164, 0.5029860367700724, -0.4004672082940195, -0.7504883828755602, 817 | 0.08164729285680945, 0.4553054119602712, 0.08164729285680945, -0.8828161875373585, 818 | -0.08164729285680945, 0.8828161875373585, -0.08164729285680945, -0.4553054119602712, 819 | -0.15296486218853164, 0.7504883828755602, 0.4004672082940195, -0.5029860367700724, 820 | 0.4004672082940195, 0.7504883828755602, -0.15296486218853164, -0.5029860367700724, 821 | 0.3239847771997537, 0.6740059517812944, 0.3239847771997537, -0.5794684678643381, 822 | 0.5794684678643381, -0.6740059517812944, -0.3239847771997537, -0.3239847771997537, 823 | 0.5029860367700724, -0.7504883828755602, -0.4004672082940195, 0.15296486218853164, 824 | 0.5029860367700724, -0.7504883828755602, 0.15296486218853164, -0.4004672082940195, 825 | 0.4553054119602712, -0.8828161875373585, 0.08164729285680945, 0.08164729285680945, 826 | 0.8828161875373585, -0.4553054119602712, -0.08164729285680945, -0.08164729285680945, 827 | 0.7504883828755602, -0.5029860367700724, -0.15296486218853164, 0.4004672082940195, 828 | 0.7504883828755602, -0.5029860367700724, 0.4004672082940195, -0.15296486218853164, 829 | 0.6740059517812944, -0.5794684678643381, 0.3239847771997537, 0.3239847771997537, 830 | 0.5794684678643381, -0.3239847771997537, -0.6740059517812944, -0.3239847771997537, 831 | 0.5029860367700724, -0.4004672082940195, -0.7504883828755602, 0.15296486218853164, 832 | 0.5029860367700724, 0.15296486218853164, -0.7504883828755602, -0.4004672082940195, 833 | 0.4553054119602712, 0.08164729285680945, -0.8828161875373585, 0.08164729285680945, 834 | 0.8828161875373585, -0.08164729285680945, -0.4553054119602712, -0.08164729285680945, 835 | 0.7504883828755602, -0.15296486218853164, -0.5029860367700724, 0.4004672082940195, 836 | 0.7504883828755602, 0.4004672082940195, -0.5029860367700724, -0.15296486218853164, 837 | 0.6740059517812944, 0.3239847771997537, -0.5794684678643381, 0.3239847771997537, 838 | 0.5794684678643381, -0.3239847771997537, -0.3239847771997537, -0.6740059517812944, 839 | 0.5029860367700724, -0.4004672082940195, 0.15296486218853164, -0.7504883828755602, 840 | 0.5029860367700724, 0.15296486218853164, -0.4004672082940195, -0.7504883828755602, 841 | 0.4553054119602712, 0.08164729285680945, 0.08164729285680945, -0.8828161875373585, 842 | 0.8828161875373585, -0.08164729285680945, -0.08164729285680945, -0.4553054119602712, 843 | 0.7504883828755602, -0.15296486218853164, 0.4004672082940195, -0.5029860367700724, 844 | 0.7504883828755602, 0.4004672082940195, -0.15296486218853164, -0.5029860367700724, 845 | 0.6740059517812944, 0.3239847771997537, 0.3239847771997537, -0.5794684678643381, 846 | 0.03381941603233842, 0.03381941603233842, 0.03381941603233842, 0.9982828964265062, 847 | -0.044802370851755174, -0.044802370851755174, 0.508629699630796, 0.8586508742123365, 848 | -0.044802370851755174, 0.508629699630796, -0.044802370851755174, 0.8586508742123365, 849 | -0.12128480194602098, 0.4321472685365301, 0.4321472685365301, 0.7821684431180708, 850 | 0.508629699630796, -0.044802370851755174, -0.044802370851755174, 0.8586508742123365, 851 | 0.4321472685365301, -0.12128480194602098, 0.4321472685365301, 0.7821684431180708, 852 | 0.4321472685365301, 0.4321472685365301, -0.12128480194602098, 0.7821684431180708, 853 | 0.37968289875261624, 0.37968289875261624, 0.37968289875261624, 0.753341017856078, 854 | 0.03381941603233842, 0.03381941603233842, 0.9982828964265062, 0.03381941603233842, 855 | -0.044802370851755174, 0.044802370851755174, 0.8586508742123365, 0.508629699630796, 856 | -0.044802370851755174, 0.508629699630796, 0.8586508742123365, -0.044802370851755174, 857 | -0.12128480194602098, 0.4321472685365301, 0.7821684431180708, 0.4321472685365301, 858 | 0.508629699630796, -0.044802370851755174, 0.8586508742123365, -0.044802370851755174, 859 | 0.4321472685365301, -0.12128480194602098, 0.7821684431180708, 0.4321472685365301, 860 | 0.4321472685365301, 0.4321472685365301, 0.7821684431180708, -0.12128480194602098, 861 | 0.37968289875261624, 0.37968289875261624, 0.753341017856078, 0.37968289875261624, 862 | 0.03381941603233842, 0.9982828964265062, 0.03381941603233842, 0.03381941603233842, 863 | -0.044802370851755174, 0.8586508742123365, -0.044802370851755174, 0.508629699630796, 864 | -0.044802370851755174, 0.8586508742123365, 0.508629699630796, -0.044802370851755174, 865 | -0.12128480194602098, 0.7821684431180708, 0.4321472685365301, 0.4321472685365301, 866 | 0.508629699630796, 0.8586508742123365, -0.044802370851755174, -0.044802370851755174, 867 | 0.4321472685365301, 0.7821684431180708, -0.12128480194602098, 0.4321472685365301, 868 | 0.4321472685365301, 0.7821684431180708, 0.4321472685365301, -0.12128480194602098, 869 | 0.37968289875261624, 0.753341017856078, 0.37968289875261624, 0.37968289875261624, 870 | 0.9982828964265062, 0.03381941603233842, 0.03381941603233842, 0.03381941603233842, 871 | 0.8586508742123365, -0.044802370851755174, -0.044802370851755174, 0.508629699630796, 872 | 0.8586508742123365, -0.044802370851755174, 0.508629699630796, -0.044802370851755174, 873 | 0.7821684431180708, -0.12128480194602098, 0.4321472685365301, 0.4321472685365301, 874 | 0.8586508742123365, 0.508629699630796, -0.044802370851755174, -0.044802370851755174, 875 | 0.7821684431180708, 0.4321472685365301, -0.12128480194602098, 0.4321472685365301, 876 | 0.7821684431180708, 0.4321472685365301, 0.4321472685365301, -0.12128480194602098, 877 | 0.753341017856078, 0.37968289875261624, 0.37968289875261624, 0.37968289875261624, 878 | ].map((n) => n / 8.881759591352166); 879 | 880 | for (let i = 0; i < 4 * 0x800; i++) { 881 | heapF64[offset + i] = gradients4D[i % gradients4D.length]; 882 | } 883 | } 884 | } 885 | 886 | // create look ups 887 | { 888 | const heapU32 = new Uint32Array(heap, 0x800 * 2 + (6 + (2 + 3 + 4) * 0x800) * 8); 889 | const heapI32 = new Int32Array(heap, 0x800 * 2 + (6 + (2 + 3 + 4) * 0x800) * 8); 890 | const heapF64 = new Float64Array(heap, 0x800 * 2 + (6 + (2 + 3 + 4) * 0x800) * 8); 891 | 892 | let offset = 0; 893 | { 894 | const lookupPairs2D = [0, 1, 1, 0, 4, 1, 17, 0, 20, 2, 21, 2, 22, 5, 23, 5, 26, 4, 39, 3, 42, 4, 43, 3]; 895 | for (let i = 0; i < lookupPairs2D.length; i += 2) { 896 | heapU32[offset + lookupPairs2D[i]] = lookupPairs2D[i + 1]; 897 | } 898 | offset += 64; 899 | 900 | const squish2D = (Math.sqrt(2 + 1) - 1) / 2; 901 | const setContribution2D = (multiplier, xsb, ysb) =>{ 902 | heapF64[(offset >> 1) + 0] = -xsb - multiplier * squish2D; 903 | heapF64[(offset >> 1) + 1] = -ysb - multiplier * squish2D; 904 | heapI32[offset + (2 << 1) + 0] = xsb; 905 | heapI32[offset + (2 << 1) + 1] = ysb; 906 | offset += 3 << 1; 907 | }; 908 | 909 | const base2D = [ 910 | [1, 1, 0, 1, 0, 1, 0, 0, 0], 911 | [1, 1, 0, 1, 0, 1, 2, 1, 1], 912 | ]; 913 | const p2D = [0, 0, 1, -1, 0, 0, -1, 1, 0, 2, 1, 1, 1, 2, 2, 0, 1, 2, 0, 2, 1, 0, 0, 0]; 914 | for (let i = 0; i < p2D.length; i += 4) { 915 | const baseSet = base2D[p2D[i]]; 916 | for (let k = 0; k < baseSet.length; k += 3) { 917 | setContribution2D(baseSet[k], baseSet[k + 1], baseSet[k + 2]); 918 | } 919 | setContribution2D(p2D[i + 1], p2D[i + 2], p2D[i + 3]); 920 | } 921 | } 922 | 923 | { 924 | // prettier-ignore 925 | const lookupPairs3D = [0, 2, 1, 1, 2, 2, 5, 1, 6, 0, 7, 0, 32, 2, 34, 2, 129, 1, 133, 1, 160, 5, 161, 5, 518, 0, 519, 0, 546, 4, 550, 4, 645, 3, 647, 3, 672, 5, 673, 5, 674, 4, 677, 3, 678, 4, 679, 3, 680, 13, 681, 13, 682, 12, 685, 14, 686, 12, 687, 14, 712, 20, 714, 18, 809, 21, 813, 23, 840, 20, 841, 21, 1198, 19, 1199, 22, 1226, 18, 1230, 19, 1325, 23, 1327, 22, 1352, 15, 1353, 17, 1354, 15, 1357, 17, 1358, 16, 1359, 16, 1360, 11, 1361, 10, 1362, 11, 1365, 10, 1366, 9, 1367, 9, 1392, 11, 1394, 11, 1489, 10, 1493, 10, 1520, 8, 1521, 8, 1878, 9, 1879, 9, 1906, 7, 1910, 7, 2005, 6, 2007, 6, 2032, 8, 2033, 8, 2034, 7, 2037, 6, 2038, 7, 2039, 6]; 926 | for (let i = 0; i < lookupPairs3D.length; i += 2) { 927 | heapU32[offset + lookupPairs3D[i]] = lookupPairs3D[i + 1]; 928 | } 929 | 930 | offset += 2048; 931 | 932 | const base3D = [ 933 | [0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1], 934 | [2, 1, 1, 0, 2, 1, 0, 1, 2, 0, 1, 1, 3, 1, 1, 1], 935 | [1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 2, 1, 1, 0, 2, 1, 0, 1, 2, 0, 1, 1], 936 | ]; 937 | // prettier-ignore 938 | const p3D = [0, 0, 1, -1, 0, 0, 1, 0, -1, 0, 0, -1, 1, 0, 0, 0, 1, -1, 0, 0, -1, 0, 1, 0, 0, -1, 1, 0, 2, 1, 1, 0, 1, 1, 1, -1, 0, 2, 1, 0, 1, 1, 1, -1, 1, 0, 2, 0, 1, 1, 1, -1, 1, 1, 1, 3, 2, 1, 0, 3, 1, 2, 0, 1, 3, 2, 0, 1, 3, 1, 0, 2, 1, 3, 0, 2, 1, 3, 0, 1, 2, 1, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1, 0, 1, 0, 2, 0, 2, 0, 1, 1, 0, 0, 1, 2, 0, 0, 2, 2, 0, 0, 0, 0, 1, 1, -1, 1, 2, 0, 0, 0, 0, 1, -1, 1, 1, 2, 0, 0, 0, 0, 1, 1, 1, -1, 2, 3, 1, 1, 1, 2, 0, 0, 2, 2, 3, 1, 1, 1, 2, 2, 0, 0, 2, 3, 1, 1, 1, 2, 0, 2, 0, 2, 1, 1, -1, 1, 2, 0, 0, 2, 2, 1, 1, -1, 1, 2, 2, 0, 0, 2, 1, -1, 1, 1, 2, 0, 0, 2, 2, 1, -1, 1, 1, 2, 0, 2, 0, 2, 1, 1, 1, -1, 2, 2, 0, 0, 2, 1, 1, 1, -1, 2, 0, 2, 0]; 939 | 940 | const squish3D = (Math.sqrt(3 + 1) - 1) / 3; 941 | const setContribution3D = (multiplier, xsb, ysb, zsb) => { 942 | heapF64[(offset >> 1) + 0] = -xsb - multiplier * squish3D; 943 | heapF64[(offset >> 1) + 1] = -ysb - multiplier * squish3D; 944 | heapF64[(offset >> 1) + 2] = -zsb - multiplier * squish3D; 945 | heapI32[offset + (3 << 1) + 0] = xsb; 946 | heapI32[offset + (3 << 1) + 1] = ysb; 947 | heapI32[offset + (3 << 1) + 2] = zsb; 948 | offset += 5 << 1; 949 | }; 950 | 951 | for (let i = 0; i < p3D.length; i += 9) { 952 | const baseSet = base3D[p3D[i]]; 953 | const length = baseSet.length / 4 + 2; 954 | heapU32[offset] = length; 955 | offset += 1 << 1; 956 | for (let k = 0; k < baseSet.length; k += 4) 957 | setContribution3D(baseSet[k], baseSet[k + 1], baseSet[k + 2], baseSet[k + 3]); 958 | setContribution3D(p3D[i + 1], p3D[i + 2], p3D[i + 3], p3D[i + 4]); 959 | setContribution3D(p3D[i + 5], p3D[i + 6], p3D[i + 7], p3D[i + 8]); 960 | offset += (5 * (8 - length)) << 1; 961 | } 962 | } 963 | 964 | { 965 | //prettier-ignore 966 | const lookupPairs4D = [0, 3, 1, 2, 2, 3, 5, 2, 6, 1, 7, 1, 8, 3, 9, 2, 10, 3, 13, 2, 16, 3, 18, 3, 22, 1, 23, 1, 24, 3, 26, 3, 33, 2, 37, 2, 38, 1, 39, 1, 41, 2, 45, 2, 54, 1, 55, 1, 56, 0, 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 256, 3, 258, 3, 264, 3, 266, 3, 272, 3, 274, 3, 280, 3, 282, 3, 2049, 2, 2053, 2, 2057, 2, 2061, 2, 2081, 2, 2085, 2, 2089, 2, 2093, 2, 2304, 9, 2305, 9, 2312, 9, 2313, 9, 16390, 1, 16391, 1, 16406, 1, 16407, 1, 16422, 1, 16423, 1, 16438, 1, 16439, 1, 16642, 8, 16646, 8, 16658, 8, 16662, 8, 18437, 6, 18439, 6, 18469, 6, 18471, 6, 18688, 9, 18689, 9, 18690, 8, 18693, 6, 18694, 8, 18695, 6, 18696, 9, 18697, 9, 18706, 8, 18710, 8, 18725, 6, 18727, 6, 131128, 0, 131129, 0, 131130, 0, 131131, 0, 131132, 0, 131133, 0, 131134, 0, 131135, 0, 131352, 7, 131354, 7, 131384, 7, 131386, 7, 133161, 5, 133165, 5, 133177, 5, 133181, 5, 133376, 9, 133377, 9, 133384, 9, 133385, 9, 133400, 7, 133402, 7, 133417, 5, 133421, 5, 133432, 7, 133433, 5, 133434, 7, 133437, 5, 147510, 4, 147511, 4, 147518, 4, 147519, 4, 147714, 8, 147718, 8, 147730, 8, 147734, 8, 147736, 7, 147738, 7, 147766, 4, 147767, 4, 147768, 7, 147770, 7, 147774, 4, 147775, 4, 149509, 6, 149511, 6, 149541, 6, 149543, 6, 149545, 5, 149549, 5, 149558, 4, 149559, 4, 149561, 5, 149565, 5, 149566, 4, 149567, 4, 149760, 9, 149761, 9, 149762, 8, 149765, 6, 149766, 8, 149767, 6, 149768, 9, 149769, 9, 149778, 8, 149782, 8, 149784, 7, 149786, 7, 149797, 6, 149799, 6, 149801, 5, 149805, 5, 149814, 4, 149815, 4, 149816, 7, 149817, 5, 149818, 7, 149821, 5, 149822, 4, 149823, 4, 149824, 37, 149825, 37, 149826, 36, 149829, 34, 149830, 36, 149831, 34, 149832, 37, 149833, 37, 149842, 36, 149846, 36, 149848, 35, 149850, 35, 149861, 34, 149863, 34, 149865, 33, 149869, 33, 149878, 32, 149879, 32, 149880, 35, 149881, 33, 149882, 35, 149885, 33, 149886, 32, 149887, 32, 150080, 49, 150082, 48, 150088, 49, 150098, 48, 150104, 47, 150106, 47, 151873, 46, 151877, 45, 151881, 46, 151909, 45, 151913, 44, 151917, 44, 152128, 49, 152129, 46, 152136, 49, 152137, 46, 166214, 43, 166215, 42, 166230, 43, 166247, 42, 166262, 41, 166263, 41, 166466, 48, 166470, 43, 166482, 48, 166486, 43, 168261, 45, 168263, 42, 168293, 45, 168295, 42, 168512, 31, 168513, 28, 168514, 31, 168517, 28, 168518, 25, 168519, 25, 280952, 40, 280953, 39, 280954, 40, 280957, 39, 280958, 38, 280959, 38, 281176, 47, 281178, 47, 281208, 40, 281210, 40, 282985, 44, 282989, 44, 283001, 39, 283005, 39, 283208, 30, 283209, 27, 283224, 30, 283241, 27, 283256, 22, 283257, 22, 297334, 41, 297335, 41, 297342, 38, 297343, 38, 297554, 29, 297558, 24, 297562, 29, 297590, 24, 297594, 21, 297598, 21, 299365, 26, 299367, 23, 299373, 26, 299383, 23, 299389, 20, 299391, 20, 299584, 31, 299585, 28, 299586, 31, 299589, 28, 299590, 25, 299591, 25, 299592, 30, 299593, 27, 299602, 29, 299606, 24, 299608, 30, 299610, 29, 299621, 26, 299623, 23, 299625, 27, 299629, 26, 299638, 24, 299639, 23, 299640, 22, 299641, 22, 299642, 21, 299645, 20, 299646, 21, 299647, 20, 299648, 61, 299649, 60, 299650, 61, 299653, 60, 299654, 59, 299655, 59, 299656, 58, 299657, 57, 299666, 55, 299670, 54, 299672, 58, 299674, 55, 299685, 52, 299687, 51, 299689, 57, 299693, 52, 299702, 54, 299703, 51, 299704, 56, 299705, 56, 299706, 53, 299709, 50, 299710, 53, 299711, 50, 299904, 61, 299906, 61, 299912, 58, 299922, 55, 299928, 58, 299930, 55, 301697, 60, 301701, 60, 301705, 57, 301733, 52, 301737, 57, 301741, 52, 301952, 79, 301953, 79, 301960, 76, 301961, 76, 316038, 59, 316039, 59, 316054, 54, 316071, 51, 316086, 54, 316087, 51, 316290, 78, 316294, 78, 316306, 73, 316310, 73, 318085, 77, 318087, 77, 318117, 70, 318119, 70, 318336, 79, 318337, 79, 318338, 78, 318341, 77, 318342, 78, 318343, 77, 430776, 56, 430777, 56, 430778, 53, 430781, 50, 430782, 53, 430783, 50, 431000, 75, 431002, 72, 431032, 75, 431034, 72, 432809, 74, 432813, 69, 432825, 74, 432829, 69, 433032, 76, 433033, 76, 433048, 75, 433065, 74, 433080, 75, 433081, 74, 447158, 71, 447159, 68, 447166, 71, 447167, 68, 447378, 73, 447382, 73, 447386, 72, 447414, 71, 447418, 72, 447422, 71, 449189, 70, 449191, 70, 449197, 69, 449207, 68, 449213, 69, 449215, 68, 449408, 67, 449409, 67, 449410, 66, 449413, 64, 449414, 66, 449415, 64, 449416, 67, 449417, 67, 449426, 66, 449430, 66, 449432, 65, 449434, 65, 449445, 64, 449447, 64, 449449, 63, 449453, 63, 449462, 62, 449463, 62, 449464, 65, 449465, 63, 449466, 65, 449469, 63, 449470, 62, 449471, 62, 449472, 19, 449473, 19, 449474, 18, 449477, 16, 449478, 18, 449479, 16, 449480, 19, 449481, 19, 449490, 18, 449494, 18, 449496, 17, 449498, 17, 449509, 16, 449511, 16, 449513, 15, 449517, 15, 449526, 14, 449527, 14, 449528, 17, 449529, 15, 449530, 17, 449533, 15, 449534, 14, 449535, 14, 449728, 19, 449729, 19, 449730, 18, 449734, 18, 449736, 19, 449737, 19, 449746, 18, 449750, 18, 449752, 17, 449754, 17, 449784, 17, 449786, 17, 451520, 19, 451521, 19, 451525, 16, 451527, 16, 451528, 19, 451529, 19, 451557, 16, 451559, 16, 451561, 15, 451565, 15, 451577, 15, 451581, 15, 451776, 19, 451777, 19, 451784, 19, 451785, 19, 465858, 18, 465861, 16, 465862, 18, 465863, 16, 465874, 18, 465878, 18, 465893, 16, 465895, 16, 465910, 14, 465911, 14, 465918, 14, 465919, 14, 466114, 18, 466118, 18, 466130, 18, 466134, 18, 467909, 16, 467911, 16, 467941, 16, 467943, 16, 468160, 13, 468161, 13, 468162, 13, 468163, 13, 468164, 13, 468165, 13, 468166, 13, 468167, 13, 580568, 17, 580570, 17, 580585, 15, 580589, 15, 580598, 14, 580599, 14, 580600, 17, 580601, 15, 580602, 17, 580605, 15, 580606, 14, 580607, 14, 580824, 17, 580826, 17, 580856, 17, 580858, 17, 582633, 15, 582637, 15, 582649, 15, 582653, 15, 582856, 12, 582857, 12, 582872, 12, 582873, 12, 582888, 12, 582889, 12, 582904, 12, 582905, 12, 596982, 14, 596983, 14, 596990, 14, 596991, 14, 597202, 11, 597206, 11, 597210, 11, 597214, 11, 597234, 11, 597238, 11, 597242, 11, 597246, 11, 599013, 10, 599015, 10, 599021, 10, 599023, 10, 599029, 10, 599031, 10, 599037, 10, 599039, 10, 599232, 13, 599233, 13, 599234, 13, 599235, 13, 599236, 13, 599237, 13, 599238, 13, 599239, 13, 599240, 12, 599241, 12, 599250, 11, 599254, 11, 599256, 12, 599257, 12, 599258, 11, 599262, 11, 599269, 10, 599271, 10, 599272, 12, 599273, 12, 599277, 10, 599279, 10, 599282, 11, 599285, 10, 599286, 11, 599287, 10, 599288, 12, 599289, 12, 599290, 11, 599293, 10, 599294, 11, 599295, 10]; 967 | for (let i = 0; i < lookupPairs4D.length; i += 2) { 968 | heapU32[offset + lookupPairs4D[i]] = lookupPairs4D[i + 1]; 969 | } 970 | 971 | offset += 1048576; 972 | 973 | // prettier-ignore 974 | const base4D = [ 975 | [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1], 976 | [3, 1, 1, 1, 0, 3, 1, 1, 0, 1, 3, 1, 0, 1, 1, 3, 0, 1, 1, 1, 4, 1, 1, 1, 1], 977 | [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 2, 1, 1, 0, 0, 2, 1, 0, 1, 0, 2, 1, 0, 0, 1, 2, 0, 1, 1, 0, 2, 0, 1, 0, 1, 2, 0, 0, 1, 1], 978 | [3, 1, 1, 1, 0, 3, 1, 1, 0, 1, 3, 1, 0, 1, 1, 3, 0, 1, 1, 1, 2, 1, 1, 0, 0, 2, 1, 0, 1, 0, 2, 1, 0, 0, 1, 2, 0, 1, 1, 0, 2, 0, 1, 0, 1, 2, 0, 0, 1, 1], 979 | ]; 980 | // prettier-ignore 981 | const p4D = [0, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 1, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, 0, -1, 0, 1, 0, 0, 0, -1, 1, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 1, 0, 0, -1, 0, 1, 0, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 0, 2, 1, 0, 1, 0, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 0, 2, 0, 1, 1, 0, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1, 0, 2, 1, 0, 0, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 0, 2, 0, 1, 0, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 0, 2, 0, 0, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 1, 4, 2, 1, 1, 0, 4, 1, 2, 1, 0, 4, 1, 1, 2, 0, 1, 4, 2, 1, 0, 1, 4, 1, 2, 0, 1, 4, 1, 1, 0, 2, 1, 4, 2, 0, 1, 1, 4, 1, 0, 2, 1, 4, 1, 0, 1, 2, 1, 4, 0, 2, 1, 1, 4, 0, 1, 2, 1, 4, 0, 1, 1, 2, 1, 2, 1, 1, 0, 0, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 1, 2, 1, 0, 1, 0, 3, 2, 0, 1, 0, 3, 1, 0, 2, 0, 1, 2, 0, 1, 1, 0, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0, 1, 2, 1, 0, 0, 1, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 1, 2, 0, 1, 0, 1, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 1, 2, 0, 0, 1, 1, 3, 0, 0, 2, 1, 3, 0, 0, 1, 2, 2, 3, 1, 1, 1, 0, 2, 1, 1, 1, -1, 2, 2, 0, 0, 0, 2, 3, 1, 1, 0, 1, 2, 1, 1, -1, 1, 2, 2, 0, 0, 0, 2, 3, 1, 0, 1, 1, 2, 1, -1, 1, 1, 2, 2, 0, 0, 0, 2, 3, 1, 1, 1, 0, 2, 1, 1, 1, -1, 2, 0, 2, 0, 0, 2, 3, 1, 1, 0, 1, 2, 1, 1, -1, 1, 2, 0, 2, 0, 0, 2, 3, 0, 1, 1, 1, 2, -1, 1, 1, 1, 2, 0, 2, 0, 0, 2, 3, 1, 1, 1, 0, 2, 1, 1, 1, -1, 2, 0, 0, 2, 0, 2, 3, 1, 0, 1, 1, 2, 1, -1, 1, 1, 2, 0, 0, 2, 0, 2, 3, 0, 1, 1, 1, 2, -1, 1, 1, 1, 2, 0, 0, 2, 0, 2, 3, 1, 1, 0, 1, 2, 1, 1, -1, 1, 2, 0, 0, 0, 2, 2, 3, 1, 0, 1, 1, 2, 1, -1, 1, 1, 2, 0, 0, 0, 2, 2, 3, 0, 1, 1, 1, 2, -1, 1, 1, 1, 2, 0, 0, 0, 2, 2, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 0, 0, 0, 0, 0, 2, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 0, 0, 0, 0, 0, 2, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1, 0, 0, 0, 0, 0, 2, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 0, 0, 0, 0, 0, 2, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 0, 0, 0, 0, 0, 2, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 0, 0, 0, 0, 0, 2, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 2, 2, 0, 0, 0, 2, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 2, 2, 0, 0, 0, 2, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 2, 2, 0, 0, 0, 2, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 2, 0, 2, 0, 0, 2, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1, 2, 0, 2, 0, 0, 2, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 2, 0, 2, 0, 0, 2, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 2, 0, 0, 2, 0, 2, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1, 2, 0, 0, 2, 0, 2, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 2, 0, 0, 2, 0, 2, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 2, 0, 0, 0, 2, 2, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 2, 0, 0, 0, 2, 2, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 2, 0, 0, 0, 2, 3, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 2, 1, 1, 1, -1, 3, 1, 0, 1, 0, 0, 2, 0, 2, 0, 0, 2, 1, 1, 1, -1, 3, 1, 0, 0, 1, 0, 2, 0, 0, 2, 0, 2, 1, 1, 1, -1, 3, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 2, 1, 1, -1, 1, 3, 1, 0, 1, 0, 0, 2, 0, 2, 0, 0, 2, 1, 1, -1, 1, 3, 1, 0, 0, 0, 1, 2, 0, 0, 0, 2, 2, 1, 1, -1, 1, 3, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 2, 1, -1, 1, 1, 3, 1, 0, 0, 1, 0, 2, 0, 0, 2, 0, 2, 1, -1, 1, 1, 3, 1, 0, 0, 0, 1, 2, 0, 0, 0, 2, 2, 1, -1, 1, 1, 3, 1, 0, 1, 0, 0, 2, 0, 2, 0, 0, 2, -1, 1, 1, 1, 3, 1, 0, 0, 1, 0, 2, 0, 0, 2, 0, 2, -1, 1, 1, 1, 3, 1, 0, 0, 0, 1, 2, 0, 0, 0, 2, 2, -1, 1, 1, 1, 3, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 4, 1, 1, 1, 1, 3, 3, 2, 0, 1, 0, 3, 1, 0, 2, 0, 4, 1, 1, 1, 1, 3, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0, 4, 1, 1, 1, 1, 3, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 4, 1, 1, 1, 1, 3, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 4, 1, 1, 1, 1, 3, 3, 0, 0, 2, 1, 3, 0, 0, 1, 2, 4, 1, 1, 1, 1, 3, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 2, 1, 1, 1, -1, 3, 3, 2, 0, 1, 0, 3, 1, 0, 2, 0, 2, 1, 1, 1, -1, 3, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0, 2, 1, 1, 1, -1, 3, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 2, 1, 1, -1, 1, 3, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 2, 1, 1, -1, 1, 3, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 2, 1, 1, -1, 1, 3, 3, 2, 0, 1, 0, 3, 1, 0, 2, 0, 2, 1, -1, 1, 1, 3, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 2, 1, -1, 1, 1, 3, 3, 0, 0, 2, 1, 3, 0, 0, 1, 2, 2, 1, -1, 1, 1, 3, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0, 2, -1, 1, 1, 1, 3, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 2, -1, 1, 1, 1, 3, 3, 0, 0, 2, 1, 3, 0, 0, 1, 2, 2, -1, 1, 1, 1]; 982 | 983 | const squish4D = (Math.sqrt(4 + 1) - 1) / 4; 984 | const setContribution4D = (multiplier, xsb, ysb, zsb, wsb) => { 985 | heapF64[(offset >> 1) + 0] = -xsb - multiplier * squish4D; 986 | heapF64[(offset >> 1) + 1] = -ysb - multiplier * squish4D; 987 | heapF64[(offset >> 1) + 2] = -zsb - multiplier * squish4D; 988 | heapF64[(offset >> 1) + 3] = -wsb - multiplier * squish4D; 989 | heapI32[offset + (4 << 1) + 0] = xsb; 990 | heapI32[offset + (4 << 1) + 1] = ysb; 991 | heapI32[offset + (4 << 1) + 2] = zsb; 992 | heapI32[offset + (4 << 1) + 3] = wsb; 993 | offset += 6 << 1; 994 | }; 995 | 996 | for (let i = 0; i < p4D.length; i += 16) { 997 | const baseSet = base4D[p4D[i]]; 998 | const length = baseSet.length / 5 + 3; 999 | heapU32[offset] = length; 1000 | offset += 1 << 1; 1001 | for (let k = 0; k < baseSet.length; k += 5) 1002 | setContribution4D(baseSet[k], baseSet[k + 1], baseSet[k + 2], baseSet[k + 3], baseSet[k + 4]); 1003 | setContribution4D(p4D[i + 1], p4D[i + 2], p4D[i + 3], p4D[i + 4], p4D[i + 5]); 1004 | setContribution4D(p4D[i + 6], p4D[i + 7], p4D[i + 8], p4D[i + 9], p4D[i + 10]); 1005 | setContribution4D(p4D[i + 11], p4D[i + 12], p4D[i + 13], p4D[i + 14], p4D[i + 15]); 1006 | offset += (6 * (16 - length)) << 1; 1007 | } 1008 | } 1009 | } 1010 | 1011 | const { setSeed, noise2D, noise3D, noise4D } = OpenSimplex( 1012 | { 1013 | Math, 1014 | Uint16Array, 1015 | Uint32Array, 1016 | Int32Array, 1017 | Float64Array, 1018 | }, 1019 | { 1020 | setSeed: (value) => (random.seed = value), 1021 | nextUint32: random.nextUint32, 1022 | print(n) { 1023 | return console.log(n); 1024 | }, 1025 | }, 1026 | heap 1027 | ); 1028 | 1029 | let seed = 0; 1030 | setSeed(seed); 1031 | 1032 | export default { 1033 | set seed(value) { 1034 | seed = value; 1035 | setSeed(seed); 1036 | }, 1037 | get seed() { 1038 | return seed; 1039 | }, 1040 | noise2D, 1041 | noise3D, 1042 | noise4D, 1043 | }; 1044 | --------------------------------------------------------------------------------