Creating Semi-Procedural Textures

Hello, this is the first of what I hope will be a series of development logs documenting some of the process in creating my projects. Some of the posts may be specific to certain applications and others may just be rants on broader game dev subjects. This particular log outlines a system that I set up in Unity3D. The technique will rely some familiarity with Unity3D and is mostly just a creative solution for something I needed in my game. Hopefully you find it interesting and/or inspiring.

The planets in Jettomero are procedurally generated using multiple techniques. In this dev log I’ll explain how the textures for each planet are created. I may still adjust it in the future to allow for greater diversity but in the mean time…

This is the hierarchy view of my texture generation process. A disabled camera lives on the parent object and points at a set of 10 quads that live underneath. By default each quad is using an identical texture, using a threshold shader so that whites are transparent and the black lines will all overlap on top of a single white background quad.

screen-shot-2016-09-15-at-7-22-03-pm

Here you can see what the layered quads look like in the scene view. It’s not much to look at yet. The lines are taken from a hand-drawn sketch and were additionally thresholded to black/white in photoshop before being imported into unity.

screen-shot-2016-09-15-at-7-24-50-pm

If I were to wrap a texture like this around one of my planets right now it would look like this:screen-shot-2016-09-15-at-7-32-28-pm

It still looks kind of cool because of the thresholded shader I’m using but I want more detail and more randomness.

Now, when I run the game, every time a new planet is created it requests a new texture from my texture generator script. So here’s what the layered quads look like when they generate a new texture:

screen-shot-2016-09-15-at-7-35-48-pm

For each quad renderer I assign one of my inkline textures and then randomize the texture scale and offset while also rotating the quads. This creates a big old mess of lines that will never be the same again. Note that the layers all all visible because I use a shader on the quads that makes white transparent.

From here my disabled camera gets rendered to a Render Texture and and I can copy that into a Texture2D which can be passed along to the planet that requested it.
screen-shot-2016-09-15-at-7-42-11-pm

The code for this is all fairly simple:

public Texture2D NewGeneratedTexture(float scale = 0.0f)
    {
        Texture2D refTex = refTextures[Random.Range(0, refTextures.Count)];

        foreach (Renderer r in GetComponentsInChildren<Renderer>())
        {
            
            r.material.mainTexture = refTex;
            float randomScale = scale == 0.0f ? Random.Range(4.0f, 8.0f) : scale;
            float randomOffset = Random.Range(1.0f, 1.0f);
            r.material.mainTextureScale = Vector3.one * randomScale;
            r.material.mainTextureOffset = Vector3.one * randomOffset;

            r.transform.localEulerAngles = new Vector3(0.0f, 0.0f, Random.Range(0.0f, 1.0f) * 360.0f);
        }

        Texture2D newTex = new Texture2D(defaultSize, defaultSize);

        RenderTexture.active = GetComponent<Camera>().targetTexture;
        GetComponent<Camera>().Render();

        newTex.ReadPixels(new Rect(0, 0, defaultSize, defaultSize), 0, 0);
        newTex.Apply();

        return newTex;
    }

I keep an array of different inklines, one of which is chosen at random at the start (although I could mix and match if I wanted). Then for each quad renderer you can see I assign the texture to that renderer’s material and proceed to warp it in basic ways. Then I create an empty texture and render my extra camera’s view into the texture.

I’m not sure if this is the most efficient code or the best solution for what I’m doing but I’ve been happy with the results so far. My original approach generated a texture completely in code using Perlin noise (which is what I use for my terrain deformation maps still), but this new technique let’s me easily use a texture with a hand-drawn feel which creates what I find to be a very appealing image on its own.

screen-shot-2016-09-15-at-7-52-36-pm

If you have any questions feel free to follow up with me by email @ ghosttimegames at gmail dot com or via Twitter @GhostTimeGames.

screen-shot-2016-09-15-at-7-54-45-pm