Over the last few months I’ve been working hard on my latest first-person shooter project Competitive Recoil. The whole process took far longer than expected, and it was mostly because scope creep seems to be a huge weakness of mine, and I get far too easily distracted by new features.
Sometimes the only way to fight this is to turn those dream features into future techarthub content, and so here we are with the first of what I hope will become a series of Substance Designer tutorials on the creation of impact decals.
This Substance Designer tutorial will take you step-by-step through the process of creating a set of bullet hole textures perfect for use either as an impact decal within the game engine of your choice, or as a part of a larger Substance Graph.
This is part one of a two part series that covers the creation of a bullet impact decal in Substance Designer before bringing it into Unreal Engine 5. The second part, where we dive into the engine and set up a Impact Decal Master Material (as well as a bunch of other cool stuff) can be found here.
Download the source files
If you’re interested in checking it out for yourself, feel free to download the Substance graph from the project’s GitHub repository. You may use it in your own projects however you’d like.
If you’d also like access to the different variations that I use within my own projects, including a tiling sprite-sheet, please consider becoming a techarthub patron. Those in the Tutorial Content tier are able to download them alongside content from all current and future techarthub tutorials.
Here are some examples of the images that can be generated from the result of this tutorial.
Click any of the images for a higher resolution version.
Before we dive into Substance Designer we have a tiny bit of homework to do. It’s always helpful to have a look through some visual reference before you start dropping things into your graph. I do this even for smaller projects because it’s all too easy to go down a rabbit hole and end up with something that looks neat but doesn’t fit the part.
Luckily, collecting reference for impacts like these is super easy. Stock photo sites are particularly useful for this as it’s usually not difficult to find some real-world examples of what we’re after. Here are a few I found which informed my approach.
When looking for reference images of things like bullet damage, be aware that there are also a lot of computer generated images mixed in with the photos. Make sure you source some photos of the real thing if you can!
That said, vector art can be really useful too. Although rarely photorealistic, vector artists will have broken down and identified the key components of each shape from reference of their own, which makes it easier for us to do the same.
After looking through a bunch of different pictures of bullet holes punching through metal I’ve identified three of these key components.
- Surface Damage (damage to the surface layer, usually radiating outward in a jagged shape)
- Metal Damage (rippling/warping to the underlying metal as it bent inward)
- Bullet Hole (the ragged hole the bullet created when it tore through the object)
For the rest of the tutorial we’ll be building each of these components in turn and then blending them together to get our final result.
The Substance Graph
If you’re already pretty familiar with the process of creating surfaces in Substance and you just want to see how I created the different shapes for this material, here is a picture of the graph in full.
For those who want to join me step-by-step, let’s start with the outermost layer and work our way in.
The Surface Damage section creates a distorted starburst shape that radiates outward from the point of impact. It’s the most complicated part of the graph but it makes the most sense when we break it down into two sections.
Using default Gradient Axial Reflected and Cross Section nodes we create a triangle shape which we can then feed into two different Splatter Circular nodes. By shrinking the splatter radius, creating some random variation, and then Adding them together we can create a rudimentary jagged explosion.
I decided to combine two different Splatter Circular nodes just so we can have a little more control over the final result. I am using one for larger shapes and the other for smaller details.
This is what mine look like, with some random scale and a pattern count of 8 and 32.
Once you’re happy with the shape you might also consider passing it through an Transformation 2D node to make best use of the space. This is particularly important if you’re making textures for a realtime project as every pixel has a cost, even ones you’re not using.
Warping the shape
One thing I really liked about our vector reference was that included some interesting curves that gave contrast to the jagged points of the paint damage. To recreate this in Substance I used an Edge Detect node with a Width of 4 and an Edge Roundness of 1.
I then Subtracted the result from the original shape, creating some interesting curves while keeping the jagged ends of our pattern intact.
As a final step in creating the surface damage I used a Vector Morph Grayscale node to twist the shape and make it feel a little more organic. For the morph’s input I decided on a Perlin Noise generator with a Scale of 32, but you’ll get interesting results from whatever you feed into it.
Finally, I used a Bevel node with a Distance value of -0.0075 to give the shape a slight gradient. This is mostly to give surface layer some depth in the normal map.
The Metal Damage section of our graph is intended to reproduce not just dirtied damage of the underlying metal, but also the radial warping that occurs when the projectile passed through it.
To start with we’ll need a noise generator to use as a base. I went with BnW Spots 1 because it’s rad.
All we need to do is use a Radial Blur to create some interesting circular noise (I used an Angle of 0.5) and then Overlay the result with itself using another Blend node set to Overlay. Remember to keep your blur samples high enough to avoid obvious tiling, but try not to go nuts as it can get expensive and will slow your compile time.
The Opacity of the Blend node will define how strong the overall grunginess will be. I kept mine relatively subtle at 0.1.
Your end result will look something like this. It’s a mask we can
use in a bunch of different ways as the material comes together.
Lastly we have the bullet hole itself.
By passing a Thorn Shape through a Curve node, we can quickly get close to the shape we need. We then use another Vector Morph Greyscale just to warp the edges and make it asymmetrical/more organic.
Pulling it all together
The rest of our graph is going to be blending these three elements together in different ways to create the texture maps we want, and it’s also where our final outputs may differ.
Depending on where you plan to use the bullet hole you may want different textures, so you may break off from here to create your own. I plan on using this in an Unreal Engine project so I’m looking to generate the following:
- Height map (Greyscale)
- Normal map (RGB)
- Mask map (RGB)
(This last one includes Ambient Occlusion (R), Roughness (G), and Opacity (B) maps)
You might be asking yourself why there isn’t a Base Color map. I decided to save some texture space and use a combination of the Roughness and Ambient Occlusion maps instead. I’ll explain how in the next part of this series when we get into Unreal.
To create the Height map, Invert the end result of both the Surface Damage and Bullet Hole sections, and Add them together. Take that result and pass it through a Normal node and you’ll also get your Normal map.
If you notice your Normal map has some weird artifacting, you might consider slightly blurring it. I had this problem so I used a Blur HQ Greyscale node with an Intensity value of 0.1.
To generate the Ambient Occlusion map, get the output of your Metal Damage section and Overlay it with your Height map input. Pass that through an Ambient Occlusion HBAO node, and then Multiply the result by the same Height map input.
The Roughness map uses the output of the Bullet Hole’s Vector Morph Greyscale node passed through an additional Histogram Scan with a Position of 0.01 and Contrast of 0.
Likewise, the Opacity map is using the output from the Surface Damage’s Bevel passed through another, identical Histogram Scan.
That last section was a bit wordy but I hope it all made sense in practice. If you’re not sure, remember you can view the full graph in its entirety here, and you can always download the whole thing and have a dig around for yourself. If you have any questions or comments please don’t hesitate to shoot me a message or drop by the techarthub Discord Server. We’re a friendly bunch, so come and say hi!
Where you go from here is up to you, but I hope I’ll see you in the next tutorial where we’ll finally jump into Unreal, create our decal Material, and set up some Blueprint functionality to draw it on a range of different surfaces.
Thanks a lot for reading.