Wednesday 28 December 2016

Procedural Generation Tutorial Checker Board Texture - Part 2

Procedural Generation Tutorial Checker Board Texture - Part 2



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:

You should have gone through and completed ‘Part 1’ of this tutorial 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.



https://joseph-easter.blogspot.com/2016/12/procedural-generation-tutorial-checker.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.

Links to Parts 1 - 3 of this tutorial series:

Part 1

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



This tutorial will be split up into several parts. In this part we will continue from part one by:
  • Display our new texture variable on the Quad by assigning to the object material

Step 1:

In ‘Part 1’ we learnt how to create the texture variable, sort through each pixel to create a simple pattern and how to assign the changes to the texture. This is ok, but we can’t see the texture on the object yet. This is because it hasn’t been assigned to the current game object’s material. Because we create the texture during run time it does not exist outside of ‘Play Mode’, and during ‘Play Mode’ you cannot assign the texture to the material manually through the inspector for testing purposes. (Note: you can save image textures created during runtime as a PNG, but it’s not covered in this tutorial. If you would like a tutorial on it, leave a comment below or send me an email).

In order to assign our new texture to the current object’s material during run time we need to assign it via code. Doing this only requires one line of code, and it looks quite daunting but it’s quite simple. At the end of the ‘CreatePattern’ method after we apply the changes to the texture, we call ‘GetComponent’ and ask for the renderer because the texture needs to be rendered by the engine. Then we ask for the renderer’s material properties, then we ask for the ‘mainTexture’ variable of the material. We ask for main texture because Unity5’s new Materials possess numerous texture types, such as normal maps, bump maps and so on. The main texture distinguishes the main pattern that player will see from any other fancy texture effects. Then we assign our local ‘mainTexture’ variable to the object’s mainTexture variable.


Code:


void CreatePattern ()
{
    ...
    mainTexture.Apply();
    GetComponent<Renderer().material.mainTextur
                            = mainTexture;
}


You may be wondering why I have put this line here instead of create a separate function for it. I have done this for the time being because the function is fairly single purpose and straight forward to understand for now. Also the function it only about 20 lines long at the moment and we only have one texture to assign so it keeps things fairly compact. If we were creating multiple textures for a single game object, then I would create an array and a separate function for it.

Now when we click ‘Play’ we can see the results. (Note: If you can’t see the texture and you have followed all the steps, check there is a directional light in the scene, pointing in the right direction and make sure it’s enabled). (See figure 1.0)

Figure 1.0: far left is 2 by 2, middle left 4 by 4, middle right 8 by 8, far right, 16 by 16.

Step 2:

This texture is good but we can improve it. I part 3 we will change how the texture is drawn and make it more flexible to work with. For now, though we will work on improving what we have b altering a few of the texture modes.

At the moment our texture has some weird edges. As we have a low resolution to make the current pattern visible we can see this strange artifact and it’s more visible. Around the edges the colours appear to have blurred into each from the opposite side. This is because the textures are set to repeat themselves as their default wrap mode. The way to fix this is by having the ‘CreatePattern’ method set the texture’s ‘wrapMode’ to ‘Clamp’ therefore clamping the colours at the edges. We do this my referencing the ‘wrapMode’ property of our texture and assigning it the ‘Clamp’ setting of ‘TextureWrapMode’. (See figure 1.1 for results)

Code:


void CreatePattern ()
{
    ...
    mainTexture.Apply();
    GetComponent<Renderer().material.mainTextur
                            = mainTexture;
    mainTexture.wrapMode = TextureWrapMode.Clamp;
}

Figure 1.1


In the next step we’ll work on making the texture less blurry.


Step 3:

At the moment our texture is still a little blurry even thought our texture resolution is low. This is down to the texture’s filtering mode, by default it’s set to bilinear causing a smooth colour transition. It works in a similar way to the ‘Lerp’ function. With two neighbouring pixels it tries to interpolate the colour in between them.

The fix for this is quite simple. We change the textures ‘filterMode’ property to ‘Point’ by assigning it’s ‘filterMode’ to ‘FilterMode.Point’. (See figure 1.2).

Code:


void CreatePattern ()
{
    ...
    mainTexture.Apply();
   GetComponent<Renderer().material.mainTextur
                         = mainTexture;
    mainTexture.wrapMode =
                       TextureWrapMode.Clamp;
    mainTexture.filterMode = FilterMode.Point;
}

Figure 1.2


The way it does this is with every pixel that’s rendered, this mode chooses the colour of the current pixel it is covering.

Great, part two is finished.

We have learnt how to:


  • Assign a texture to our object’s material via code using it’s ‘mainTexture’ variable
  • Prevent edges of a texture from repeating itself by setting it’s wrap mode to clamp
  • Make the texture look sharper by changing its filter mode to ‘Point’ from bilinear


In Part 3 we will cover how to make our texture more flexible by:

  • Using the block variant of SetPixel called SetPixels32
  • Have the block sizes change dynamically instead of colouring each pixel


Download resources and project files.