OpenSimplex noise
OpenSimplex noise is an n-dimensional gradient noise function (supporting up to 4 dimensions) developed by Kurt Spencer in September 2014 as a patent-free alternative to Simplex noise, addressing the licensing restrictions on higher-dimensional implementations of the latter at the time (the Simplex noise patent expired in 2022).[1] It generates smooth, high-quality pseudorandom patterns suitable for procedural content creation, with reduced visible repetition and artifacts compared to Perlin noise, though it requires approximately twice the computation time and produces features roughly double the size at slightly lower contrast compared to Simplex noise.[1] The algorithm builds on the principles of gradient noise, where values are interpolated from random gradients at lattice points, but employs a larger kernel and optimized lattice orientations to enhance isotropy and visual quality, particularly in 3D and 4D spaces.[2] Released into the public domain, OpenSimplex noise has been widely ported to languages including Python, Go, Rust, and JavaScript, and integrated into tools like the Godot game engine (via FastNoiseLite supporting OpenSimplex variants as of Godot 4) for terrain generation, animations, and texture synthesis. Its output typically ranges from about 0.06 to 0.93 across dimensions (based on 80,000 samples), making it versatile for applications requiring seamless, non-repeating noise.[1][3][4]Background
Gradient noise fundamentals
Gradient noise is a class of procedural generation algorithms used to create smooth, natural-appearing randomness in computer graphics and simulations, achieved by interpolating between random gradient vectors assigned to points on a regular lattice grid. Unlike simpler methods, it evaluates noise values at arbitrary points by computing contributions from nearby lattice points, where each contribution is derived from the dot product of a pseudo-random gradient vector at the lattice point and the vector from that point to the evaluation location, followed by attenuation based on distance. This approach ensures the generated noise is continuous and differentiable, making it suitable for modeling organic phenomena such as terrain, clouds, or fluid motion in procedural textures.[5] The foundations of gradient noise trace back to early work in computer graphics, building on value noise—a precursor that assigns random scalar values to lattice points and interpolates them linearly, often resulting in blocky or grid-aligned artifacts due to discontinuous derivatives. Gradient noise was pioneered by Ken Perlin in 1983, developed to address the unnatural, mechanical appearance of early computer-generated imagery during his work on visual effects for films. Perlin's implementation, detailed in his 1985 SIGGRAPH paper, introduced the core technique for efficient naturalistic texture synthesis using a pseudo-random hash function to generate gradients at integer lattice coordinates. This innovation earned Perlin a Technical Achievement Academy Award in 1997 for its widespread impact on procedural modeling in animation and rendering.[5] Key components of gradient noise include the lattice structure, typically a uniform integer grid; pseudo-random gradient vectors, which are unit-length directions selected from a finite set to ensure isotropy; dot products that measure how aligned the evaluation direction is with the local gradient; and a smoothing kernel, often a cubic fade function like f(t) = 6t^5 - 15t^4 + 10t^3, to blend contributions smoothly and avoid sharp transitions. To generate 2D gradient noise at a point (x, y), the process conceptually follows these steps:- Compute the lattice cell indices: i = \lfloor x \rfloor, j = \lfloor y \rfloor, and fractional offsets u = x - i, v = y - j.
- Identify the four surrounding lattice corners: (i, j), (i+1, j), (i, j+1), (i+1, j+1).
- For each corner (x_k, y_k), retrieve or compute a pseudo-random gradient vector \mathbf{G}_k using a hash of the lattice coordinates.
- Calculate the distance vector \mathbf{D}_k = (x - x_k, y - y_k) and the raw influence as the dot product \mathbf{G}_k \cdot \mathbf{D}_k.
- Apply fade curves to the offsets: fu = f(u), fv = f(v), and interpolate the influences bilinearly to yield the final noise value n = lerp(lerp(influence at bottom, influence at top, fv), lerp(influence at left, influence at right, fv), fu), scaled to [-1, 1].
Simplex noise overview
Simplex noise, developed by Ken Perlin in 2001, serves as a refinement of his earlier classic Perlin noise algorithm from 1983. It replaces the hypercubic lattice with a simplicial lattice, which contains only n+1 lattice points per cell in n dimensions rather than $2^n, resulting in substantially fewer evaluations and improved computational efficiency, especially as dimensionality increases.[8][9] The underlying simplex grid employs simple geometric forms: line segments in 1D, equilateral triangles in 2D, regular tetrahedra in 3D, and analogous hyper-simplices in higher dimensions. This design minimizes the number of adjacent cells to consider during noise evaluation, shifting the algorithmic complexity from exponential O(2^n) in classic noise to polynomial O(n^2), making it more suitable for real-time applications and dimensions beyond 3D.[8][9] At its core, the algorithm locates the simplex containing the input point by skewing and unskewing coordinates to identify the cell and its vertices. Pseudo-random unit-length gradients are then assigned to these vertices using a hash function, and the noise value is derived as a sum of contributions from each vertex. Each contribution is the dot product of the gradient with the vector from the vertex to the input point, attenuated by distance-based kernel functions for smooth blending.[9] The interpolation within these contributions relies on a quintic fade curve, defined as F(t) = 6t^5 - 15t^4 + 10t^3, which ensures C^1 continuity and natural easing from 0 to 1.[9] While Simplex noise effectively mitigates the directional artifacts present in classic Perlin noise—yielding visually isotropic output—and supports efficient higher-dimensional generation, its adoption was limited by U.S. Patent 6,867,776 until expiration on January 8, 2022. In very high dimensions (e.g., 6D+), the coordinate sorting step for simplex identification introduces significant overhead, rendering it less practical.[9][4]Development
Motivation and patent context
The development of OpenSimplex noise arose from significant legal and practical barriers posed by the patent on Ken Perlin's Simplex noise algorithm. In 2001, Perlin filed for a patent on an improved noise generation method using simplicial grids to produce visually isotropic textures without grid artifacts, which was granted as US Patent 6,867,776 B2 in 2005 and restricted commercial implementations until its expiration in January 2022.[4] This limitation hindered widespread adoption in open-source projects and commercial software, as developers risked infringement when integrating Simplex noise for procedural generation tasks like terrain modeling and texture synthesis.[10] Within open-source communities focused on procedural content creation, there was increasing demand for unrestricted alternatives to patented noise functions, particularly for tools in game engines, simulations, and computer graphics where Simplex noise's efficiency in higher dimensions was highly valued.[1] Prior efforts to address this included adaptations of earlier noise types, such as Worley noise—a cellular basis function introduced in 1996 that generates Voronoi-like patterns for organic textures—but these often fell short in delivering the continuous, gradient-based smoothness and spectral qualities of Simplex noise, making them less suitable for applications requiring seamless, artifact-free gradients.[11] To overcome these patent-related constraints, software developer Kurt Spencer released OpenSimplex noise on September 22, 2014, explicitly designing it as an open, unlicensed gradient noise algorithm that supports up to four dimensions while aiming to match or exceed Simplex noise's quality without invoking protected methods.[1] Spencer's implementation was created to ensure patent avoidance, providing a viable option for developers in resource-constrained environments like indie game development and real-time rendering.[12]Creation and release
OpenSimplex noise was developed by Kurt Spencer, a software developer interested in procedural generation techniques for games. Spencer released the initial Java implementation on September 22, 2014, through a forum post on JVM Gaming, where he shared the source code for a 3D noise generator as a patent-free alternative to Simplex noise.[1] Spencer's development process focused on preserving Simplex noise's core benefits, such as computational efficiency and fewer visible artifacts compared to classic Perlin noise, while avoiding patent restrictions and achieving better visual isotropy—particularly in higher dimensions—via modified lattice geometries and gradient selections.[1] On October 5, 2014, he updated the code (version 1.1) to include 2D and 4D variants alongside the 3D implementation, with tweaks to the 3D gradient set for improved quality; these were also posted on the same forum, marking the first public demonstration of the algorithm's dimensional flexibility.[1] The original code was released without a formal license, effectively placing it in the public domain to encourage broad adoption without legal barriers.[13] This permissive approach, combined with the timing amid ongoing concerns over Simplex noise patents, led to quick community uptake; forum feedback highlighted its "really nice patterns" and technical merits, fostering integration into indie game tools and projects for tasks like terrain generation.[1] By 2015, ports and adaptations began appearing in various languages, solidifying its role in open-source procedural workflows.[14] In December 2019, Spencer released OpenSimplex 2, a revised version addressing limitations in higher dimensions and providing variants like OpenSimplex2S (sparse) and OpenSimplex2F (fast) for different optimization trade-offs.[15]Algorithm
Core generation process
The core generation process of OpenSimplex noise transforms an input point into a noise value through a series of geometric and arithmetic operations on a skewed lattice. The input coordinates are first stretched by a factor derived from the lattice geometry, such as adding a stretch offset of (x + y) × -0.211324865405187 in 2D, to align the point with the lattice cells. The negative stretch offset skews the lattice in the opposite direction to standard Simplex, dividing hypercubes into the non-patented pair of simplices while maintaining efficiency. The integer coordinates of the cell origin are then found by flooring these stretched values, and the point is squished back using a factor like 0.366025403784439 to determine its relative position within the cell. This skewing ensures an asymmetric distribution that avoids the patent-encumbered simplex shapes while maintaining efficient higher-dimensional scaling.[1][13] The relative position identifies the contributing vertices within an expanded kernel around the cell, where gradients are evaluated. A key innovation is the larger, asymmetric kernel size compared to Simplex noise—for instance, 4 points in 2D versus Simplex's 3—which enables broader overlap for smoother interpolation and fewer visible artifacts like directional bias. Gradients for these vertices are assigned using a pseudo-random permutation table, seeded to ensure reproducibility; the table indexes into a fixed set of unit-length gradient vectors, akin to Perlin noise but adapted for the skewed lattice. The displacement vector δ from the input point to each vertex is computed, and the raw contribution from a vertex is the dot product of its gradient and δ, often offset by a linear term (e.g., +1) to center the distribution around zero.[1][13] Each contribution is weighted by a distance-based fade function to blend influences smoothly. The fade applies a quintic polynomial to the normalized distance t (where t ∈ [0,1] along the kernel boundary), given byf(t) = 6t^5 - 15t^4 + 10t^3,
which provides a smoothstep-like curve with zero second derivative at the endpoints for artifact-free blending; the full weight for a vertex is then att × f(t), where att = lin_grad + \mathbf{grad} \cdot \delta and t is derived from the Euclidean distance within the kernel. The total noise value is the sum of these weighted contributions across all vertices in the kernel.[1][13] Finally, the summed value is normalized by dividing by a dimension-specific constant (e.g., 47 in 2D) to map the output to the range [-1, 1], ensuring consistent amplitude across evaluations. The seeding mechanism hashes the provided seed to initialize and shuffle the permutation table during construction, guaranteeing deterministic results for the same seed and input while varying patterns across different seeds.[1][13]
Dimensional adaptations
OpenSimplex noise adapts its core algorithm to different dimensions through tailored lattice selections and skew parameters, ensuring reduced directional artifacts and improved isotropy compared to patented Simplex noise. These adaptations involve dimension-specific constants for stretching the input coordinates to align with the simplex lattice and squishing them back for gradient evaluation, while the choice of lattice and kernel size varies to balance visual quality and computational efficiency. The negative stretch ensures patent avoidance by using the alternate simplex orientation.[16] In the 2D variant, a hexagonal lattice is used with a 4-point kernel to provide balanced isotropy suitable for texture generation. The stretch factor is -0.211324865405187 and the squish factor is 0.366025403784439.[16] The 3D variant employs a tetrahedral lattice for smooth gradients in spatial volumes, utilizing a 7-point kernel; this configuration is recommended for terrain generation due to its spatial coherence. The stretch factor is -\frac{1}{6}.[1] For 4D, the algorithm applies a simplicial (pentachoron) lattice, incorporating an 8-point kernel for coherent noise in animations or time-varying fields. The stretch factor is -0.138196601125011 and the squish factor is 0.309016994374947.[16] The following table summarizes the key parameters for the primary dimensional variants:| Dimension | Lattice Type | Kernel Size | Stretch Factor | Squish Factor |
|---|---|---|---|---|
| 2D | Hexagonal | 4 | -0.211324865405187 | 0.366025403784439 |
| 3D | Tetrahedral | 7 | -\frac{1}{6} | \frac{1}{3} |
| 4D | Simplicial (pentachoron) | 8 | -0.138196601125011 | 0.309016994374947 |
Properties
Visual and spectral qualities
OpenSimplex noise produces a smoother visual appearance than traditional Simplex noise, owing to its use of larger contribution kernels that reduce sharp transitions and introduce a subtle blurring effect, resulting in lower contrast and more gradual feature blending.[1] This yields organic patterns in 2D outputs, such as flowing cloud formations or undulating terrain surfaces, while effectively avoiding grid-aligned artifacts common in lattice-based noises.[1] In higher dimensions, OpenSimplex noise exhibits improved isotropy compared to Simplex noise, with reduced directional bias.[1] Kurt Spencer's original evaluations confirmed this through visual inspections and output range analyses, reporting normalized ranges like 0.060 to 0.932 in 3D (from 80,000 samples), indicating consistent isotropy without extreme outliers.[1] When layered via fractal Brownian motion (fBm), OpenSimplex noise supports realistic variation in applications such as planetary surfaces or atmospheric effects.[17] In fBm applications, multiple octaves of OpenSimplex noise are summed with decreasing amplitudes and increasing frequencies, with Spencer's 4D variants showing superior pattern coherence over Simplex noise in such compositions.[1] This enhances its utility for generating visually compelling, non-repetitive textures devoid of low-frequency artifacts.[17]Performance and computational aspects
OpenSimplex noise exhibits increased computational demands compared to classic Simplex noise primarily due to its larger contribution kernels, which evaluate more lattice points per sample—for instance, 9 vertices in 2D versus 3 in Simplex. This results in additional dot products and skewing operations, leading to roughly 50% slower performance in 2D implementations.[1] Benchmarks on modern hardware demonstrate practical efficiency for real-time applications, with 3D OpenSimplex generating approximately 37 million samples per second on an Intel Core i7-7820X CPU clocked at 4.9 GHz using optimized C++ code. In contrast, equivalent 2D Simplex noise achieves about 71 million samples per second under similar conditions, underscoring the performance trade-off while still outperforming classic Perlin noise in higher dimensions, where Perlin's complexity grows exponentially with dimensionality.[18] Memory usage remains efficient, relying on compact permutation tables of around 256 entries for gradient selection, comparable to Simplex noise and suitable for GPU environments without excessive overhead. Vectorized implementations, such as those in GLSL shaders, mitigate costs through SIMD instructions, enabling high-throughput generation in graphics rendering. Seeding via permutation shuffling further optimizes by eliminating per-sample randomness computations.[15] OpenSimplex scales linearly with dimensionality like Simplex noise (O(n^2) operations), avoiding Perlin's O(2^n) scaling, which makes it preferable for 4D applications despite overall higher demands in elevated dimensions; however, 4D evaluations remain computationally intensive, often 2-3 times slower than 2D on the same hardware.[18]Implementations
Software libraries and code
The original implementation of OpenSimplex noise was released in Java by Kurt Spencer in 2014 as a GitHub Gist. An updated version is hosted on GitHub at [15], providing variants for 2D, 3D, and 4D noise generation with support for seeding to ensure reproducible results.[15] This reference implementation serves as the foundation for subsequent ports and includes core functions for evaluating noise at given coordinates, emphasizing gradient-based computation without patent restrictions. Several open-source ports extend the original Java code to other programming languages. In Python, theopensimplex package offers a direct port, enabling easy integration into scripts for procedural generation tasks.[19] For C++, the FastNoiseLite library incorporates OpenSimplex variants, including optimized 2D and 3D modes, suitable for performance-critical applications like real-time rendering.[18] JavaScript implementations, such as the open-simplex-noise npm package, facilitate web-based procedural generation by providing TypeScript-compatible noise evaluation.
Notable integrations appear in game engines. Godot Engine included a built-in OpenSimplexNoise class from version 3.1 (released in 2018) to 3.x, allowing developers to configure parameters like seed, octaves, and period for fractal noise sampling directly in GDScript or C#. In Godot 4.0 (released in 2023) and later, it was replaced by the FastNoiseLite class, which supports OpenSimplex2 variants such as OpenSimplex2F and OpenSimplex2S.[20] For Unity, community-provided C# ports of OpenSimplex noise exist, often shared via GitHub or forums, with some bundled in procedural generation toolkits for terrain and texture synthesis.
Libraries commonly extend basic OpenSimplex evaluation with advanced features, such as fractal modes—including ridged multifractal for sharper ridges and domain warping for twisting input coordinates to create complex patterns. These enhancements build on the core algorithm to support layered noise for natural-looking outputs.
A basic sampling example in Python using the opensimplex library demonstrates simple 2D noise generation:
Similar snippets exist in other languages, typically involving initialization with a seed followed by coordinate-based queries. The OpenSimplex2 repository, last updated in 2022, includes extensions like SuperSimplex (OpenSimplex2S) for improved isotropy in higher dimensions. Forks and ports, including Rust implementations, continue to be developed as of 2025.[15]pythonimport opensimplex # Initialize with a [seed](/page/Seed) for [reproducibility](/page/Reproducibility) opensimplex.seed(1234) # Sample noise at coordinates (x, y) noise_value = opensimplex.noise2(x=1.0, y=2.0) print(noise_value) # Outputs a value between -1 and 1import opensimplex # Initialize with a [seed](/page/Seed) for [reproducibility](/page/Reproducibility) opensimplex.seed(1234) # Sample noise at coordinates (x, y) noise_value = opensimplex.noise2(x=1.0, y=2.0) print(noise_value) # Outputs a value between -1 and 1