Procedural Generation Tutorial Checker Board Texture - Part 3
The end result of the full tutorial.
At the end of Part 10 we will have produced this (See image 1.0).
Image 1
Before you start you should know these things:
You should have gone through and completed ‘Part 2’ 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_81.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 2
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.
This tutorial will be split up into several parts. In this part we will continue from part two by:
- Changing the number of squares on the texture independent of texture size
- Adjust the size of the blocks dynamically independent of texture size
- Change several pixels in one go using SetPixels32
- Learn how to position said squares correctly using the width and height of the squares
‘SetPixels32’ works like ‘SetPixel’ where we state the ‘X’ and ‘Y’ position, but after this we need to set the width, and height of the block itself. We add these variables after setting the position of the block but before we set the colour. For ease of use we will create and use two int variables ‘blockWidth’ and blockHeight’ and set them to a value of ‘4’.
Code:
public int blockWidth = 4;
public int blockHeight = 4;
void CreatePattern ()
{
for (int i = 0; i < mainTexWidth; i++)
{
for (int j = 0; j < mainTexWidth; j++)
{
if ()
{
mainTexture.SetPixels(i, j,
blockWidth, blockHeight,
Color.black);
}
else
{
mainTexture.SetPixels(i, j,
blockWidth, blockHeight,
Color.white);
}
}
}
...
}
public int blockHeight = 4;
void CreatePattern ()
{
for (int i = 0; i < mainTexWidth; i++)
{
for (int j = 0; j < mainTexWidth; j++)
{
if ()
{
mainTexture.SetPixels(i, j,
blockWidth, blockHeight,
Color.black);
}
else
{
mainTexture.SetPixels(i, j,
blockWidth, blockHeight,
Color.white);
}
}
}
...
}
If we go back to Unity and let the code compile we will get four errors, but two of them are the same because we have repeated part of the code. Out of the errors the ones highlighted are the ones to worry about. This is because the not highlighted ones is saying what line the problem is on and is telling us how the function works but not the specific error. (See figure 1.0)
Figure 1.0
The hilighted ones are telling us what the error actually is. It is because ‘SetPixels’ uses a colour array and not just a single. This seems a little odd but when you know how it works it makes sense. We will go through this in the next step.
Step 3: – Setting the colours using arrays
Code:
public Color32 colour0Arr;
public Color32 colour1Arr;
void CreatePattern ()
{
for (int i = 0; i < mainTexWidth; i++)
{
for (int j = 0; j < mainTexWidth; j++)
{
if ()
{
mainTexture.SetPixels(i, j,
blockWidth, blockHeight,
colour0Arr);
}
else
{
mainTexture.SetPixels(i, j,
blockWidth, blockHeight,
colour1Arr);
}
}
}
...
}
Figure 1.1
We will create a new function below ‘CreatePattern’ called ‘ConvertColourToArray’. The value we parse the function will be used to set it’s new length for both arrays (we will parse ‘blockWidth’ times ‘blockHeight’ to get the value we need). (See Figure 1.2 for the results in the inspector)
Code:
Figure 1.3
Code:
public int squaresX = 4;
public int squaresY = 4;
void CreatePattern ()
{
for (int i = 0; i < squaresX; i++)
{
for (int j = 0; j < squaresY; j++)
{
if ()
{
mainTexture.SetPixels(i, j,
blockWidth, blockHeight,
colour0Arr);
}
else
{
mainTexture.SetPixels(i, j,
blockWidth, blockHeight,
colour1Arr);
}
}
}
...
}
When we compile and run the code, this is what we get. (See figure 1.4)
Figure 1.4
The next things to do are colour the arrays. We could do this manually in the ‘Inspector’ but this would be boring, take too long and defeat the point.
For this reason we will do this using a for loop and create to new variables, which we’ll assign to the colour arrays.
Also when we reference the function, we need to parse it the ‘blockWidth’ multiplied by ‘blockHeight’. This with give us the area of pixels or the total number of pixels per block.
Code:
public Color32 colour0;
public Color32 colour1;
void ConvertColourToArray (int arrSize)
{
colourArr0 = new Color32[arrSize];
colourArr1 = new Color32[arrSize];
for (int i = 0; i < arrSize; i++)
{
colourArr0[i] = color0;
colourArr1[i] = color1;
}
}
Figure 1.5: Far left image has the properties of the far right image. The centre image shows the one square per pixel.
Step 4:- Fixing the spacing
We have this overlapping effect. This is because it is still positioning each square one pixel apart but keeping the dimensions, therefore overlapping them. This is a straight forward fix.
Even though the for loops are counting the squares in each iteration ‘SetPixels32’ Is being parsed ‘i’ and ‘j’ for the starting X and Y position a bit like it’s counting the pixels of the texture. This is why the squares are drawn one pixel apart on the bottom left on the X and Y coordinates. This is also partly why there is the wired over lapping effect with the upper and right most edges and why the squares only appear to work properly at one pixel high and wide or we can’t have the same amount of pixels as squares with larger pixels.
Code:
void CreatePattern ()
{
for (int i = 0; i < squaresX; i++)
{
for (int j = 0; j < squaresY; j++)
{
if ()
{
mainTexture.SetPixels(i *
blockWidth, j *
blockHeight,
blockWidth, blockHeight,
colour0Arr);
}
else
{
mainTexture.SetPixels(i *
blockWidth, j *
blockHeight,
blockWidth, blockHeight,
colour1Arr);
}
}
}
...
}
Figure 1.6
- Use SetPixels to set a large group of pixels at once
- Learnt how to resize and recolour a colour32 array quickly and easily
- How to set block positions that don’t over lap each other using width times the integrator
Thanks for making this tutorial. My confidence for creating texturing using scripting has gone up and has encouraged me to find out more and experiment with what I have learned here. It is good how it is explained in simple terms SetPixels32 works, the benefits of using it as to SetPixels, how to recode how the loops work to adjust the block size regardless of the texture's resolution. I look forward to reading more of your tutorials in future.
ReplyDeleteI enjoyed going through this tutorial. In this part I liked how it leaves in errors and goes into debugging at the right speed. This is good because it teaches how to avoid bad code (and good code used in the wrong places and contexts) and how to fix it correctly. The only improvement I can think of is when an abstract concept is being explained it would be nice to see a diagram or see it being used directly when possible. I apreasheate this can't be done with everything, but it would be nice when possible. Maybe you could do a separate post on said thing e.g. the modulus operator and leave a link to it in the appropriate place so those who want to learn more about it can read up on it. Apart from those suggestions I enjoyed this a lot. Cannot wait to read your other tutorials.
ReplyDeleteThis tutorial wrapped up well. I've learnt a lot from it. The debugging process was straight forward and clearly explained. Reworking the code was simple. The theory at the start was as interesting as it was informative. The post introduces new functions and concepts as they are needed in order to make these digestible. It explains what the differences are and how something is used in different scenarios. I.E. SetPixel vs SetPixels32. One last thing, each post has a quick summary of what will be covered in the post. I like this because it gives you a good idea of what you will be doing before hand. Where needed each step is titled relevant to what it covers. This gives you the gist at a glance before you continue. I would recommend this!
ReplyDeleteplease reupload projekt^^
ReplyDelete