Monday 27 January 2020

An Elegant Shader for a More Civilized Age

It surprises me that I had to go through so much trial and error to find such a shader for such a simple thing.
But here it is!
Imagine, if you can, a game featuring a city setting, populated with cars all around you. It shouldn't be too hard to picture. It would be pretty lame if all of those cars passing you had identical paint jobs, right? But how do those games do it? How do cars procedurally instantiate around the player, each in a different colour? Wait - more importantly - how will I do it?
Easy: MAGIC! ...Or is it math?
Shaders (in a really dumb nutshell) are programs that talk with your computer's GPU, instructing it how to render what you're seeing in the game. They calculate the colour of the thing you're looking at, account for things like lighting, specularity (i.e. shininess), texture (is it rough or smooth?), and emissiveness (does it glow?), and generate a final pixel colour - and it does this for each pixel on your screen!
So the answer, naturally, is to build a shader that can randomly generate colours and patterns to apply to a single 3d model, giving it a varied look. To do this, I used four basic textures:
Colour, Detail, Metallic, Normal
  • The colour replace map to determine the basic pattern and colour of the paint job. This doesn't look like much but I'll explain.
  • The detail (or diffuse) map shows the car's actual visual texture - metal fixings, rust, dents, and so on.
  • The metallic (or specular) map determines specularity - where it's shiny and how shiny it is. Black is dull, while white is very shiny.
  • A normal map, referring to the geometric normal of a surface, which determines how "bumpy" or textured the model will look. It will talk with any light sources in the game to simulate high and low spots to give the model a more detailed look.
The Jokermobile never looked so good.
 Most of these things are pretty standard; Unity ships with a bunch of shaders that handle this stuff - except for the colour replace map. Basically, the shader I put together takes the red, green, and blue values of the image, and substitutes each with a new colour, which themselves can be either hand-picked, or generated with a bit of code when the car instantiates in the game world.
The end result is simple, but pretty neat, if I do say so myself.
Get you a cab that can do both.
So now for each car model I end up using, I can add three or four colour replace maps, then replace the colours of those maps to get lots of variety on the mean streets.
Speaking of car models, the model I'm using was not made by me; it's a placeholder I'm using, made by Renafox on Sketchfab. I've made some modifications to the textures - and, of course, removed the wheels. Renafox has tons of car models, and other neat stuff available, and its all amazing. Check it out!
I hope I was able to explain myself well enough here. And for those interested in the shader code itself, check it out here. Any suggestions for improvement? Feel free to post a comment here or on the linked page.
What's next? Camera stuff?

No comments:

Post a Comment