How To Make a Bullet Hole in Substance Designer

Over the last few months I’ve been working hard on my latest first-person shooter project Competitive Recoil (now available on the Unreal Marketplace). The process took far longer than expected, mostly because scope creep seems to be my biggest weakness and I get distracted by new features far too easily.

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 impact decal tutorials!

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 in creating a bullet impact decal in Substance Designer and then bringing it into Unreal Engine 5. The second part, where we’ll dive into the engine and set up the Material (and a bunch of other cool stuff), is coming soon.

Here are some examples of the images that can be generated from the result of this tutorial.
You can click any of the images to grab a higher resolution version.

If you’d like to play around with the Substance graph yourself, you can download it via the project’s GitHub repository. Feel free to use it in your own projects however you like, no attribution necessary (although a shout out would be much appreciated!)

This project was supported by my amazing Patrons. If you’d like access to the different variations of the graph that I use in my own projects (including a tiling sprite-sheet) please consider joining up to access the Patron-only downloads page.

Those in the Tutorial Content tier gain access not only to these files, but all of the source assets and project files from the entire techarthub site. More content is released every month, so let me know what you’d like to see next!

That’s the sales pitch out of the way. Let’s get started.

Reference Collection

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 find 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 the 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.

Click here for a higher-resolution version that you can actually read

For those who want to join me step-by-step, let’s start with the outermost layer and work our way in.

Surface Damage

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.

The Starburst

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 simple jagged explosion shape.

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 rotate it to make best use of space. This is particularly important if you’re making a textures for games 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.

Metal Damage

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 a projectile passes 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.

Bullet Hole

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.

My curve’s settings.

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 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 game 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 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 with an Intensity value of 0.1.

To generate the Ambient Occlusion map, get the output of our 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 passed through a Histogram Scan node with a Position of 0.01 and a Contrast of 0.

Likewise, the Opacity map is using the output from the Surface Damage’s Bevel passed through an identical Histogram Scan node.

What’s next?

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, or you can just download the whole thing and have a dig around 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 surfaces.

Thanks a lot for reading, and good luck with your projects!