Wednesday 21 December 2016

Procedural Generation Tutorial Checker Board Texture - Part 1

Procedural Generation Tutorial Checker Board Texture - Part 1


The end result of the full tutorial.



At the end of Part 10 we will have produced this (See image 1).
Image 1


Before you start you should know these things:
  • Be competent with Unity (at least know the basics) 
  • Know the basics of scripting in Unity using C# 

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.


Links to Parts 2 - 3 of this tutorial series:

Part 2

Part 3

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

This tutorial will be split up into several parts. In this part we will work on getting the basics done:

  • Setting up the scene with a basic quad visible to the player


Step 1:

After you have set up a new project and created a new Scene in Unity, create a new ‘Quad’ in the scene view and change its rotation so it's facing the player. You can do this through the ‘Create’ menu in the tool bar. Now rename this to ‘Checker Board Pattern’ in the inspector. (See figure 1.0)

Figure 1.0

After this create a new folder ‘Scripts’, then create a new script inside that folder called ‘CheckerBoardPatternTexture’. When this is done add the script to the ‘CheckerBoardPattern’ game object.

Step 2:

Before we write a line of code we need to do some theory. To create a texture through code the first thing we will need is a texture. We can create a texture variable easily though code, but we’ll also want to set the X and Y dimensions of the texture. If we do not give it pixel height and width values, it’s effectively null and nothing can be drawn to it.

Open the script in ‘MonoDevelop’ or Visual Studio or your preferred editor. At the top of the script above the ‘Start’ function we will need to add a few public variables. First we need to create our main texture ‘mainBrickTexture’, then we add ‘mainBrickTexWidth’ and ‘mainBrickTexHeight’. The main texture will be public for now so we can more instantly see the changes we are applying to it in the ‘Inspector’.

Code:

public Texture2D mainTexture;

public int mainTexWidth;
public int mainTexHeight;


After savings, we go back to Unity and let the code compile. If we look in the inspector we see three new variables.

Figure 1.1

At the moment the texture variable is blank or null because we have not added any settings to it yet. To make it usable, add the number ‘256’ into both ‘mainTexWidth’ and ‘mainTexHeight’ variables in the inspector.

Now we need to assign the ‘mainTexWidth’ and ‘mainTexHeight’ variables to the texture variable to set the width and height of it. (You might be thinking why not set it straight through code? Well because we are procedurally generating this you may want to more quickly change part of the texture. Using this method helps us dynamically test our settings before hard coding them).

To do this we will create a new method called ‘SetMainTextureSize()’ just below ‘Start’ and add a reference to it in the ‘Start’ method. (See figure 1.2).




Code:

void Start ()
{
      SetMainTextureSize();
}

void SetMainTextureSize()
{
      mainTexture = new Texture2D(mainTexWidth, mainTexHeight);
}

Figure 1.2


What we have just done here is set the ‘mainTexture’ width and height by creating a new temp texture. In other words, we have replaced the old variables of the texture with new ones making it a new texture2D variable. Another way of looking at it is like if we set the position of an object through code, we assign the transform variable to a new transform position.

Great, we have the texture properties stored locally so they can be dynamically set. Not only that, the texture will be created, and it’s ‘width’ and ‘height ‘pixel sizes will be set on the first frame of the scene.

Step 3:

In this step we will implement the logic to sort through each pixel of the texture and alternate between two different colours using the modulus operator (%).

There are two ways we can do this, either sort through each pixel one by one, or by colouring large blocks of pixels. We will quickly go through the first one.

First we need to sort through each pixel of the texture. The best way to do this is to create a new method called ‘CreatePattern’ and add a reference to it in ‘Start’ after the first method reference. In this method create two for loops, one nested in the other, one going through the X and one through the Y axis. Therefore, in the conditional statement of the for loops, ‘i’ will stop when it reaches the same value as ‘mainTexWidth’ and ‘j’ when it reaches the same value as ‘mainTexHeight’.

Code:

void Start ()
{
    SetMainTextureSize();
    CreatePattern();
}
...
void CreatePattern()
{
    for (int i = 0; i < mainTexWidth; i++)
    {
        for (int i = 0; i < mainTexWidth; i++)
        {
            
        }
    }
}

The next thing we need to do it set the pixel colour. The way to do this is to find out if ‘i’ and ‘j’ are either both even or odd numbers, or if one is even and the other is odd. Because this is a square texture and ‘i’ and ‘j’ are tracking the pixels’ position, this will be relatively easy.

We do this by adding ‘i’ and ‘j’ together and put them in a pair of brackets. Then we use the modulus operator ‘%’  followed by a value, (we will put a ‘2’ there), then put this equation along with the last one in brackets. Basically it maps number one (on the left of the operator) which is the result of the brackets to number two (on the right of the operator), then divides number one by number two. It returns the remainder of number one (assuming it is an absolute value). If the equation doesn’t equal a whole number, it returns a zero, if it does, it equals the value set. After this we check if the whole equation equals zero or 1 (you can set whatever int value you like, as long as it is half of the first one after the ‘%’). If it equals zero, it will set as a certain colour, if it equals 1 then it will set the pixel as a different colour.

Code:

void CreatePattern()
{
    for (int i = 0; i < mainTexWidth; i++)
    {
        for (int i = 0; i < mainTexWidth; i++)
        {
            if (((i + j)%2)==1)
            {
            
            }
            else
            {
            
            }
        }
    }
}

In the next step we will set the colour of those pixel and apply it to the texture variable.

Step 4:

The next thing to do is set each pixel to one of two colours based on the if statement from ‘Step 3’. First we need to reverence our texture variable, then reference ‘Set’Pixel’ and parse it the pixel location then give it a colour to set it to. Referencing the specific pixel is easy, we parse it ‘i’ and ‘j’ for the ‘X’ and ‘Y’ position. Then to say which colour we want it to be there are a few routes to this. For the time being we will use ‘Color.black’ and ‘Color.white’. These are short cuts to basic colours from Unity’s code library.


Code:

void CreatePattern()
{
    for (int i = 0; i < mainTexWidth; i++)
    {
        for (int i = 0; i < mainTexWidth; i++)
        {
            if (((i + j)%2)==1)
            {
                mainTexture.SetPixel(i, j, Color.black);
            }
            else
            {
                mainTexture.SetPixel(i, j, Color.white);
            }
        }
    }
}


Now last but not least, we need to apply all of these changes to the texture variable itself. At the bottom of the for loop we will reference the texture again but reference ‘Apply()’. This applies all of the recent changes to the texture. (See figure 1.3).

Code:

void CreatePattern()
{
    for (int i = 0; i < mainTexWidth; i++)
    {
        ...
    }
    mainTexture.Apply();
}


Figure 1.3: I set the resolution to '2' by '2' for this example because it's easier to see.

Great, part one is finished. We have done some of the ground work.

We have learnt:



  • Set up the scene with a basic quad
  • Create a texture variable and set it size dynamically
  • How to sort through every pixel quickly using nested for loops
  • What the modulus operator is and how to use it to alternate between two values
  • How to colour pixels individually using ‘SetPixel’ and the colour short cut ‘Color.black’
  • How to apply changes made to a texture variable



In Part 2 we will cover how to set the new texture to the current material of the object through code. Click here for Part 2



4 comments:

  1. Thanks for writing this tutorial. I am interested in procedural textures as I am not an artist and wondered how to make textures through code as I have never done it before. How you explained SetPixel works and sorting through each pixel using two for loops is very clear and easy to understand for a total beginner on procedural texturing. I look forward to reading part 2!

    ReplyDelete
  2. This tutorial is laid out well, at the top I can see what I will be making at the end of it and at the end of the individual part. Each step is clearly labeled to break things up and each explanation is illustrated with an example when needed so you have a clear idea of what is going on. At the top it is explained what the reader needs to know before they start so they do not get confused and turn off. At the end there is a quick summary of what has been covered and what will be covered in the next part. The explanations are clear and concise for a beginner in this area. The code examples are formatted well and work as expected. Using a different font that is easy to read as well as a different colour also help out telling which is an example and what is text. It is nice to see a link for the next part of this series making it easy for the reader if they read all parts in one go. Plus there is a link to download the project at the bottom which contains all the resources covered in the tutorial. If you have gone wrong somewhere it is good to see the project in action and compare it with your own scripts. Good work. Can't wait for part 2.

    ReplyDelete
  3. One last thing. The modulus operator is explained well for a complex mathematic operation. It was concise and does not bog the reader down in too much detail.

    ReplyDelete
  4. Thanks for writing this. I have been struggling for some time and didn't know where to start with regards to creating textures with code. This has been really helpful. I now know how to create textures and modify them in scripts. You explained the algorithms pretty well, specifically how to sort through the pixels using two for loops. Also, you explained how the modulus operator worked well, you didn't over complicated it or bog us down in detail. Just what we need at the moment. It would be cool if you did a more detailed post on it for those who want to know more about it or for a later tutorial. The only criticism is it would be nice if there were an image illustrating the modulus operator and how it works. For those of us who aren't great at math, seeing what it does visually would be a nice enhancement. That's it.

    Oh and I nearly forgot. I like how in the code formatting with the examples, when you add or modify some existing code you put the font in bold. When there is a lot of code already there, I would get very confused. This helped me distinguish between existing code and modifications. Having the examples clearly labeled, laid out, in a different font and colour is a nice touch. It helped me understand which bit was code and which was text easily.

    ReplyDelete