In the past couple of months things have really taken off with our current project Kindred, which I would love nothing more than to tell you all about, unfortunately it isn’t that time, we’re currently working through environment art and tool refinement, which is taking a lot of time, hopefully you’ve taken a look at Mark’s PA Particle Field package on the asset store and can see what we’ve been spending our time doing, if not take a look, this thing seriously blows my mind if you actually think about what it’s doing!
I’ll come back to PA Particle Field later, since I’m using it in my current mini project straight out of the box with amazing results.
So I set myself a challenge, although both Mark and I can create 3D, predominantly I do most of the asset creation for our games, obviously working closely with Mark to make sure we are both happy with the direction the games are taking. That said it can get a bit much working on artwork exclusively, so in this mini project I didn’t want to spend weeks creating artwork, I wanted to create some basic assets and then let Unity and in this case Shader Forge do all the work for me. So that’s what I did, and considering I started this less than a week ago in my free time (while also working on the artwork for Kindred) I have a prototype out and I am happy with the results.
The aim in simple terms was to blend together multiple pre defined heightmaps with a random seed for scale and offset inside a series tileable textures, letting the heightmaps blend together when they cross paths to create new shapes in the heightmap, this heightmap is then passed through the Vertex Offset to create mountain ranges, endlessly in world space Y. The system works, there is a sense of deja vu when wandering through the world that I hope to get rid off by rotating the maps on the seed value, as “god doesn’t build in straight lines” and although my system sort of does I don’t want those lines running parallel to each other….
I’ve used several other techniques too, such as blending normal maps of the heightmaps to create more detail and then passing a gradient through the world space Z axis to colourise the mountains and the mountain tops separately.
Before I get in to how the Shader works I just need to say that if you haven’t got your hands on Shader Forge yet you really need to get it, especially if you’re an artist it has not only allowed me to improve on my visuals inside of Unity but also given me a better understanding of what Unity can actually do.
Here is a break down of everything the above demo is doing.
- Pseudo Procedural Heightmap created on the GPU
- Pseudo Procedural Normal passed in to Normal
- Pseudo Procedural Terrain in world space Y
- Ramp in world space Z
- Pseudo Procedural Heightmap passed in to Alpha
- Alpha render to textured from camera as Nav Texture
- Player click to move in black areas of Alpha only
- Terrain and Collider transform matched to Player
- Clouds PA Particle Field Demo from package
And here is a break down of each of the Node Structures in Shader Forge and what each Structure is doing.
Pseudo Procedural Heightmap created on the GPU
In the above image from Left to Right you can see the Seed Value and how it’s being divided by 3.142 to make it a decimal value, this is then being passed through a FRAC to remove the whole number value, this creates a nice 0-1 value to work forward from. This 0-1 value is the multiplied by a few obscure numbers to add more randomness to the values which are then plugged in to a Dot Product with each other to give a final Pseudo random value. This value is then plugged in to a FRAC again to remove the whole value leaving us with 4, 0-1 values that will define our UV tiling, there is also a Tiling Value for global tiling which could be used for scale or refinement in the art process. The World Position node into the Component Mask is defining the Y direction as it’s world space UV projection.
Pseudo Procedural Normal passed in to Normal
The Pseudo Procedural system is the driving force for everything in the Shader, It plugs in to 4 texture inputs that create the terrain we see on screen. These textures are actually normal maps with a heightmap inside their alpha channel, but since Shader forge unpacks normal textures without an alpha channel and I didn’t want twice as many texture look ups I had to build the unpack normal myself. as you can see above.
We can also see the Alpha being plugged in to the Vertex offset here, I’ve added some Shimmer on the horizon to attempt to hide the vertex flicker that you get from scrolling textures through the vertices.
Ramp in world space Z
The colour for the Terrain is defined here, I’ve used a Ramp to isolate the peak, slope and base of the mountain ranges, the Red Green and Blue channels of the Ramp are then linked to Colours that are definable in the shader I could have used a coloured ramp straight in to the Texture slot but I would like to randomise these colours on start at some point leading to more variation in play.
The Ramp is Clamped in the texture settings so that it doesn’t tile if the mountains go above or below the projected range, you can see the Z projection plugged into the UV element of the Ramp Texture.
Pseudo Procedural Heightmap passed in to Alpha
Finally you can see Heightmap being passed in to the Alpha of the shader, this is not used for transparency but instead is used with a NavTexture Script that Mark helped me work up and that I will go through properly in the next instalment of this post.
Thanks for Reading, To get a closer look at the PA Particle Field Clouds I’ve used in the Demo Check out the Package page on this blog (Blog Link) or get your hands on the Package from the Unity Asset Store (Asset Store Link).
I might actually get around to making this in to a game and I’ll keep posting these up in a step by step process as the project develops.