A (new) way to create large area retro textures

One of the biggest and most frustrating struggles I’ve been having with developing my techniques for creating the assets for Iridium Moons since the very start was how to make the kinds of textures that I want for the game. There are loads of guides on “How to make PS1 textures”, but none of them really do the specific kind of texture I am having in mind, or really work in a way that I think makes everything vastly more complicated and inefficient than it should be. I had a pretty good idea for what I wanted to do, but not knowing the technical terms for the various steps I had in mind made it extremely difficult to search for information on how to do them with Gimp and Blender. But every time I spend half a day trying and failing to find the answers I was looking for, I did pick up a few pieces of knowledge about image editing and the functions of these two programs, which now finally have given me the ability to actually develop the whole process to get what I want by myself.

There are three different sections on making late 90s pixelated textures that I am going to cover here: Pixelation noise in hand-drawn textures in Gimp, converting PBR materials to single image files in Blender, and breaking up repeating texture patterns of small textures on large environment surfaces.

Adding Pixelation Noise

This one is super easy, and it’s also just dumb how long it took me to get here.

When you draw a low resolution texture with few colors by hand, it can often look very flat and dull. One thing that makes the textures on 3D models on PlayStation and early PC games with texture mapping look the way that they do is that you almost never have two pixels of identical colors sitting next to each other. It’s also very prominent in Minecraft and other games that replicate its style. It’s what causes the graininess in the textures that basically defined this visual style.

Really all that is needed is a way to randomly change the Hue (color), the Value (brightness), or the Saturation (greyness) of every pixel on the texture by just a little bit. Over the past half year, I’ve come across numerous guides that explain how to do this by creating shaders in Blender that go over the source texture, or how to make custom grunge brushes for Gimp, and all of them either were way more complicated than it has any right to be, left out some crucial step on where to get a necessary resource, or just didn’t look right.

But somehow, and it is really completely inexplicable how such a thing could even be possibly, none of these literally dozens of guides ever mentioned once that Gimp has an HSV Noise filter. Which isn’t under Filters > Render > Noise like all the other noise filters that regularly come up in instructions, but under Filters > Noise.

It’s not really hidden, but all the instructions using Solid Noise, Perlin Noise, or Plasma Noise got me locked into that area of the Filters menu and blind to there being a whole second Noise section in it.

This does exactly what I always wanted to do, and it is exactly as quick and easy to do in Gimp as I always thought it should be. How I never found any information or mention of this in any guide on retro textures will forever remain a mystery for me.

Converting PBR Materials to Single Texture Files

This part is fairly simple and intuitive, but because it’s an integral part of what’s covered in the next section, I’m including it here for completeness, for anyone who comes upon this guide to make textures like these without prior knowledge.

When looking for free textures for a game, there’s actually not a lot of sources for simple low-resolution generic surface textures. But there a loads and loads of modern, high quality, free PBR materials. These materials consist of typically six or more different files that are combined by 3D rendering or game engines for various advanced visual effects and come at minimum sizes of 1024×1024 pixels that often come in at 10 to 20 MiB each. But they can easily be converted into a single 128×128 pixels .png file with a size of 30 KiB using Blender. You could simply just use the color texture from the PBR material and call it a day, but that leaves it without any shadows, which can look very boring and bad on many materials. But getting a texture file that combines both the basic colors and shadows is easy enough to do:

  • Create a new Blender file.
  • Go into the Output Properties on the right side of the screen, and under Format set the resolution to a square resolution of a power of 2, like 1024×1024.
  • Go into the World Properties on the right side of the screen and under Surface, set the Strength to 0 to remove ambient light from the scene.
  • Delete the cube and add a new plane mesh.
  • Position the camera directly above the plane and have it look straight down at it by setting all rotations to 0°.
  • Go into camera view to see what the camera is seeing by pressing 0 on the NumPad. In the camera’s Data settings change type from Perspective to Orthographic and change the Orthographic Scale so that the edges of the camera image match the edges of the plane. (If it’s a default new plane and the camera is 1m above is, the scale should be 2.0.)
  • Select the default light source or create a new sun (make sure it’s the only light source) and go into its Object Properties on the right side of the screen and set the x-rotation to -45° and the y-rotation to 45°. This will bring out the shadows that will add a perception of depth to the texture, and 45° angles is a good middle ground between all the possible directions a light could hit a surface from.
  • In the light’s Data Properties on the right side of the screen, set the Strength to 3. (Actually the correct value is pi, and you can either type in “3.142” or just “pi” instead of a number, and Blender will convert it automatically.)
  • Select the plane and go into its Material Properties on the right side of the screen and assign the material that you downloaded to the plane. (If you’re completely new to Blender and don’t know how to assign materials, I have to direct you to look for one of the many, many guides that explains that.)
  • In the Material Properties, Blender sets the IOR (Index of Refraction) for every new material to 1.5 by default. For most materials, this will produce a white sheen over the surface of the plane causes by the light from the light source coming in at an angle and bouncing off, that we do not want. Set this to 1 instead. Except for textures of natural stone and probably some other cases! For natural stone, I have found that an IOR of 1.5 almost always looks way better than changing it to 1. Try which value looks best depending on each material. This is the one step that will have to be manually repeated for every new material applied to the plane. If your finishes texture comes out looking either desaturated or too dark, check the IOR setting on the material.
  • Now that everything is set up, go into Render > Render Image at the top of the screen. In the new window that opens, go Image > Save as… to save your new texture file.
  • Optional: If you want to modify a texture to break up repeating patterns for large surfaces, as will be covered in the next section, and you have a material with a very uneven surface that produces a lot of strong shadows, create a second version of render image but with the light source turned 90° on the y-axis. The two will then be combined into one image later.

Breaking up Repeating Patterns on Large Surfaces

PBR Materials are almost always made and labled as “seamless”. Which means when you put two copies of the image next to each other, there will be no visible line where the two images touch. But unfortunately that doesn’t mean you can repeat that texture 10 times on the same surface without getting ugly visual artifacts.

You can not tell where the edges between the tiles are, but you can definitely see that there are repeating tiles. It looks bad enough on the wall of a building, but just awful on the side of a mountain. While textures like these are indeed “seamless”, they are completely unsuited for surfaces where they will repeat more than two or three times.

One common method to break up this repeating pattern in Blender or Godot is to use a shader that breaks up the surface into irregularly shaped pieces and randomly rotates the texture on each of these pieces. Which often looks pretty good on higher resolution textures where you can’t see the individual pixels. But in low-fidelity retro styles where texture pixels are very visible as individual squares, this makes the edges between each piece quite visible and looks pretty bad close up. And if there are strong shadows in the texture, as in many rock faces, it will look even worse. Getting the edges between these rotated areas to disappear took me a long time, but now I finally have it worked out how to do it in Gimp, without having to deal with any kind of shaders.

The numbers in the example below are based on using a 1024×1024 pixels source image that gets downsampled to 256×256 pixels and then repeats 16 times on the output image. Calculate whichever values apply for the scale you want to work with.

  • Open the texture file in Gimp.
  • In the top menu go on View and select “Show Grid” and “Snap to Grid”.
  • In the top menu go to Image > Configure Grid and set the grid spacing to 256 pixels horizontal and vertical.
  • Scale the active layer down to 256×256 pixels. To get the crisp pixelation look of old games in your textures, set Interpolation to “None”. Otherwise the image will get blurred in the downscaling process, losing the defining feature of this visual style.
  • At the bottom of the Layers docker, click “Duplicate Layer” until you got 16 copies of the downscaled layer and move them to the 16 squares of the grid. With snapping to grid enabled, they will align with each other automatically. Then at the bottom of the Layers docker, click “Merge” until all the layers are combined back into one.
  • Duplicate the new 4×4 image layer again, and rotate the new layer by 90 degrees.
    • Optional: If you are working with a texture with strong shadows, and you rendered a second image of the material with the shadows rotated by 90 degrees as explained below, don’t duplicate the layer and instead go into the top menu File > Open as Layers and select that second image. Then do the whole process of scaling it down, repeating it across the 4 by 4 grid, and merging it back into one layer, and then rotate it by 90 degrees.
  • To better see what’s going on, hide the lower of the two layers in the Layers docker by clicking on the eye icon.
  • Right click on the upper layer and select “Add Layer Mask.” Pick “White (full opacity)”. There are now two images for the layer in the Layers docker. One showing the image of the layer, the other currently just a white square. You can click on them to select which one you want to work with.
  • With the layer mask selected, go to the top menu and go Filter > Render > Noise > Solid Noise. You can pick whatever Size or Detail you want, but I like to go with size 8 and detail 4. Check the box “Tileable”. Every part of the layer that is under a dark pixel in the noise mask is now transparent. The darker the pixel, the greater the transparency.
  • With the layer mask still selected, go to the top menu Colors > Levels. Below the top slider bar, set the black value to 64 and the white value to 128. Or whichever other values you prefer, but those always work well for me. This will result in most of the noise being turned either completely white or completely black, and the layer being either completely opaque or completely transparent, but it leaves a blurry gradient of transparency on the edges of the regions, which will hide the seams.
  • Turn visibility on the bottom layer back on. If you combined two images with different shadow directions, check if the shadow directions match and rotate one of the two layers if they don’t.
  • As a final touch, go into the top menu and go Image > Mode > Indexed… and pick “Generate optimum palette” with a maximum number of colors of 16. This will make the crisp, grainy pixelation pop even more, and also reduce file size significantly. For a texture with many different colors, maybe try setting it to 24 or 32 if too much detail gets lost.
  • The image can now be exported as a .png and is ready to go.

The keen eyed may have noticed that this is a different texture than used in the example above. Even with this technique, the source image needs to be somewhat homogeneous in its color and brightness. It can break up a pattern in the source image to make it less visible, but when there’s a clear line between a light and dark area, this just becomes impossible to hide unless you go in and do fine color adjustments. Which is fiddly work and requires some skill, that I personally don’t want to bother with. And the whole point of developing this process was to have something that can be quickly repeated on a large number of textures.

Of course, a texture modified like this will still produce a repeating pattern. But instead of having 64 repititions on a 2048×2048 surface, we now only have four. And if you really want to, you can make the new texture on an 8 by 8 grind instead of a 4 by 4 and increase the distance between repetitions even further.

But I think it looks really good in action.

Especially compared to the rocks in Half-Life, which were a crime on the eyes even 28 years ago.

Day and Night Cycle over Palan

Really not a lot to say about this. This is what I’ve been doing over the past three days.

This scene is build with the Terrain3D plugin for large outdoor maps, the Sky3D plugin for the sky colors, clouds, sun, and moon, and the Cogito template to move around it as a player.

The rings and the space station cube are all mine. The geometrically correct shadow on the ring at midnight is particularly cool.

The only thing that’s not yet quite perfect about it is that the clouds appear behind the rings. Which is something I have not figured out how to set in the sky shader, but since the moon is behind the clouds where it’s supposed to be, I expect this to be relatively easy once I have some understanding of shader code.

Here comes the Sun!

I noticed some weird shadow colorations on the ceiling of my Oligarch Palace elements when importing them into Godot. And on my search to fix it and make the shadows at the top of vaults look more natural, I discovered the Global Illumination feature.

A difference like Day and Night!

This obviously looks nothing like the way 3D games were lit in 1999, or even in 2003. This took me four clicks and is much more advanced than anything that they had back then.

But one of the very first decisions that I made when I had the idea to make a game two and a half years ago was that I want it to have retro-styled models and textures but with nice modern lighting and shadows. So this is still entirely according to plan.

This might actually be a bit too realistic though. But I think once I really get into the entire lighting thing, adjusting the settings to make things less realistic probably shouldn’t that much of an obstacle.

“And he looked upon all that he had made, and he saw that it was good.”

Another big day for Iridium Moons.

I have finally fixed all the little issues I had with making buildings in Blender that can be directly imported into Godot and requiring very little final touches. And the results look amazing. With the procedures I am using, I can now very easily make buildings in this style of whatever dimensions I want, with multiple floors, and doors and windows I can move around as I wish in a few minutes. All that’s left after dragging and dropping the Blender editor file into Godot is to assign the materials I want to the material slots. And that’s it. All the textures will go where they are supposed to go, all the collision will work.

The textures used here aren’t final, but the process by which I make textures that match the specific parameters of my chosen graphics style are now also completely worked out.

It’s crazy how long it took and how difficult it was to get everything close to the way I wanted back in May, and how I now can replicate everything I made over the course of a month of 10 hour days in just one hour, or maybe even just half, and it’s at a higher quality. Learning all of this has not always been fun, thought it mostly was. And now that I actually know what I am doing with environment assets, I am expecting to see incredible advanced happening over the winter.

Some first views from Sarhat

Huge Progress with Iridium Moons this week.

The practice with tree models two weeks ago had gone very well and taught me quite a lot about how much detail you actually have to have on screen to create a scene that is visually rich and expressive and evocative to the viewers. Other than animated creatures of course, I think plants, and trees in particular, are probably the visual assets that need the most detail to look like the thing they need to represent. Buildings and machines can look very blocky, as that’s how they generally really are, but plants are overall very round and irregular. Which is why I choose to do trees first. A density of polygons and texture resolution that looks good enough on trees will looks good enough on everything. And it turns out that level of detail is much less than I had thought. When you manage to get the idea of a thing across, the brain does a lot of the heavy lifting to create the sensation of a much more complete environment and detailed world.

With that experience, I am now feeling very confident of going with a visual style that is more typical of what 3D games looked around 1997 than around 2002. A style that to me personally does feel a good deal more interesting and captivating and I expect to be much more fun to work with. Each assets requiring a shorter amount of work time is of course already nice when you are making every single object all by yourself from scratch. But a visual style with a lower amount of detail on each object also allows you to decorate a space with fewer objects without it feeling empty and deserted. And given that I expect many of the areas to be crammed and complex interiors of starships and factories, and the outdoors of Kion is mostly dense forests, this will be a big timesaver as well. All those things on the shelves and tables in Morrowind must have taken someone weeks if not months to arrange.

Because I have repeatedly greatly overestimated how much detail is actually needed to create a look that I am happy with so far, I have changed my approach to creating an asset library for Iridium Moons. Starting with a list of assets that I think I am going to need and working my way down until I have everything to start creating levels did sound smart originally, but it’s now very apparent that I would probably make way more stuff than I actually need to get the look that I want. So instead, my new approach is to make one small prototype map for each level that has small mockups of all the kinds of locations I want to have in the game. Starting with the most bare-bones, crude placeholders, and then adding detail to whatever things stand out to me as needing more work before they look right. This should help avoid making anything that I don’t actually need, or more variations of a thing than I need. I also think being able to place a work in progress into the environment and among other objects it is most likely to appear next to in the game will help a lot with getting the look right and consistent across the whole asset library.

For this purpose, I started working with Terrain3D this week, and it is just a joy. It’s not just a plugin for Godot that lets you sculpt a mesh for the ground, but also a full package to use absolutely gigantic maps in an actual game without blowing up the computer from trying handle all that data at once. I am now very determined to have loading screens between locations replaced with two or three minute hoverbike drives across the deserts of Sarhat or the open plains of Meruna. Even when there isn’t any real content to be discovered by exploration, I think it’s still very worthwhile just for the pacing of the game, like in Shadows of the Colossus.

Starting with Sarhat as the first planet to create assets for seemed like the natural choice, as it’s probably the easiest. The volcanic plains of Palan have an even more simpler landscape with nothing but rubble fields and a few shrubs, but it also has the two big cities which I am probably saving (or avoiding) for last.

First attempts with Terrain3D have been very promising. While it was a big struggle to find a good way to create sand and rock textures that can cover very large areas without repeating every two meters, the actual solution I have now is very simple, and I think the ground textures look really good.

As much fun as I had with the house models I made back in May while learning Blender and as good as they came out, I am now completely remaking them from scratch to fit with the new visual style I have settled for. So they still look rather flat. But I think the ground textures work amazing at 64 pixels per meter at 1920×1080 screen resolution.

But much more impressive is that I have rivers on Sarhat! Which I made completely by myself too. And you don’t see it on this screenshot, but it’s actually flowing downhill. And changing direction as the river winds through the landscape.

I thought getting to this stage would have been much, much harder, but it’s actually been stunningly easy. Given how many basic game mechanics I have already available by using the Cogito template for Godot, the only real technical challenge that I see in the future is coding NPC combat behavior. But given how absolutely everything about making a game with Godot and Blender has been so much easier than I would ever have thought so far, I am sure even that is only going to be an obstacle, but surely won’t be a barrier.