diff --git a/src/SimplexNoise.cpp b/src/SimplexNoise.cpp old mode 100644 new mode 100755 index fd60b73..c50b281 --- 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 * @@ -97,7 +95,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, 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 @@ -141,8 +143,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 +174,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 +190,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 +213,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 +255,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 +301,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 +358,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..becfe1b --- a/src/SimplexNoise.h +++ b/src/SimplexNoise.h @@ -9,6 +9,7 @@ */ #pragma once +#include // int32_t/uint8_t #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(uint32_t 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 + 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). 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;