— Multipass Shaders (& inverted Hull outlines)
1.5M ratings
277k ratings

See, that’s what the app is perfect for.

Sounds perfect Wahhhh, I don’t wanna

Multipass Shaders (& inverted Hull outlines)

So far we only ever wrote a color to the screen once per shader (or let unity generate multiple passes for us via surface shaders). But we have the possibility to draw our mesh multiple times in a single shader. A great way to use this is to draw outlines. First we draw our object as usual and then we draw it again, but we change the vertices a bit so it’s only visible around the original object, drawing a outline.

To understand this Tutorial it’s best if you understood surface shaders: https://ronja-tutorials.tumblr.com/post/172421924392/surface-shader-basics

The first version of this shader will be based on the simple unlit shader: https://ronja-tutorials.tumblr.com/post/172173911737/textures

image

We already have a shader pass in this shader, so we just duplicate that for now. Because we’re writing the same information twice, this doesn’t change how the shader looks though.

image

The next change is to set up our properties and variables. This second pass will only write a simple color to the screen so we don’t need the texture. we just need the outline color and the outline thickness. We put the properties in the properties area at the top like usual. It’s important that we put the new variables in the second pass though.

image
image

The next step is to rewrite our fragment shader to use the new variable instead of a texture. We can simply return the color without any additional calculations in there.

image

Because we don’t read from a texture in this pass, we can also ignore the uv coordinates, so we remove them from our input struct, our vertex to fragment struct and we stop passing them between the structs in the vertex shader.

image
image

With those changes, we can see in the editor that the objects now simply have the color the outlines should have. That’s because our second pass simply draws over everything the first pass has drawn. That’s a thing we’re going to fix later though.

Before that we ensure that the outlines are actually outside of the base object. For that we simply expand them along the their normals. That means we need the normals in our input struct, then we simply add them to the position of the vertices. We also normalize the normals and multiply them with the outline thickness to make the outlines as thick as we want them to be.

image
image
image

With this we can now adjust the thickness of our hull, but it’s still hiding the base objects. The fix for that is that we don’t draw the front of the hull. Usually when we render objects we only draw the front because of performance reasons (you might have looked inside a object before and were able to look outside, that’s why). For this we can now invert that and only draw the backside. That means we can still see the object because we can look into the hull and we can see the hull behinde the object because it’s bigger than the object itself.

To tell unity to not render the frontsides of objects we add the Cull Front attribute to the hull pass outside of the hlsl area.

image
image

And with this we have the outlines how we want them.

image
image

It is pretty straightforward to also apply the outlines to a surface shader. Unity does generate the passes of the surface shader for us, but we can still use our own passes too which unity won’t touch so they operate as usual.

This means we can simply copy the outline pass from our unlit shader into a surface shader and have it work just as we expect it to.

image
image
image

The differences of outlines via a inverted hull shader to a postprocessing effect is that you can make the outlines on a material by material basis, you don’t have to apply it to all objects. Also it’s a different look than choosing outlines based on depth and normals. It’s best to inform yourself about both techniques and then choose which is better for your game.

I hope it’s now clear how shaders with multiple passes can work and how to use them to make outlines.

You can also find the source code for the shaders here:
https://github.com/axoila/ShaderTutorials/blob/master/Assets/19_Inverted_Hull/UnlitOutlines.shader
https://github.com/axoila/ShaderTutorials/blob/master/Assets/19_Inverted_Hull/SurfaceOutlines.shader

If you have any questions feel free to contact me here on tumblr or on twitter @axoila.

shader unity tutorial outline outlines unitytips madewithunity