Wednesday 8 March 2017

Procedural Generation Tutorial Brick Noise Texture - Part 5

Procedural Generation Tutorial Brick Noise Texture - Part 5


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_39.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 5 and the completed project file of Part 5.

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
  • Learn to create 3D noise using the quads 'x', 'y' and 'z' position
  • Put one indexer in another to mask the value

Step 1: The theory


In todays tutorial we will cover how to create 3D noise building upon what we have learnt by creating 2D noise. Like Part 3, this part will be very quick and straight forward because we are essentially tweaking what we already have to create a new function. Also we are adding more complexity to it, to make the random noise more convincing, depending on your needs.

We will do this by using the quad’s ‘z’ position value, turn it into an integer value, this add the ‘x’ integer hash value to the ‘y’ integer value. Then add the ‘y’ integer value to the ‘z’ value, offsetting the value when referencing it I the hash table to get the value we need. Essentially this will offset where pattern repeats on the vertical pixels even more and make it less obvious.

You might be asking, ‘if this is so simple, why didn’t you add it to the end of the last tutorial?’. I did this because I wanted to make sure each part was a manageable size, and we can focus of the added complexity more.

Step 2: The basics

The first thing we do is copy and paste the ‘RandomValue2D’ below the original one and change the ‘2D” as the end to a ‘3D’. Then in the ‘Noise’ script change the reference to the method to the name of the static function ‘NoiseLibrary.RandomValue3D’.


Code:


using UnityEngine;

public static class NoiseLibrary()
{
   ...
   public static float RandomValue2D (Vector3 
point, float patternAlternationSpeed)
   {
      point *= patternAlternationSpeed;
      int intX = Mathf.FloorToInt(point.x);
      int intY = Mathf.FloorToInt(point.y);
      intX &= 15f;
      intY &= 15f;
      return hashValue[(hashValue[intX] + intY)
                      & 15f] * (1f / 15f);
   }


   public static float RandomValue3D (Vector3 
point, float patternAlternationSpeed)
   {
      point *= patternAlternationSpeed;
      int intX = Mathf.FloorToInt(point.x);
      int intY = Mathf.FloorToInt(point.y);
      intX &= 15f;
      intY &= 15f;
      return hashValue[(hashValue[intX] + intY)
                      & 15f] * (1f / 15f);

   }
}


The next thing to do is cast the ‘z’ position value to an integer value and called it ‘intZ’.

Code:


using UnityEngine;

public static class NoiseLibrary()
{
   ...
   public static float RandomValue3D (Vector3 
point, float patternAlternationSpeed)
   {
      point *= patternAlternationSpeed;
      int intX = Mathf.FloorToInt(point.x);
      int intY = Mathf.FloorToInt(point.y);
      int intZ = Mathf.FloorToInt(point.z);
      intX &= 15f;
      intY &= 15f;
      intZ &= 15f;
      return hashValue[(hashValue[intX] + intY)
                      & 15f] * (1f / 15f);

   }
}

Step 3: The additional hash value

Now when we return the value we need to add the hashed ‘intY’ value to ‘intZ’. We do this by nesting the current hash indexer in another hash indexer and using the bitwise operator again the the ‘intY’ value.

Code:

using UnityEngine;

public static class NoiseLibrary()
{
   ...
   public static float RandomValue3D (Vector3 
point, float patternAlternationSpeed)
   {
      point *= patternAlternationSpeed;
      int intX = Mathf.FloorToInt(point.x);
      int intY = Mathf.FloorToInt(point.y);
      int intZ = Mathf.FloorToInt(point.z);
      intX &= 15f;
      intY &= 15f;
      intZ &= 15f;
      return hashValue[(hashValue[(
                      hashValue[intX] + intY)
                      & 15f]+ intZ) & 15f] * (1f / 15f));

   }
}

Now you might be thinking why are we using the bitwise operator on ‘intY’ and ‘intZ’ (also called masking in this context), if we end up doing it again when adding it to the hash as a hash value indexer? That’s a good point, because using a bitwise operator (mask) after adding the values in the hash iterator would normally be enough. In the majority of cases the last hash will not occur. We will deal with this later in Part 6 when we get to grips with Perlin noise and masking. If we enter play mode, we can see the result of our code.



Great we know how to make 3D noise now using the ‘z’ position value and mask another indexer for the hash value, and how to nest one indexer in another.

We have learnt how to:
  • Create 3D Noise
  • Put one indexer in another and mask the previous values again

In Part 5 we will learn how to use the skills learnt here to create Perlin Noise, create a mask variable meaning we don’t need to change the length manually when masking. We will also learn how to avoid the need for masking the values a second time in the hash table indexer.


No comments:

Post a Comment