From 8c6ef5c0cdf3a65e39ffa43f6ebe67cabb3d94b8 Mon Sep 17 00:00:00 2001 From: Aaron Kriegman Date: Tue, 7 Apr 2020 19:36:12 -0400 Subject: [PATCH 1/4] Fixed bug in 2D gradient, added seeding --- src/SimplexNoise.cpp | 35 ++++++++++++++++++++--------------- src/SimplexNoise.h | 12 ++++++++---- 2 files changed, 28 insertions(+), 19 deletions(-) mode change 100644 => 100755 src/SimplexNoise.cpp mode change 100644 => 100755 src/SimplexNoise.h diff --git a/src/SimplexNoise.cpp b/src/SimplexNoise.cpp old mode 100644 new mode 100755 index fd60b73..f5064c4 --- a/src/SimplexNoise.cpp +++ b/src/SimplexNoise.cpp @@ -23,6 +23,7 @@ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt * or copy at http://opensource.org/licenses/MIT) */ +// Minor changes from Aaron Kriegman #include "SimplexNoise.h" @@ -97,7 +98,11 @@ static const uint8_t perm[256] = { * @return 8-bits hashed value */ static inline uint8_t hash(int32_t i) { - return perm[static_cast(i)]; + return perm[static_cast(i)] ^ perm[static_cast(i >> 8)]; +} + +static inline uint8_t hash(int32_t i, uint8_t seed) { + return perm[static_cast(i)] ^ perm[static_cast(i >> 8)] ^ seed; } /* NOTE Gradient table to test if lookup-table are more efficient than calculs @@ -141,8 +146,8 @@ static float grad(int32_t hash, float x) { */ static float grad(int32_t hash, float x, float y) { const int32_t h = hash & 0x3F; // Convert low 3 bits of hash code - const float u = h < 4 ? x : y; // into 8 simple gradient directions, - const float v = h < 4 ? y : x; + const float u = h & 4 ? x : y; // into 8 simple gradient directions, + const float v = h & 4 ? y : x; return ((h & 1) ? -u : u) + ((h & 2) ? -2.0f * v : 2.0f * v); // and compute the dot product with (x,y). } @@ -172,7 +177,7 @@ static float grad(int32_t hash, float x, float y, float z) { * * @return Noise value in the range[-1; 1], value of 0 on all integer coordinates. */ -float SimplexNoise::noise(float x) { +float SimplexNoise::noise(float x) const { float n0, n1; // Noise contributions from the two "corners" // No need to skew the input space in 1D @@ -188,13 +193,13 @@ float SimplexNoise::noise(float x) { float t0 = 1.0f - x0*x0; // if(t0 < 0.0f) t0 = 0.0f; // not possible t0 *= t0; - n0 = t0 * t0 * grad(hash(i0), x0); + n0 = t0 * t0 * grad(hash(i0, mSeed), x0); // Calculate the contribution from the second corner float t1 = 1.0f - x1*x1; // if(t1 < 0.0f) t1 = 0.0f; // not possible t1 *= t1; - n1 = t1 * t1 * grad(hash(i1), x1); + n1 = t1 * t1 * grad(hash(i1, mSeed), x1); // The maximum value of this noise is 8*(3/4)^4 = 2.53125 // A factor of 0.395 scales to fit exactly within [-1,1] @@ -211,7 +216,7 @@ float SimplexNoise::noise(float x) { * * @return Noise value in the range[-1; 1], value of 0 on all integer coordinates. */ -float SimplexNoise::noise(float x, float y) { +float SimplexNoise::noise(float x, float y) const { float n0, n1, n2; // Noise contributions from the three corners // Skewing/Unskewing factors for 2D @@ -253,9 +258,9 @@ float SimplexNoise::noise(float x, float y) { const float y2 = y0 - 1.0f + 2.0f * G2; // Work out the hashed gradient indices of the three simplex corners - const int gi0 = hash(i + hash(j)); - const int gi1 = hash(i + i1 + hash(j + j1)); - const int gi2 = hash(i + 1 + hash(j + 1)); + const int gi0 = hash(i + hash(j, mSeed), mSeed >> 8); + const int gi1 = hash(i + i1 + hash(j + j1, mSeed), mSeed >> 8); + const int gi2 = hash(i + 1 + hash(j + 1, mSeed), mSeed >> 8); // Calculate the contribution from the first corner float t0 = 0.5f - x0*x0 - y0*y0; @@ -299,7 +304,7 @@ float SimplexNoise::noise(float x, float y) { * * @return Noise value in the range[-1; 1], value of 0 on all integer coordinates. */ -float SimplexNoise::noise(float x, float y, float z) { +float SimplexNoise::noise(float x, float y, float z) const { float n0, n1, n2, n3; // Noise contributions from the four corners // Skewing/Unskewing factors for 3D @@ -356,10 +361,10 @@ float SimplexNoise::noise(float x, float y, float z) { float z3 = z0 - 1.0f + 3.0f * G3; // Work out the hashed gradient indices of the four simplex corners - int gi0 = hash(i + hash(j + hash(k))); - int gi1 = hash(i + i1 + hash(j + j1 + hash(k + k1))); - int gi2 = hash(i + i2 + hash(j + j2 + hash(k + k2))); - int gi3 = hash(i + 1 + hash(j + 1 + hash(k + 1))); + int gi0 = hash(i + hash(j + hash(k, mSeed), mSeed >> 8)); + int gi1 = hash(i + i1 + hash(j + j1 + hash(k + k1, mSeed), mSeed >> 8)); + int gi2 = hash(i + i2 + hash(j + j2 + hash(k + k2, mSeed), mSeed >> 8)); + int gi3 = hash(i + 1 + hash(j + 1 + hash(k + 1, mSeed), mSeed >> 8)); // Calculate the contribution from the four corners float t0 = 0.6f - x0*x0 - y0*y0 - z0*z0; diff --git a/src/SimplexNoise.h b/src/SimplexNoise.h old mode 100644 new mode 100755 index 4cecaed..e4ea466 --- a/src/SimplexNoise.h +++ b/src/SimplexNoise.h @@ -7,6 +7,7 @@ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt * or copy at http://opensource.org/licenses/MIT) */ +// Minor changes from Aaron Kriegman #pragma once #include // size_t @@ -17,11 +18,11 @@ class SimplexNoise { public: // 1D Perlin simplex noise - static float noise(float x); + float noise(float x) const; // 2D Perlin simplex noise - static float noise(float x, float y); + float noise(float x, float y) const; // 3D Perlin simplex noise - static float noise(float x, float y, float z); + float noise(float x, float y, float z) const; // Fractal/Fractional Brownian Motion (fBm) noise summation float fractal(size_t octaves, float x) const; @@ -36,10 +37,12 @@ class SimplexNoise { * @param[in] lacunarity Lacunarity specifies the frequency multiplier between successive octaves (default to 2.0). * @param[in] persistence Persistence is the loss of amplitude between successive octaves (usually 1/lacunarity) */ - explicit SimplexNoise(float frequency = 1.0f, + explicit SimplexNoise(unsigned int seed = 0, + float frequency = 1.0f, float amplitude = 1.0f, float lacunarity = 2.0f, float persistence = 0.5f) : + mSeed(seed), mFrequency(frequency), mAmplitude(amplitude), mLacunarity(lacunarity), @@ -48,6 +51,7 @@ class SimplexNoise { private: // Parameters of Fractional Brownian Motion (fBm) : sum of N "octaves" of noise + unsigned int mSeed; float mFrequency; ///< Frequency ("width") of the first octave of noise (default to 1.0) float mAmplitude; ///< Amplitude ("height") of the first octave of noise (default to 1.0) float mLacunarity; ///< Lacunarity specifies the frequency multiplier between successive octaves (default to 2.0). From 90b9a7359a9949db32696e2fb792ac5cf270b24f Mon Sep 17 00:00:00 2001 From: Aaron Kriegman Date: Tue, 7 Apr 2020 19:50:45 -0400 Subject: [PATCH 2/4] Fixed bug in 2D gradient --- src/SimplexNoise.cpp | 1 - src/SimplexNoise.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/SimplexNoise.cpp b/src/SimplexNoise.cpp index f5064c4..1dbde22 100755 --- a/src/SimplexNoise.cpp +++ b/src/SimplexNoise.cpp @@ -23,7 +23,6 @@ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt * or copy at http://opensource.org/licenses/MIT) */ -// Minor changes from Aaron Kriegman #include "SimplexNoise.h" diff --git a/src/SimplexNoise.h b/src/SimplexNoise.h index e4ea466..94e91e2 100755 --- a/src/SimplexNoise.h +++ b/src/SimplexNoise.h @@ -7,7 +7,7 @@ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt * or copy at http://opensource.org/licenses/MIT) */ -// Minor changes from Aaron Kriegman + #pragma once #include // size_t From 0c35255e07861451f8e35b9e6c3638f80b56e76e Mon Sep 17 00:00:00 2001 From: Aaron Kriegman Date: Wed, 8 Apr 2020 13:09:20 -0400 Subject: [PATCH 3/4] Fixed casting issue --- src/SimplexNoise.cpp | 6 ++---- src/SimplexNoise.h | 6 +++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/SimplexNoise.cpp b/src/SimplexNoise.cpp index 1dbde22..c50b281 100755 --- a/src/SimplexNoise.cpp +++ b/src/SimplexNoise.cpp @@ -26,8 +26,6 @@ #include "SimplexNoise.h" -#include // int32_t/uint8_t - /** * Computes the largest integer value not greater than the float one * @@ -100,8 +98,8 @@ static inline uint8_t hash(int32_t i) { return perm[static_cast(i)] ^ perm[static_cast(i >> 8)]; } -static inline uint8_t hash(int32_t i, uint8_t seed) { - return perm[static_cast(i)] ^ perm[static_cast(i >> 8)] ^ seed; +static inline uint8_t hash(int32_t i, uint32_t seed) { + return perm[static_cast(i)] ^ perm[static_cast(i >> 8)] ^ static_cast(seed); } /* NOTE Gradient table to test if lookup-table are more efficient than calculs diff --git a/src/SimplexNoise.h b/src/SimplexNoise.h index 94e91e2..becfe1b 100755 --- a/src/SimplexNoise.h +++ b/src/SimplexNoise.h @@ -7,9 +7,9 @@ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt * or copy at http://opensource.org/licenses/MIT) */ - #pragma once +#include // int32_t/uint8_t #include // size_t /** @@ -37,7 +37,7 @@ class SimplexNoise { * @param[in] lacunarity Lacunarity specifies the frequency multiplier between successive octaves (default to 2.0). * @param[in] persistence Persistence is the loss of amplitude between successive octaves (usually 1/lacunarity) */ - explicit SimplexNoise(unsigned int seed = 0, + explicit SimplexNoise(uint32_t seed = 0, float frequency = 1.0f, float amplitude = 1.0f, float lacunarity = 2.0f, @@ -51,7 +51,7 @@ class SimplexNoise { private: // Parameters of Fractional Brownian Motion (fBm) : sum of N "octaves" of noise - unsigned int mSeed; + uint32_t mSeed; float mFrequency; ///< Frequency ("width") of the first octave of noise (default to 1.0) float mAmplitude; ///< Amplitude ("height") of the first octave of noise (default to 1.0) float mLacunarity; ///< Lacunarity specifies the frequency multiplier between successive octaves (default to 2.0). From 67b55a0df0ab18b23f1d5f91f7339f128787840f Mon Sep 17 00:00:00 2001 From: Aaron Kriegman Date: Wed, 8 Apr 2020 13:17:04 -0400 Subject: [PATCH 4/4] Changed test because noise is no longer static --- test/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/main.cpp b/test/main.cpp index c0129ab..4ad5ddf 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -11,7 +11,7 @@ int main() { float x = 0.123f; // Define a float coordinate - float noise = SimplexNoise::noise(x); // Get the noise value for the coordinate + float noise = SimplexNoise().noise(x); // Get the noise value for the coordinate (void)noise; return 0;