Programmatic 2d outline for textures, but with some z-offset

Started by
3 comments, last by BlinksTale 10 years, 5 months ago

This is probably the most complicated semi-2d thing I have attempted before, and so far I have not found anything online about this kind of a shader, approach, anything.

I'm trying to make one outline for multiple 2d textures (from image files with transparency) rendered on separate 3d planes (couldn't wait until Unity 4.3). It should have A, B, and C up front, and then A's outline, B's outline, and C's outline in back (so that A, B, and C have no outlines at their overlaps). An image might help:

TV93xvA.png

The final monkey accomplishes everything that I'm looking for. The pieces overlap, but the outlines all appear behind.

Now, there are a couple of ways to do this, but I want to see if there's a way to do it without doubling the assets, and without having a crazy slowdown. Reasonable requirements in general, but lofty goals for this particular issue it seems.

Some have suggested simply scaling all assets and rendering them in black:

TSxmq62.png

This does not work with shapes like crescents, where there is empty space between the center of the object and one of its filled pixels. Scaling a silhouette will instead lead to outlines only for the outer edges.

An approach that does make a decent outline is rendering the silhouette in 24 different angles, offset by some radius:

0dVf1Jf.png

This approach though becomes painfully slow if anything is changing. It can be done once at the beginning of a scene to great effect, but it does not work well if your animations change every frame.

Luckily: I am not seeking to change my animations every frame, so I believe this approach will work for me. The question then is, how can I get it to appear with a Z-offset?

Conceptually, I will most likely have a separate plane for every object, then a second plane for each object's outline, and then have all the outline planes mimicking the original planes every frame, and compute the outline from those 24 offsets at the beginning of the scene only. The Unity forums said that creating a shader would be too expensive if it was trying to do an outline every frame, so having extra assets was the best approach. I think I can still do those assets programmatically, but just in general I am looking for the most flexible approach to this.

Are there any other techniques in this field that I should be looking at for 2d outlines of image files with transparency, rendered on 3d planes?

Advertisement

How about you render the black outlines for all three segments first, then you draw the three segments colour bits over the top.

To render high quality black outlines without rendering/sampling the texture 24 times you could preprocess the alpha channel of the texture to use a signed distance field, that way you only need a simple shader modification, and as an added bonus, you can tweak the thickness of the silhouette easily at runtime.

^^ what he said.

The second technique is used for the fonts in Team Fortress 2, pdf describing technique here http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Upvoting good advice.

EDIT: Though, depending on what your pipeline restrictions are, it may be a little bit faster to exploit stuff like early-Z and draw the colored bits *first* with the outline *after* but this will obviously fall apart if you don't have access to depth.

clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.

I really like the idea of sending it through a shader, so it can change in runtime.

How do I go from 2D PNG with transparency to an outline though, even with a static value?

I'm sure there's a way to do it without the 24 copies, but what is it? I've heard people mention edge detection before, does that work on 2d? (and as someone relatively new to shaders, how do I tell it to draw the outline itself, instead of just recoloring pixels or moving vertices by an offset?)

This topic is closed to new replies.

Advertisement