Giter Site home page Giter Site logo

jwagner / simplex-noise.js Goto Github PK

View Code? Open in Web Editor NEW
1.5K 26.0 128.0 1.6 MB

A fast simplex noise implementation in Javascript / Typescript.

License: MIT License

JavaScript 8.75% HTML 0.51% Shell 4.44% Dockerfile 2.28% TypeScript 84.02%
javascript noise-functions simplex demo gfx nodejs procedural procedural-art procedural-generation procedural-terrain

simplex-noise.js's Introduction

Tests TypeScript

simplex-noise.js header API Documentation

simplex-noise.js is a simplex noise implementation in Javascript/TypeScript. It works in the browser and Node.js, using CommonJS and ES Modules. It is self-contained (dependency-free), relatively small (about 2k minified and gzipped) and fairly fast (about 20 nanoseconds for a sample of 2d noise) and tree shakeable.

Demos & Real World Examples

Created something awesome with simplex-noise? Let me know so I can add it to the list.

Installation

npm i -S simplex-noise

Usage Examples

ES Module Import

// import the noise functions you need
import { createNoise2D } from 'simplex-noise';

CommonJS Require

// import the noise functions you need
const { createNoise2D } = require('simplex-noise');

2D

// initialize the noise function
const noise2D = createNoise2D();
// returns a value between -1 and 1
console.log(noise2D(x, y));

3D

const noise3D = createNoise3D();
console.log(noise3D(x, y, z));

4D

const noise4D = createNoise4D();
console.log(noise4D(x, y, z, w));

Using a seed value

By default simplex-noise.js will use Math.random() to seed the noise. You can pass in a PRNG function to use your own seed value.

# install the alea prng
npm install -S alea
import alea from 'alea';
// create a new random function based on the seed
const prng = alea('seed');
// use the seeded random function to initialize the noise function
const noise2D = createNoise2D(prng);
console.log(noise2D(x, y));

The ALEA PRNG used in the example above can be found in the alea npm package.

Benchmarks

simplex-noise.js is reasonably quick. According to perf/index.js I can perform about 70 million noise2D() calls/second on a single thread on my desktop (Ryzen 5950X).

$ node perf/index.js
noise2D: 72,916,215 ops/sec ±1%
noise3D: 47,855,199 ops/sec ±0%
noise4D: 35,564,111 ops/sec ±0%

Migrating from 3.x to 4.x

random initialization

// 3.x
import SimplexNoise from 'simplex-noise';
const simplex = new SimplexNoise();
const value2d = simplex.noise2D(x, y);
// 4.x
// import the functions you need
import { createNoise2D } from 'simplex-noise';
const noise2D = createNoise2D();
const value2d = noise2D(x, y);

Initialization with a seed

// 3.x
import SimplexNoise from 'simplex-noise';
const simplex = new SimplexNoise('seed');
const value2d = simplex.noise2D(x, y);
// 4.x
// npm install -S alea
import { createNoise2D } from 'simplex-noise';
import alea from 'alea';
const noise2D = createNoise2D(alea('seed'));
const value2d = noise2D(x, y);

// IMPORTANT: If you use multiple noise functions (for example 2d and 3d)
// and want compatible output with 3.x you will need to pass a fresh instance
// of alea to each create call. If you reuse the alea instance you will
// get different outputs compared to simplex-noise 3.x.
const seed = 'seed';
const noise2D = createNoise2D(alea(seed));
const noise3D = createNoise3D(alea(seed));

Emulating the 3.x and older API

const simplex = {
  noise2D: createNoise2D(alea(seed)),
  noise3D: createNoise3D(alea(seed)),
  noise4D: createNoise4D(alea(seed)),
};

Changelog

4.0.1

  • Explicitly defined the return type of createNoise4D to be NoiseFunction4D. Contributed by satelllte.

4.0.0

⚠️ This release changes the API and the output of the noise functions. ⚠️

  • Reworked the API so that the noise functions can be imported individually. When combined with tree shaking this helps with build sizes.
  • Removed the built in version of the ALEA PRNG to focus the library to do only one thing. If you want to continue to use it you'll have to install and import it separately.
  • Noise functions are a bit faster (~ 20 - 30%).
  • Noise values can be different from previous versions
  • Input coordinates bigger than 2^31 may not result in a noisy output anymore. If you have a use case that is affected by this change, please file an issue.
  • Test coverage is now at 100%.
  • A big thank you to @mreinstein, @redblobgames and everyone else involved for their comments and PRs which motivated me to create this new version.

3.0.1

  • Include simplex-noise.ts as source file, fixes sourcemap warnings.

3.0.0

  • Changed module structure. When using bundlers that import the es module even using require() the import might need to be updated.
  • Dependency update
  • Setting sideEffects: false in package.json
  • Added snapshot tests
  • Code converted to typescript, the package can of course still be used from regular JS
  • Dropped bower
  • Added support for es modules

2.4.0

  • Included a PRNG based on ALEA to directly allow seeding
  • Included typescript definitions

2.3.0

⚠️ This release changes the output of the noise functions. ⚠️

In the future such changes will be released as a new major version.

  • Corrected generation of permutation table
  • Moved tests to mocha/chai
  • Cleanup

2.2.0

  • Small performance improvement for 2D noise

2.1.1

  • Increased entropy by fixing a little initialization issue.

2.1.0

  • AMD support

2.0.0

  • Changed node.js api, SimplexNoise is now exported directly.
  • Added unit tests

1.0.0

  • Initial Release

License

Copyright (c) 2022 Jonas Wagner, licensed under the MIT License (enclosed)

Credits

This is mostly a direct javascript port of the Java implementation by Stefan Gustavson and Peter Eastman.

The initial typescript definition has been provided by Neonit.

simplex-noise.js's People

Contributors

deathcap avatar dependabot[bot] avatar espadrine avatar jwagner avatar neonit avatar satelllte avatar sietsem avatar tophattom avatar viljami avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

simplex-noise.js's Issues

bigint

Would you consider supporting bigint?

importing alea as a module

https://www.npmjs.com/package/alea is tiny and could probably be leveraged inside of simplex-noise.

This would be valuable because other parts of my simulation rely on alea, and if simplex-noise is pulling this in as a dependency I'll have less duplicated code.

@jwagner would you be open to a PR for this? I'm happy to submit one.

Licensing?

Great library! Can you clear up licensing by adding that in the readme somewhere? We would love to use this for our projects.

error in `/simplex-noise/dist/cjs/simplex-noise.js:460`, `random is not a function`

Hello, I installed simplex-noise from npm and get the following error upon using it:

.../node_modules/simplex-noise/dist/cjs/simplex-noise.js:460
        const r = i + ~~(random() * (256 - i));
                         ^

TypeError: random is not a function
    at buildPermutationTable (.../node_modules/simplex-noise/dist/cjs/simplex-noise.js:460:26)
    at createNoise3D (.../node_modules/simplex-noise/dist/cjs/simplex-noise.js:164:18)
    ...

Node.js v18.9.1

I've removed my directories from the log.
I can't tell if this is an issue on my side (and I am missing the random function) or if this was supposed to be Math.random

Thanks!

Gustavson issued corrections to his Java code, but no one has updated to reflect them!

Hi jwagner,

I'm new to github, so please forgive my ignorance...

I've been looking into performant noise algorithms and read Perlin's followup paper as well as Gustavson's more recent corrections to his original Java Simplex Noise pdf.

As far as javascript optimizations go, I believe I've made a least a modest improvement to your port of Gustavson's code. I had worked out a way to factor out simplex lookup without realizing you had already done so. In this fork I also factored out gradient lookup. I haven't run any tests on this yet, but based on my atomic tests on simplex lookup (in and of itself), the computation vs lookup is 50% faster. I would assume that factoring out gradient lookup provides a similar result, but I don't know how much that weights against the complete noise function (i.e. my test was isolated to just the lookup).

The correction that Gustavson has posted is related to interpolant continuity at cell edges, i.e. offsetting from 0.6 places a seam between cells (in 3d as well as 4d, 2d was correct), where an offset from 0.5 (centered) was the correct calculation.

I can create a pull request if you like, but I didn't know if there was anything else that I could/should do that would be useful on my fork - (I only made changes to simplex-noise.js).

Sorry for the long message, I didn't know how else to message you and I'm not familiar with discussion boards yet. :/

https://github.com/EricBalingit/simplex-noise.js

Include ALEA in simplex-noise.js

Properly seeding simplex-noise.js has repeatedly caused confusion among it's user base.
For the next release include the alea prng by Johannes Baagøe directly in simplex-noise.js.
Use it to allow the construction of noise generators directly from a seed.

It should not add more than a few hundred bytes to the total size of the library which I consider to be a good trade-off considering the usability benefits.

https://github.com/nquinlan/better-random-numbers-for-javascript-mirror#license

Firefox bad performance

Only in firefox i had issues, like 10 fps.... any fix ?

I tested, opera, safari, chrome, vivaldi, edge all fine.

Analytical derivatives?

Any chance you might add an (optional) way to get analytical derivatives for the noise result?

Derivatives are handy because they tell you the ”slope” of the noise, which is incredibly useful for use cases like terrain generation. It’s possible to manually calculate them by sampling the noise 3+ times, but (as I understand it) analytical derivatives are much cheaper to compute.

As a reference, I’ve found these implementations:

I’ve explored adding them myself and making a PR, but honestly I’m a bit out of my depth here. :)

Browser use

Sorry, if this is a silly question but how do I use this library in a browser? Is there a minified version of the code somewhere that I could include on the front-end? Your linked codepen example probably uses an older version of the lib as the seed oprion doesn't work. Thank you.

rollup complains about the `#__PURE__` annotations

👋 hey, love the library, i've used it for years for many projects, it's my go-to!

i noticed rollup is complaining about the #__PURE__ comments -- glancing at rollup's docs, i think it just wants these annotations positioned before the const?

i suspect a change like this might make both uglify and rollup happy? i'm using terser, which apparently supports these same kinds of annotations.

- const F2 = /*#__PURE__*/ 0.5 * (Math.sqrt(3.0) - 1.0);
+ /*#__PURE__*/ const F2 = 0.5 * (Math.sqrt(3.0) - 1.0);

rollup's warning, literally complaining about the meta-comment // these #__PURE__ comments help uglifyjs with dead code removal which is kinda funny

(!) A comment

"// these #__PURE__ comments help uglifyjs with dead code removal"

in "../toolbox/node_modules/simplex-noise/dist/esm/simplex-noise.js" contains an annotation that Rollup cannot interpret due to the position of the comment. The comment will be removed to avoid issues.
https://rollupjs.org/https://rollupjs.org/configuration-options/#pure
../toolbox/node_modules/simplex-noise/dist/esm/simplex-noise.js (29:0)
27:  SOFTWARE.
28:  */
29: // these #__PURE__ comments help uglifyjs with dead code removal
    ^
30: //
31: const F2 = /*#__PURE__*/ 0.5 * (Math.sqrt(3.0) - 1.0);

another rollup warning about the next line

(!) A comment

"/*#__PURE__*/"

in "../toolbox/node_modules/simplex-noise/dist/esm/simplex-noise.js" contains an annotation that Rollup cannot interpret due to the position of the comment. The comment will be removed to avoid issues.
https://rollupjs.org/https://rollupjs.org/configuration-options/#pure
../toolbox/node_modules/simplex-noise/dist/esm/simplex-noise.js (31:11)
29: // these #__PURE__ comments help uglifyjs with dead code removal
30: //
31: const F2 = /*#__PURE__*/ 0.5 * (Math.sqrt(3.0) - 1.0);
               ^
32: const G2 = /*#__PURE__*/ (3.0 - Math.sqrt(3.0)) / 6.0;
33: const F3 = 1.0 / 3.0;

this obviously is not a critical issue.

Error in generation of permutation table

Simplex requires that p[] be a permutation table. The existing code:

for (var i = 0; i < 256; i++) {
    this.p[i] = random() * 256;
}

does not generate a permutation table. In the worst case, this could be an entire table with the same number.

ENOENT Error

What

Forgive me if I'm wrong but I am using this package in a create-react-app 5.0.0 and React 17.X.X setting and with simplex-noise 3.0.0 I recieve this error.

WARNING in ./node_modules/simplex-noise/dist/esm/simplex-noise.js
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from '/Users/matt-jarrett/Developer/js-pollock/node_modules/simplex-noise/simplex-noise.ts' file: Error: ENOENT: no such file or directory, open '/Users/matt-jarrett/Developer/js-pollock/node_modules/simplex-noise/simplex-noise.ts'
 @ ./src/lib/create-renderer.js 6:0-41 15:22-34
 @ ./src/lib/index.js 8:0-50 28:25-39
 @ ./src/App.js 13:0-25 87:39-42
 @ ./src/index.js 8:0-27 11:38-41

1 warning has detailed information that is not shown.
Use 'stats.errorDetails: true' resp. '--stats-error-details' to show it.

webpack 5.65.0 compiled with 1 warning in 1864 ms

My use

import SimplexNoise from "simplex-noise"
...
export default (opt = {}) => {
  ...
  const simplex = new SimplexNoise(randFunc)
  ...
}

Am I doing something wrong?

I searched for simplex-noise.ts as it's referenced in the error and I see it in this package's package.json.

...
"source": "simplex-noise.ts",
...

Move permutation table creation to a separate class method when using own PRNG

Feature request

Move the following into a SimplexNoise.init() (or other name) method:

this.p = buildPermutationTable(random);
this.perm = new Uint8Array(512);
this.permMod12 = new Uint8Array(512);
for (let i = 0; i < 512; i++) {
this.perm[i] = this.p[i & 255];
this.permMod12[i] = this.perm[i] % 12;
}
}

Use case

When updating the random number generator, we are forced to recreate an instance of SimplexNoise. With this, we could create a single instance and reinit it if the PRNG changed:

// Use default Math.random (non predictable)
let simplex = new SimplexNoise(Math.random);

function setSeed(s) {
  // Update seed to make Math.random predictable
  seedMathRandom(s)
  
  // Before:
  // Recreate noise instance
  simplex = new SimplexNoise(Math.random);

  // After proposed change:
  // Reset permutation table
  simplex.init(Math.random);
}

setSeed('0')

Let me know how that sounds and if you need a PR.

WebGL for noise2d

I was just looking through this and wondering if webgl could be used to offload the generation to the gpu.

The code looks like it doesn't use anything a fragment shader can't do, but I would like someone who knows more about simplex noise to weigh in.

Add note to readme about `-1` to `1`

Thanks for this great library!

I think it would be helpful to add a note to the readme mentioning that the values returned are between -1 and 1, for the case where people don't remember and want to check quickly. I verified this currently by just looking at the test files.

Since P5.js returns values between 0 and 1 (which seems weirder?) I always forget which is the right way to do it.

higher dimensions

Would you consider supporting dimensions beyond 4D, specifically 5D and 6D?

For me this would simplify use-cases for looping / tiling animations such as #29 which can be implemented by using two of the dimensions to sample along a circle.

SimplexNoise is undefined in webworkers

Just calling importScripts() does not bring SimplexNoise to the global scope in webworkers. This at least used to work with earlier versions.

Workaround:

let exports = {};
importScripts('simplex-noise.js');
let SimplexNoise = exports.SimplexNoise;

`package.json` not exported for Sapper

Whenever I build dev or build in sapper, rollup-plugin-svelte shows this warning.

[rollup-plugin-svelte] The following packages did not export their `package.json` file so we could not check the "svelte" field. If you had difficulties importing svelte components from a package, then please contact the author and ask them to export the package.json file.

Just to bring this to your attention, everything still works even though the warning is shown. All builds still are successful and functionality is not affected.

can not use seeds

if you try to use seeds ("var simplex = new SimplexNoise(Math.random);") the script will stop with an error.

simplify interface

hey, love what this module is doing. I was thinking it could be simplified further by using the following function signature:

simplex(random)(x[, y, z, w]) -> noise

The result would use currying to accept a function with the same random() -> percent signature as Math.random, then the user would be able to call a 1D, 2D, 3D, or 4D variation of the function which would be selected based on the number of arguments supplied.

Also addresses #16 by definition.

2.3.0 is braking change and should be bumped to 3.0.0

I'm making a game where I was using use 2.2.0 to generate a terrain. After new npm install I've got recently published 2.3.0 and the resulting noise has changed breaking my landscape completely. To follow the semantic versioning I would suggest reverting the changes and publishing 2.4 that's backwards compatible and publishing permutation table as 3.0.0

Before
screen shot 2017-01-12 at 21 00 06

After
screen shot 2017-01-12 at 21 00 49

Typo in readme

Under the section called "Initialization with a seed", it looks like the function call Alea('seed') should be alea('seed') instead.

import { createNoise2D } from 'simplex-noise';
import alea from 'alea';
const noise2D = createNoise2D(Alea('seed')); // this line
const value2d = noise2D(x, y);

`noise()` generic function

what about a "generic" noise function, with variable-length arguments, ie:

generic implied comment
noise() noise2D(0, 0) 0 by default
noise(1) noise2D(1,1) same value for 2nd arg
noise(1,2) noise2D(1,2)
noise(1,2,3) noise3D(1,2,3)
noise(1,2,3,4) noise4D(1,2,3,4)
noise(1,2,3,4,5) noise4D(1,2,3,4,5) NB: when more than 4 args => 5th, 6th... will just be ignored by noise4D

This is inspired from https://processing.org/reference/noise_.html

function noise(...args) {
  let dim // 2 or 3 or 4
  let args2 = [...args] // copy of args
  
  if (args.length < 2) {
    // 0 or 1 arg => noise2d
    const arg = args[0] || 0
    args2 = [arg, arg]
    dim = 2
  } else {
    // 2 or 3 or 4 or more args => noise2D or noise3D or noise4D
    dim = Math.min(args.length, 4)
  }
  
  return simplex[`noise${dim}D`](...args2) /2 + 0.5 // normalize [0;1]
}

NB: I've chosen to normalise the value to ]0;1[ but maybe you prefer staying ]-1;1[

working demo: https://codepen.io/abernier/pen/ExvqNyj

Option to make the noise wrap

I'm still searching for documentation on the subject since there isn't much and it's quite scattered, but it seems like making tileable noises is a non-trivial problem. It could be interesting to implement this directly into the library.

asm.js support

Any interest in porting this module to use asm.js for potentially better performance? Seems like a good fit (pure math).

I've started to.. my progress is available at https://github.com/deathcap/simplex-noise.js/tree/asm - only for noise2D at the moment, produces identical output as the original implementation (unit tests added) + successfully links as asm.js in Firefox.

Unfortunately, benchmarks show the asm.js version is drastically slower: http://jsperf.com/simplex-noise-comparison-asm (haven't yet tracked down why, exactly; very new to asm).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.