Mesh Outline effect

image

:right_arrow: Live Demo Link

Efficient mesh outline effect. Uses a single draw per object unlike many other implementations that require multiple passes.

  • supports different color per mesh
  • supports transparency
  • supports masked alpha
  • supports skinning

The work itself is from quite a while ago, the initial version was done for Might is Right, but has evolved since then.

Uses just 2 material shaders for everything, no matter how many different meshes you have.

API is something like:

new Entity()
  .add(new Trasnfrom())
  .add(new Mesh(geometry, material))
  .add(new Highlight(r,g,b,alpha))
  .build();

The link actually contains the source for the API in case you’re interested in details.

9 Likes

Is the halo always drawn on top, even over objects closer to the camera?

1 Like

Yes.

The rationale was that it’s a visibility effect, so in cases of selection, for example, you’d like to see the entire object’s outline, even if it’s occluded.

In game settings, if you want to attract the attention of the player to something - it’s the same thing. Let’s say there’s an enemy, and he’s behind a wall - you’d still want to draw the outline in most cases.

That said - I’d like to extend it to have optional depth buffer blending and separate occluded/non-occluded outline settings.

5 Likes

Firstly this is great. I was looking for something like this!

Regarding the occlusion / depth. This is interesting, I’m not sure how to interpret this:

It looks like both the orange and white highlight are occluding each other?

1 Like

That’s interesting. If you add a highlight with 0 opacity then it will occlude the one behind. I guess this is not performant though so you would not want to put this non-highlight on all scene objects just so they occluded highlights on objects if they were in front of them.

Here I edited the “stacked” one (the front left) to have “no” highlight:

function stacked() {
    const h = new Highlight();
    h.add(HighlightDefinition.rgba(0, 0, 0, 0));
    return h;
}

1 Like

You got it, the way the technique works is we draw all outlined objects at once. We actually write just IDs of each object, then convert that to color via a lookup table, and then blur while preserving silhouette.

It’s very efficient and allows drawing thousands of outlines together without having to pay significant cost for each.

There’s also a side benefit of having correct color mixing when two outlines touch, but it does have some limitations as well.

As for 0 alpha draw - I thought about it, but I figured it would cause unexpected behavior when animating transparency for the user, so I left it to the user to decide. Removing the highlight when alpha is 0 is entirely possible has no performance downsides.

1 Like