Outline Effect

Hey there,
I want to make the outline effect system which will allow getting the needed renderer to have the outline and enable it with needed settings. Also, I can add two types of outline: the first one will not be seen through the walls, and another one will. Here's the link to the card: https://open.codecks.io/unity-open-project-1/decks/16/card/12e-outline-effect
(Tell me if there are some other requirements)


How would you implement it? I know a classic way to do it is to render the geometry with inverted normals. Some people call it the "inverted hull" technique.
(this tutorial does it: https://ronja-tutorials.tumblr.com/post/176120178562/multipass-shaders-inverted-hull-outlines )

However, that technique has limitations and it would require us to author all of our meshes without sharp corners, or the technique breaks.

However it can also go really well, like in this case: https://twitter.com/ironicaccount/status/1244621413425659906 but again, the mesh needs to be made on purpose...

I'm going to use something similar like the "inverted hull" method but I'll move the vertex position among the normal not in the objects space but in the screen space coords. Also, I'll not use culling at all. Instead, I'm going to use another pass for writing into the stencil buffer which will hide things that we don't need. Here's the example:

1 Like

Also, forgot to mention that it works in the URP.

1 Like

@cirocontinisio I can take on the card if you wish, I have tested a method based on inverted hulls that doesn't break on sharp edges, but takes up the vertex color channel of the mesh. It works on URP, uses stencils to avoid outline cluttering/ugly self-intersections and it can also be used for per-object selection outlines (that is, non-black outlines).

EDIT: Here's a proof: the model is completely hard-edged, but the outline still holds with no breaks.6367536--708714--outline example.png

So you to going to draw mesh twice.

First time draw mesh to set stencil buffet to one .
Second draw mesh with shift vertex position along normal (pos+=normal *offest )and set stencil test to pass in case is equal 0 only.

1 Like

Not sure what's the difference between the two shaders, but a couple of questions:
A) We plan to use Shader Graph for the toon shader. Is this outline going to play nice with that?
B) I don't see these outlines producing any inside lines, which is a feature I'd like to have. i.e. having an outline when depth or normals change, but the outline is "inside" the mesh itself.

You can see this behaviour in the outline solution that's in the repo right now on the toon-shading branch:


Bonus points if the outline is done IN ShaderGraph :)

My solution is done in ShaderGraph, and if I disable the stencil pass it should also do outlines inside; the only "problem" is baking the vertex colors on the mesh: I have used Blender for my first tests but I'm pretty sure that such operation can be automated within Unity with an editor script.
On a final note, I might also try to improve the outline shader in order to give it the ability to render imperfect/uneven strokes.

1 Like

Why do you want to bake the colours on the mesh?

Because if the mesh has any flat face or sharp edge the outline hull will break, in order to sidestep this issue I bake the smoothly interpolated vertex normals in the vertex color channel and then plug that value instead of the mesh vertex normals in the outline inflation step.
I'll post more info about my workflow later, it's 3 AM here.


This is actually genius

1 Like

Sorry but I prefer using hlsl instead of the Shader Graph. Also, I need some matrix multiplications in the shader and I don't know if Shader Graph can do it. My method doesn't need baking the mesh colors and yeah, I'm going to draw the mesh twice.

Also, I've looked at your implementation of the outline and it's a screen space effect. So, the vertex moving outline never will look like the SS outline because it doesn't know about other vertices.

Hello all,
I'm Fabien, 3D artist very interesting by npr rendering since few of years.

Using a thickness map could be usefull multiply with the global outline width.

Documentation on the subject :

I will try in my side with the shader graph to test something but i'm really not sure to suceed.

I did a test few years ago (without outline in this case) but to get an acceptable result it will be important to break edges of all (lights, shadows, colors, outlines) with a distortion and a little noise to get a more drawing look.

Test toon shader and post processing distortion:


Hope i will could help on this topics or in another.

I am making this thread the official one for the Outline Effect (card on the roadmap).

Thanks for the ongoing discussion, this is great!


According to me, we should use post processing to provide an easy parametric Outline Effect, .


Maybe, we should do a poll to choice define guideline between Hlsl or ShaderGraph

Shader graph uses hlsl files under the hood I think

Yes, but more importantly you can embed HLSL code into Custom Shader Graph nodes, which is how we're doing the toon shading in the project.

1 Like

I have toyed today with my outline shader and found some issues: while it works great for outer outlines, it doesn't appear as good as I thought on inner lines.

What about using CommandBuffers instead to issue specific variations on each renderer? If I understood correctly, the reason you don't want to go full screen with a global filter is because you want to be able to set a specific outline width for each outlined object, and only for those object that must be outlined.
I wonder, would it be possible to use the Graphics.Blit function, together with the method explained in https://alexanderameye.github.io/outlineshader to draw the outlines on top of the object by doing the calculations in a smaller area? I mean, the trick here would be blitting smaller screenspace squares which hold a single object to outline rather than processing the whole screen.

1 Like

Possibly you can do a special pass for the outlined objects which will do several blits. Something like that:
1. Run a pass with the object shader but using depth normal pass.
2. Store them into the render texture.
3. Run a full-screen outline effect for this particular object sending the render texture into the shader.
4. Discard the pixel if the depth == 0. (it will save some performance).

It can work but need to check the performance issues that can possibly be. (but it's not a mobile game so it might not be an issue)