Perlin Noise breaks if scale is a whole number [FIXED!]

Updated on July 19, 2019 in [A] C# .Net
Share on Facebook0Tweet about this on TwitterShare on Google+0Share on Reddit0
2 on July 16, 2019

I’m generating a texture using perlin noise with 3 seeds for HSV colors.

 

It use to work fine, I’m not sure when this started happening, but now whenever the scale for the perlin is a whole number (1, 5, 9001), it doesn’t necessarily break, but the entire texture is a green/blue, which is wrong.

 

If you give it decimal numbers though (0.1, 5.5, 900.1) it works as expected (kinda, depends on the texture size). See images linked here -> https://imgur.com/a/ZU0RYPd

 

As you can see, 0.1 and 1.1 work as expected, but 1 causes it to be smooth with no noise.

 

 

 

Here is the function I use to get the perlin value

 

 
float GetPerlinNoiseValue(float xCoord, float yCoord, string seed = "", float scale = 1f, float valueMod = 1f)
 { 
     float seedHash = seed.GetHashCode() >> (seed.Length * seed.Length);
 
 
 
     xCoord += seedHash;
 
     yCoord += seedHash;
 
 
 
     xCoord *= scale;
 
     yCoord *= scale;
 
 
 
     return Mathf.Clamp01(Mathf.PerlinNoise(xCoord, yCoord)) * valueMod;
 }

 

I have tried removing the “*= scale” and it acts the same as if it were a whole number.

 

 

 

Here is where I use it to generate the texture.

 

 
private Texture2D GeneratePerlinTexture(string seed, float scale = 1f)
 
{
 
     Texture2D perlinTexture = new Texture2D(cols, rows);
 
     Color[] pixels = new Color[perlinTexture.width * perlinTexture.height];
 
 
 
     seed = seed.GetHashCode().ToString();
 
     int seedLength = seed.Length;
 
 
 
     for(int i = 0; i < perlinTexture.height; i++)
 
     {
 
          for(int j = 0; j < perlinTexture.width; j++)
 
          {
 
               float xCoord = j;
 
               float yCoord = i;
 
 
 
               float sampleH = GetPerlinNoiseValue(xCoord, yCoord, seed.Substring(0, seedLength / 2), scale);
 
               float sampleS = GetPerlinNoiseValue(xCoord, yCoord, seed.Substring(seedLength / 4, seedLength / 2), scale);
 
               float sampleV = GetPerlinNoiseValue(xCoord, yCoord, seed.Substring(seedLength / 2, seedLength / 2), scale);
 
 
 
               pixels[(i * perlinTexture.width) + j] = Color.HSVToRGB(sampleH, sampleS, sampleV);
 
          }
 
     }
 
 
 
     perlinTexture.SetPixels(pixels);
 
     perlinTexture.Apply();
 
 
 
     Renderer r = GetComponent();
 
     if(r != null)
 
          r.material.mainTexture = perlinTexture;
 
 
 
     return perlinTexture;
 }

 

 

 

It’s not just a graphical thing either, all of the perlin values are actually the same

 

Like I said, it only breaks when it’s a whole number, and removing the scale all together just makes it break all the time. It doesn’t matter what the seed is, or how long the seed is. I have no Idea why this is happening, so any input would be greatly appreciated.

  • Liked by
Reply
0 on July 18, 2019

Update: Ok, so after some more testing and changing the order of some of the math, it still does the same thing with whole numbers, but you can see it happening as you approach them.

So I don’t think any thing is “broken” or the math is wrong, but if someone who knows perlin and hashing a bit better could explain why this is the case, I would be very appreciative.

 

Thanks.

  • Liked by
Reply
Cancel
0 on July 19, 2019

Update: I fixed it. I rewatched Brackey’s videos reguarding Perlin, and noticed he was dividing the x and y coordinates by the grid x and y size.

It works exactly as expected now, but if anyone knows why only whole number were braking it, I’d still be interested in learning why.

 

Here is the fixed code too, if anyone wants it:

float GetPerlinNoiseValue(float xCoord, float yCoord, string seed = "", float scale = 1f, float valueMod = 1f)
{
    float seedHash = (float)(seed.GetHashCode() % (seed.Length));
 
    xCoord /= cols;
    yCoord /= rows;
 
    xCoord *= scale;
    yCoord *= scale;
 
    xCoord += seedHash;
    yCoord += seedHash;
 
    return Mathf.Clamp01(Mathf.PerlinNoise(xCoord, yCoord)) * valueMod;
 }
  • Liked by
Reply
Cancel