Wednesday 22 February 2017

Procedural Generation Tutorial Brick Noise Texture - Part 3

Procedural Generation Tutorial Brick Noise Texture - Part 3


Before you start you should know these things:
  • Create Texture variables
  • Manipulate textures using SetPixels

You should have gone through and completed all the ‘Checker Board Texture’ and 'Brick Pattern Texture' tutorials before going any further. If you find yourself not understanding some of the terminology or code of the tutorial I would also recommend going through the previous tutorial to get up to speed. I will leave a link to it below to go through at your leisure.

http://joseph-easter.blogspot.com/2017/01/procedural-generation-tutorial-brick_95.html

If you follow this tutorial and find I am moving too fast or if you don’t know the things in the list above, I would recommend getting up to speed and then come back to this tutorial when you are ready.

With this tutorial if you want to convert this into JavaScript by all means do so but it may be easier for you to follow this in C# and stick with the language of the tutorial to make it easier.

PROJECT RESOURCES: At the bottom of the post there is a download link to a zip file. This files includes all files needed to follow Part 3 and the completed project file of Part 3.

In this tutorial series, we will be adding to the brick pattern texture using code by adding noise to the texture image.



In this tutorial series, we will be adding to the brick pattern texture using code by adding noise to the texture image.

We will:
  • Explain the theory
  • Create a static class
  • Learn how to make a hash table function
  • How to create our own 1D noise using the quads 'x' position

Step 1: The theory


In this part we will cover how to make a 1D value noise pattern, dependant on the object’s location in world space and independent of it’s resolution.

In order to create noised based on a value we need to store a hash table of predetermined noise values in a static script. Then we will create a function in the script which returns a value (from the object’s location) and use it to find a value from the hash table and then we will multiply our noise colour by the value noise from the script.

When we create our value noise pattern we will start off by creating a pattern of vertical lines along the ‘x’ axis which will alternate between white and black. After this we will work on increasing the frequency in which they appear. This will make their colour and scale dependant on the hash table of values giving them a seemingly random appearance.

In later parts of the tutorial we will use this technique for 2D and 3D noise values and introduce ‘Perlin’ noise.

Step 2: Establishing the NoiseLibrary Class

The first thing we need to do is create a table of seemingly random values which we can refer to at any time. This will be our library of noise values. It will be a static class and won’t be attached to any game objects, just kept in the ‘Scripts’ folder and merely referenced in our code for it’s functions. The code below is what the entire class is supposed to look like for now (until we add more to it).


Code:

using UnityEngine;

public static class NoiseLibrary()
{
   
}


In this class we need a function that, when we parse it a point in world space, will give us (or return) what looks like a random value based on a calculation and algorithm. For the time being we will make it return the game object’s position on the ‘x’ axis. You can return ‘y’ or ‘z’ if you like, I just chose ‘x’ for simplicity and its the first axis on the list.

Code:


using UnityEngine;

public static class NoiseLibrary()
{
   public static float RandomValue (Vector3 
point)
   {
      return point.x;
   }
}

We can now use this. In the script ‘Noise’ go to the ‘CreateNoisePattern’ function and replace ‘Random.value’ with ‘NoiseLibrary.RandomValue(point)’ so it uses that method instead.


Code:

void CreateNoisePattern()
{
   float normalizer = 1f / resolutionW;
   WorldCoordinates();
   for (int w = 0; w < resolutionW; w++)
   {
      LeftAndRightSides(pointLL, pointLR,
                        pointUL, pointUR, 
                        w, normalizer);
      for (int h = 0; h < resolutionH; h++)
      {
         CalculatePoint(leftSide, rightSide,
                        h, normalizer);
         noiseTexture.SetPixel(w, h, 
              Color.grey * 
              NoiseLibrary.RandomValue(
              point));
      }
   }
   noiseTexture.Apply();
}





At the moment the result isn't particularly pretty or useful to us.

Step 3: Creating a pattern with alternating stripes


With creating a noise pattern, we will start very simple, then add the complexity later as we go on. We will start by creating a pattern of alternating black and white vertical stripes.

This can be done simply by getting the ‘x’ position coordinate value we parse to the ‘RandomValue’ function (or what ever value you parsed to it) and we cast it as an integer (treat it like one) to work with the texture coordinate system. We do this because integers work with textures and the position uses a decimal float number so we need to get rid of the decimal part of it.

After this we return this value as a ‘1’ if the ‘int’ value ‘intX’ is odd and a zero if ‘intX’ is an even number. How can we do this though? One way to do it is when we return the value at the end of the function we could divide the result of ‘intX’ by 2 as a test. The most efficient way to do this is by using the modulus operator instead of the traditional ‘/’ operator. This works by seeing if there is a remainder in the number, and it get’s rid of the remainder turning the result into an integer. Then by using 2 after it, if it’s got a remainder it will convert the value to zero, if not then a 1.

Code:


using UnityEngine;

public static class NoiseLibrary()
{
   public static float RandomValue (Vector3 
point)
   {
      int intX = (int)point.x;
      return intX % 2;
   }
}

Now if we run our code we will notice something. The stripes are one unit by one unit. If we set the quad one unit to the right on the ‘X’ axis (before pressing Play) we will get the alternating colour. When combined with the brick texture we cannot see the pattern. It may be easier for you if you deactivate the ‘CheckerBoardPatternTexture’ script and in the ‘Noise script’ uncomment the ‘Start’ method, make sure ‘GenerateNoiseTexture’ is uncommented and ‘SetNoiseTextureSize’ and ‘CreateNoisePattern’ are commented out. Then in ‘SetNoiseTextureSize’ uncomment the line where we set the ‘noiseTexture’ as the ‘mainTexture’. We will undo this later when we finish.




If we wanted to we could increate the objects scale, but this might be impractical. However, we could decrease the scale of the stripe pattern. We need to add another variable to show how fast we want the pattern to change. We do this by adding a new float called ‘patternAlternationSpeed’ as a parse parameter in the ‘RandomValue’ function, then we need to multiply the point value by the ‘patternAlternationSpeed’ variable using the multiplication incremental operator. This is done just before we cast the ‘x’ position data as an integer.

Code:


using UnityEngine;

public static class NoiseLibrary()
{
   public static float RandomValue (Vector3 
point, float patternAlternationSpeed)
   {
      point *= patternAlternationSpeed;
      int intX = (int)point.x;
      return intX % 2;
   }
}

After we do this we need to go back to the ‘Noise’ script, and add ‘patternAlternationSpeed’ as a public float and assign it ‘1f’ for the time being. This is so we can change it later when we need to. Then parse this variable to the ‘NoiseLibrary.RandomValue’ reference in ‘CreateNoisePattern’ (make it the second parsed variable).

Code:

public float patternAlternationSpeed = 1f;
...
void CreateNoisePattern()
{
   float normalizer = 1f / resolutionW;
   WorldCoordinates();
   for (int w = 0; w < resolutionW; w++)
   {
      LeftAndRightSides(pointLL, pointLR,
                        pointUL, pointUR, 
                        w, normalizer);
      for (int h = 0; h < resolutionH; h++)
      {
         CalculatePoint(leftSide, rightSide,
                        h, normalizer);
         noiseTexture.SetPixel(w, h, 
              Color.grey * 
              NoiseLibrary.RandomValue(
              point, patternAlternationSpeed));
      }
   }
   noiseTexture.Apply();
}




Now, working on the assumption the quad is in the same place, we can guess there are about 2 stripes, at al ‘patternAlternationSpeed’ of five, with one white and one black. However, they are only being shown on the right hand side. This is because the right hand side is seen as the positive side (value wise), so either the values on the left are returning zero values or negative ones being clamped to zero. This is because the modulus operator is working its magic and the remainder is either zero or one.

We could convert the remainder to an absolute value saving us a headache. However, we could use the bit-wise operator instead which is a lot quicker. This works by looking at the ‘int’ as a binary value, and only looks at the least significant bit (and removes everything else). Using this method, it calculates if the number is odd or even.

Code:

using UnityEngine;

public static class NoiseLibrary()
{
   public static float RandomValue (Vector3 
point, float patternAlternationSpeed)
   {
      point *= patternAlternationSpeed;
      int intX = (int)point.x;
      return intX & 2;
   }
}




We now have four stripes with a gat in the middle. A pretty symmetrical pattern with a gap in the middle. This isn’t what we are looking for. It’s happening because on the right side the value are positive and it’s rounding down when removing the decimal parts when casting everything as an ‘int’ value. It is also rounding the values on the left hand side up as they are negative values.

There are two ways to solve this, we could add one when a negative values appears and subtract when a positive is cast. There is a more convenient way to do this though. The method ‘Mathf.FloorToInt’ takes care of this for us when we parse it the requires value. We will use this instead of casting the ‘point.x’ ourselves.

Code:

using UnityEngine;

public static class NoiseLibrary()
{
   public static float RandomValue (Vector3 
point, float patternAlternationSpeed)
   {
      point *= patternAlternationSpeed;
      int intX = Mathf.FloorToInt(point.x);
      return intX & 2;
   }
}



We now have a regular stripe pattern that does not mirror itself.

We have segregated the texture into chunks with a regular pattern that we have created. We can use this to make more interesting patterns, such as lattice noise.

Step 4: Lattice Noise

Lattice noise divides the texture up into regular intervals. To sum it up, it can create a 1D interval, a two dimensional square grid, or even a three dimensional grid.

Even though our pattern is nice to look at, it’s pretty boring for what we need. We need to assign apparently random values to each stripe (in the coordinate system) to we have a variety of colours. Not quite a gradient, but a variety.

We will use a hash function for this purpose. A hash function will convert any one of our lattices, get its coordinate values, and convert to to another value. There are loads of different hash functions we could use for our purposes. For our purposes we will use a permutation array to create a hashing function. This is essentially a table of seemly random values, stored in an array that we can call as a function.

To keep thing straight forward for now, we will only hold a small number of integers. Do this in the ‘NoiseLibrary’ script.

Code:


using UnityEngine;

public static class NoiseLibrary()
{
   private static int [] hashValue = 
   {
     0, 1, 2, 3
   };
   
   public static float RandomValue (Vector3 
point, float patternAlternationSpeed)
   {
      point *= patternAlternationSpeed;
      int intX = Mathf.FloorToInt(point.x);
      return intX & 2;
   }
}

If we continue with this and use it, we will get a value that goes to eight. Considering our colour values only go between 0 to 1, this is too high. We need to normalize it to stay in that boundary when we return the value in ‘RandomValue’ by dividing it by the highest value in the array.

Code:


using UnityEngine;

public static class NoiseLibrary()
{
   private static int [] hashValue = 
   {
     0, 1, 2, 3
   };
   
   public static float RandomValue (Vector3 
point, float patternAlternationSpeed)
   {
      point *= patternAlternationSpeed;
      int intX = Mathf.FloorToInt(point.x);
      return hashValue[intX] / 3f;
   }
}

Before we run our code we need to do one more thing. If we run it, we will get an error because the array only goes between 0 and 3. If one of our values goes below zero or above 9 the index is out of range and has no value to choose. We can fix this by constraining the binary value of ‘intX’ to just the least important digits (three in fact), we index will always wrap back only itself when it needs. E.g. it will cycle back to the start when it reaches the end, or cycle to the end when it goes below a certain value. We do this using the bitwise operator ‘&’.

Code:


using UnityEngine;

public static class NoiseLibrary()
{
   private static int [] hashValue = 
   {
     0, 1, 2, 3
   };
   
   public static float RandomValue (Vector3 
point, float patternAlternationSpeed)
   {
      point *= patternAlternationSpeed;
      int intX = Mathf.FloorToInt(point.x);
      intX &= 3f;
      return hashValue[intX] / 3f;
   }
}




Using the hashValue array function with a ‘patternAlternationSpeed’ of 16.

Step 5: Mixing up the permutation table

Now we can see four colours, even if we increased the number of colours the pattern would be obvious because it repeats regularly. There is a simple way to fix this though. We could try to make it somewhat less blatant by mixing up the values into a different order. We would have the same values but in a different sequence. This is type of array is called a permutation table.

Code:


using UnityEngine;

public static class NoiseLibrary()
{
   private static int [] hashValue = 
   {
     2, 1, 3, 0
   };
   
   public static float RandomValue (Vector3 
point, float patternAlternationSpeed)
   {
      point *= patternAlternationSpeed;
      int intX = Mathf.FloorToInt(point.x);
      intX &= 3f;
      return hashValue[intX] / 3f;
   }
}




Pattern alternation speed is 64.

The pattern looks less regular but it’s still obvious. This is down to how few integers we have in the permutation table (or permutation array). We could easily increase the number of integers to get a more varied result.

Code:


using UnityEngine;

public static class NoiseLibrary()
{
   private static int [] hashValue = 
   {
     2, 1, 3, 0, 5, 6, 4, 7
   };
   
   public static float RandomValue (Vector3 
point, float patternAlternationSpeed)
   {
      point *= patternAlternationSpeed;
      int intX = Mathf.FloorToInt(point.x);
      intX &= 7f;
      return hashValue[intX] / 7f;
   }
}




Resolution 512 by 512, pattern alternation speed of 64.

The pattern is less blatant but still obviously regular when the resolution and the ‘patternAlternationSPeed’ are cranked up. What we are learning here is the more values we have and the more we shuffle the integers around, the less we notice the repeating pattern when the frequency it is repeated is increased or the texture size is increased. We could also add more and different numbers to the mix for a more varied result.

Code:


using UnityEngine;

public static class NoiseLibrary()
{
   private static int [] hashValue = 
   {
     8, 1, 3, 4, 14, 7, 5, 12, 11, 2, 10, 
     13, 0, 9, 6
   };
   
   public static float RandomValue (Vector3 
point, float patternAlternationSpeed)
   {
      point *= patternAlternationSpeed;
      int intX = Mathf.FloorToInt(point.x);
      intX &= 15f;
      return hashValue[intX] / 15f;
   }
}




Resolution 256 by 256, pattern alternation speed of 128.

This hash table will still produce a repeating pattern depending on how many time it’s repeated, but it is a lot less obvious then it was when we started. Also we only notice when we see a big enough sample when it’s repeated a whole lot.

Now if we combine our texture with this noise one we can see the result. Enable the ‘CheckerBoardPatternTexture’ script, and in ‘Noise’ comment out the ‘Start’ method, then in ‘SetNoiseTextureSize’ comment out the line where we assign the ‘noiseTexture’ as our main texture.




Resolution 256 by 256, pattern alternation speed of 64.

Great we know how to make our own noise using a static noise class and how to create a hash table with seemly random values.

We have learnt how to:
  • Create a static class
  • Reference a function from said class
  • Create a simple regular pattern
  • Use lattice noise
  • Create 1D noise Use a hash table/ hash array
  • Control the frequency at which the noise pattern repeats itself
  • What ‘Mathf.FloorToInt’ does and how to use it
  • Use an objects ‘x’ coordinate to generate a value from a hash table
  • Use a bitwise operator ‘&’ to check is a value is odd or even
  • Make an array indexer wrap back on itself if it exceeds hash table length
  • Use modulus operator to find a remainder and how it’s efficient
  • Normalize hash table indexer after
  • Bitwise operator using ‘/’


In Part 4 we will learn how to use the skills learnt here to create 2D noise.