Dev Diary: Creating Tile-Based Texture Maps for Games
One of the key difficulties in creating good looking ground materials is trying to stop visual repetition when seen from a reasonable distance. There are many techniques that can be used to achieve this including detail textures, various methods of blending between textures, and tile-based texture mapping.
In Path of Exile we use tile-based texture mapping extensively to break up the repeating patterns that would otherwise be very unsightly. One problem is that there is very little in the way of information for artists about how to create tile textures. This tutorial is designed to give some insight into the process we use when creating these textures.
In order to make a non-repeating texture, one approach is to use tiles. You can imagine this just like assembling tiles in a 2d game. If we have a set of tiles then we can randomly place them in a grid and we shouldn't ever see any large-scale repetition.
For this to look good we need to make sure that the seams between the tiles are continuous. The problem is that if all tiles have the same repeating edge then you would see a clear square pattern to the texture at the edges where each tile goes to the next one. To break this up we want to have more than one different tile edge that can be connected together.
On the right you can see a set of 16 tiles. Each blue vertical line will tile with any other blue vertical line and any orange vertical line will tile with any other orange vertical line. Similarly for the horizontal lines. By constructing a texture in this way we can get a set of textures that can be tiled for a long time without being able to see any large scale repeating patterns.
Using the GPU its possible from an image like this to generate a very large non-periodic texture. Here is an article about the details of implementing this on the programmer's side.
The remainder of this article describes how an artist can go about creating these textures.
Step 1: Source Textures
The first obvious step is to get a good photo base. I currently get about 90% of all my textures from CGTextures.com.
When I started out, I had this idea that I needed a personal texture library. I soon realised that it takes a lot of time to index and sort a collection that is large enough to be useful. CGTextures does all that for you and has a huge number of good texture photos. There is no need to have a library of your own except for a small number of special things you need or exceptionally cool texture photos that you manage to take yourself.
To the right are the four photographs that were used to create this texture. Generally you would want to avoid stitching several textures like this together, but it can be hard to find photographs that cover enough ground for tile textures. Because you need an above average amount of source ground they must be taken from a higher position than a typical photographer would use.
Step 2: Stitching Together
Here the textures were put together in different layers in one big 1024x1024 map with some basic fixes such as lens correction to remove distortion and some vertical perspective depending on the base texture.
The perfect base texture for a ground texture is taken far away straight onto the surface. As this isn’t always practical, most photos will be taken with the lens close to the ground with some lens distortion. You also often get some vertical perspective as the area photographed is limited by the feet of the person taking it, causing the photographer to take the shot aiming slightly forward rather than straight down. In addition to the lens and perspective correction, hue/saturation, match colour and brightness/contrast were used to make the photos fit better together. Any seams within the texture can be fixed by erasing the upper layer in which they can be seen.
Step 3: Getting Uniform Luminosity
In this step I want to get rid of any large differences in luminosity within the texture to help it repeat better. To the left below you can see the big differences in luminosity if the texture is repeated next to itself.
This is something you can do quite late on a "normal" repeating texture, but here I need to do it before I fix the large number of seams, as a blurred layer above would affect the seams if it's done afterwards instead of before.
The steps taken for this in Photoshop are: merging all to a single layer, duplicating that layer, invert, desaturate, blur and then set to overlay. You can then adjust the layer with brightness and contrast if needed. The overlay texture that is created with this process is shown here in the center.
On the right is the texture tiling with itself after this process. As you can see the texture now has a uniform luminosity and so it tiles much better.
Step 4: Adding Details
Here I brought in another texture I made before to get some interesting grungy damp moss in between the stones. By putting the moss texture on top at 50% opacity, I could manually erase the parts that would cover stone that I wanted seen. I ended up using a layer with 33% opacity and another layer on top set to overlay on 33% opacity. Both of those layers were adjusted with brightness/contrast. In retrospect I probably could have skipped this step as it didn't turn out that well. This type of thing can also be added as a last step with some extra work which will give you two different textures you can use.
Step 5: The Tile Grid
This red and orange grid shows where the texture is supposed to be seamless according to the technical description at the beginning of the article. One pixel on each side of the seam is left empty to make it easy to see exactly where the seam is.
Step 6: Assembling The Seams
One seam section is chosen and copied over so that the blue vertical parallel lines are filled with the same seam part.
It does not really matter from where on the texture you copy the part that is to be used as a seam. To make the seam less noticable it is good to not use anything that would stand out too much on the seam itself. If I had chosen a section that was covered almost entirely by a single stone I would run into problems later. Likewise if I used almost only a dark part between stones it would make the seam noticable at the end.
The same process is then repeated with a different seam for the orange vertical lines and then for the blue and orange horizontal lines.
Here you can see all the seams in a layer above the texture. As you can see there is quite a lot of work required to get the texture to a completely seamless state.
I start out by adding a thin line showing the exact place of the seam. I then start to carefully erase the sides to make it meld in better with the rest of the texture beneath.
Here's the base texture with the seams fixed. The layer containing the seams currently looks like the left bottom image. I also made a few changes to the layer below to stitch it together better.
Final Colour Texture
Step 9: Normal Map
The following steps vary a lot between different textures. For environment normal maps, I use the excellent program CrazyBump.
In order to "help" CrazyBump read some stones as higher up than the soil between them, I have one 50% opacity layer where I paint white on top to make a few chosen stones to come up more. Make sure that you duplicate the white on each repeating place on the seams so that the normal map will work properly as a tile texture too!
On stone floor textures you can use the CrazyBump shape recognition to get stones that are angled in different ways. Here I added a couple of stones from each of the shape recognition directions to make the normal map more interesting.
Some colours and luminosity from the normal map are baked into the colour map. In this case it was two layers. The first layer was set to overlay and 50% opacity with reduced saturation and auto colour balance. The second layer was set to luminosity with 10% opacity and the contrast turned up a lot. I also made a specular map in CrazyBump.
The Final Result
This is the end result of the colour, normal and specular maps viewed in our asset viewer tool. As you can see there are certain parts of the texture that are repeated on the surface. These repetitions are placed randomly, so you can’t discern any repeating patterns even when viewed from far away.
Below you can see the final ground material in the game.