Skip to content
Stefan Gustavson edited this page Mar 25, 2022 · 40 revisions

Noise for GLSL 1.20

This repository contains GLSL source code for Perlin noise in 2D, 3D and 4D, both the modern simplex versions and the classic versions, including periodic noise similar to the pnoise() function in RenderMan SL. The functions have very good performance and no dependencies on external data. The code is open source, licensed under the terms of the OSI-approved and very permissive MIT license. For licensing details, please refer to the LICENSE file in the repository.

A scientific paper about this was accepted for publication in JGT, (Journal of Graphics Tools), and after a long delay it finally appeared in print in June 2012. You are also welcome to read our preprint on http://www.itn.liu.se/~stegu/jgt2012/.

The source code has been available online here on Github for some time, and you can of course use the functions without reading any part of the article. They require no setup or external data, just the GLSL source provided here, and they should work on any current OpenGL platform, including OpenGL 2.1, OpenGL 3.x and 4.x, OpenGL ES 2.x and WebGL (both 1.0 and 2.0). They will also work in limited vertex shader environments where texture lookup is not available.

NOTE: You do not need a super fast GPU to use these functions. They are useful even on low end hardware, old hardware and embedded OpenGL ES hardware with low performance. However, they require support for "highp" precision.

The repository also contains C code for a cross-platform benchmark and a demo. To compile and run these programs, you need a desktop OS like Linux, Windows, MacOSX or some flavor of Unix with OpenGL support, and the GLFW library (http://glfw.sourceforge.net). Makefiles are provided for Linux, Windows and MacOS X. The demo is a few years old and might be tricky to compile because it uses GLFW 2.x and old school OpenGL 2.1 calls (because that's what MacOS X required back in 2011), but the noise functions as such have aged well. They are perfectly useful even in OpenGL 4.x, not only in WebGL.

The GLSL source files and the noise functions that were originally published here were:

  • noise2D.glsl - 2D simplex noise float snoise(vec2 x). Very fast, very compact code.

  • noise3D.glsl - 3D simplex noise float snoise(vec3 x). Fast, compact code.

  • noise4D.glsl - 4D simplex noise float snoise(vec4 x). Reasonably fast, reasonably compact code.

  • classicnoise2D.glsl - 2D classic Perlin noise float cnoise(vec2 x), and a periodic variant float pnoise(vec2 x, vec2 period). Fast and compact code, only slightly slower than 2D simplex noise.

  • classicnoise3D.glsl - 3D classic Perlin noise float cnoise(vec3 x), and a periodic variant float pnoise(vec3 x, vec3 period). Reasonably fast but not very compact code. Not quite as fast as 3D simplex noise.

  • classicnoise4D.glsl - 4D classic Perlin noise float cnoise(vec4 x), and a periodic variant float pnoise(vec4 x, vec4 period). Only about half as fast as 4D simplex noise, and rather bloated code, but still useful.

The versions here are further optimized compared to the versions in the published JGT paper. Not by a lot, but they are somewhat faster still. Many of the hand-tweaked optimizations are now (2021) moot on recent GPUs with modern GLSL compilers, but low-end platforms can still benefit from them.

All the noise functions return values in the range -1 to 1, with a more or less bell-shaped distribution around a zero mean.

N-D return types

All classic and simplex noise functions above return a single float. For the equivalents of noise2(), noise3()and noise4(), you need to call these noise functions several times with different constant offsets for the arguments, e.g. vec3(snoise(P), snoise(P+17.0), snoise(P-43.0)). People have different opinions on whether these offsets should be integers for the classic noise functions to match the spacing of the zeroes, so we have left that for you to decide for yourself. For most applications, the exact offsets don't really matter as long as they are not too small or too close to the noise lattice period (289 in our implementation).

Other noise implementations

The motivation for these functions not using any textures is ease of use, self-sufficiency and scalability for massively parallel execution. Noise is seldom used by itself, and these functions can make use of the often untapped ALU resources when run concurrently with traditional texture-intensive real time rendering tasks. However, if you are generating noise by itself and using a lot of it, the texture-intensive noise implementations this work was based on are still up to twice as fast on current generation desktop GPU hardware with lots of texture units and smart texture caching. You can find the original release of the old noise code on http://www.itn.liu.se/~stegu/simplexnoise/GLSL-noise.zip (Windows binary, Windows-dependent source code using legacy OpenGL). A cross platform benchmark comparing it to this new version is on http://www.itn.liu.se/~stegu/simplexnoise/GLSL-noise-vs-noise.zip. For the convenience of Windows users, a version with a precompiled Windows binary is in http://www.itn.liu.se/~stegu/simplexnoise/GLSL-noise-vs-noise-Win32.zip.

Cellular (Worley) noise in GLSL

A few GLSL 1.20 compatible implementations of cellular noise ("Worley noise") are available in this repository, and also on http://www.itn.liu.se/~stegu/GLSL-cellular/. It is a straightforward but non-trivial implementation of previous ideas from software procedural shading, using the ideas for pseudo-random permutation from the computational Perlin noise originally presented here, with some optional shortcuts for situations where speed is more important than accuracy.

Tiling simplex noise with analytic derivatives and rotating gradients

In May 2016, another newly written variation on 2-D simplex noise was uploaded here, with eight separate but similar functions:

  • psrdnoise2D.glsl

vec3 psrdnoise(vec2 pos, vec2 per, float rot)

vec3 psdnoise(vec2 pos, vec2 per)

float psrnoise(vec2 pos, vec2 per, float rot)

float psnoise(vec2 pos, vec2 per)

vec3 srdnoise(vec2 pos, float rot)

vec3 sdnoise(vec2 pos)

float srnoise(vec2 pos, float rot)

float snoise(vec2 pos)

This version has a different, slightly stretched simplex grid which permits tiling in x and y, similarly to the periodic versions of classic noise. These functions also compute an analytical derivative of the noise function, which is useful for creating bump maps and normal maps, for texture domain distortion, and for tricks like "flow noise" and "curl noise". The animated rotation of the underlying gradients is a component of flow noise, as presented by Perlin and Neyret. For details, have a look at the source code. The comments should contain what you need to use these functions.

Flow noise

"Flow noise" is a neat trick for 2-D noise, where you rotate the gradients at the grid points and displace later terms in a fractal sum by the accumulated gradients of previous terms. It's a cheat with no strong connection to physics, but it can create a visual impression of turbulent flow. The functions in "psrdnoise" can be used to create flow noise.

Another, earlier GLSL 1.20 compatible implementation of "flow noise" using the original, non-tiling simplex grid is available as part of this demo: http://www.itn.liu.se/~stegu/gpunoise/. It's undocumented, but the example and the original Siggraph publication below should be enough to use it: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.141.5266&rep=rep1&type=pdf

Demos and Applications of webgl-noise

Do you have a WebGL application or demonstration that uses this noise library? Let us know and we will add it to this list.