I want to make a fairly generic material that blends a bunch of layers together for painted, worn, dirty metal, since that just about describes most of the materials in my Half Life scene!
There’s a good 10 years’ worth of Unreal Engine 3 materials to do this sort of thing, so it’s not going to be anything particularly new to you Unreal-ers out there, not to mention for people who have been writing shaders for a while.
That said, it’s been about 5 years since I’ve done a significant amount of shader work (not including a handful of Unity projects at home, and prototyping things here and there), so it’s seriously fun to be jumping back in 🙂
One thing I can’t recommend enough, especially for people who haven’t done a lot of shader/material work, is to prototype your materials in Photoshop.
Quick and dirty checker plate
The first material instance I’ll be making to test out a generic-ish material is a checkerplate metal, with paint, dirt and dents.
I’ll focus on the dirt part first.
So here are the basic elements of the masking I wanted to use, mocked up in Photoshop:
So now to settle on how I want to build my overall “dirt mask” for the material.
I want the vertex colour to overpower the AO, i.e:
- When the vertex colour is white I want 100% dirt
- When the vertex colour is black I want 0% dirt
And by black and white, I really mean Red, because I’m using the red channel, but… Details 🙂
A multiply doesn’t give me what I want:
So what I actually want is an overlay:
UE4 has nodes for all of the Photoshop blend modes, so this is very simple to do (and note, order of operations is important, swapping your Base and Blend layers will give you different results).
So here’s what it looks like in UE4, with some quick vertex colouring and the overlay mask:
So far, so good.
Actually, worth mentioning, I’m using the dirt mask to change the Metallic and Roughness parameters of the material, and probably will use it to subtly blend in a different normal and diffuse map at some point.
You could happily just feed this mask into the UE4 layered material system instead, which is just a wrapper around manually blending all the parameters together anyway…
Ok, with some more Photoshop tooling around, I’ve decided I want another overlay, this time using my existing map as a base, and my large scale dirt mask as the overlay:
And, same as before, hook the layers up in UE4:
Ok, so not too bad!
At this point, it could be worth adding a mask sharpness amount that you could paint per vertex, which is a pretty typical approach (scale the mask value around 0.5), but I’m actually pretty happy with the mask part of this now.
Next up, I’m going to put in a wear / dent amount. This will vary the surface normal, and also remove paint.
I’ve sculpted some dents and scratches in Modo, and I’m overdoing it quite severely because I intend to drop it back with vertex colours. Also, my sculpting is a bit lame, so I’ll probably want to redo it later.
Here is the metal with the checkplate normal, and the dent normal blended together (without masking):
It’s a little beyond the scope of this post, but worth pointing out that just regular blends of normal maps (lerp-ing, overlay, etc), are all a bit lame.
I’m using the reoriented normal mapping approach as outlined by Colin Barré-Brisebois and Stephen Hill:
Ok, next up I want to blend in the dents based off the green vertex channel.
I should probably work out how to build an “amount” parameter into the reoriented normal blend function, but for now I’m just going to modify the strength of the dent normal by blending it with a straight up vector (0,0,1) based on how much green channel there is:
So you can see that some clumsy button pushing scientist has dropped a large barrel off the ladder, and there are various other dents and scratches around.
It’s not shown off well here, but I’ve tried to paint the majority of scratches and bumps in the middle of the walkable area, and near the steps, where I think it makes sense.
I’ve been talking about adding a paint layer, but now I’m thinking that’s overkill.
There’s already enough instructions in this thing to raise an army of angry graphics programmers against me…
Forgetting paint, I think it would be nice to have some large scale roughness variation. To justify this to myself, I like to think that the roughness is the micro-surface detail, and the damage normal is the macro-surface detail, so it makes sense that the large tiling thing would have an effect on the micro scale as well as macro.
To side track further, if every texture in my game was 64 000 * 64 000, and the game resolution was large enough, I wouldn’t need roughness maps because I’d just have a lot of micro variation in the normal map, and it would serve the same purpose 😛
Annnnyway, I’ve dumped a large scale roughness map into the Normal map’s Alpha channel, and I’m using that to overlay the original small tiling roughness (still blending to a different roughness for the dirt):
So yeah, that’s it for now. Things I might think about addressing:
• Decide if I want to add a paint layer or not (I could probably just expand the dirt functionality, and make the whole thing a generic “2 layer material with additional blendy normals”.
• Create AO for the large denty map, combine that with the tiley AO, use that combined to blend in the dirt so that dents get more dirt
• Get better at texturing 🙂
The shader is 105 instructions with dynamic lighting only.
That’s pretty heavy (at least for PS3 / Xbox 360, or other hardware of similar age).
That’s a cost incurred for every pixel of the material, so that might be perfectly fine for a character’s face, or something that is unlikely to take up the whole screen during gameplay, etc.
That said, it’s always a balance.
Shaders like this reduce the need for a tonne of decals, lots of additional textures, etc.
I’m making a bunch of assumptions about how the UE4 renderer works, too.
At this point, I haven’t looked over the shader generation code at all, so I really don’t know much about what UE4 does with these materials.
A multi-purpose blending material, particularly one using overlays, may not be your best friend.
If you end up using it on a giant surface that has large sections that don’t use some of the functionality of the material (for example, a wall that has dirt on the bottom metre of it, and is ten metres tall with no other dirt on it), you might actually be better off:
- Using decals
- Creating a cheaper material for the top part that can seamlessly blend with the expensive multi-layer material at the bottom 🙂
Also, don’t just try and guess if things are expensive like I’m trying to here. Just profile it 🙂
Oh my. Nodes everywhere
I would absolutely not have a material this messy in a game, btw, I’d create functions for half this stuff, I promise 😛
Well, the ReorientedNormalBlend is in a function, so that’s a start…
Maybe next post I’ll clean this up and re-post it, so that it doesn’t look like a dog’s breakfast.
As a final note, here’s a good fun video on texture / vertex painting / material blends in UE4 from Uppercut games: