0 votes

I made a character that uses two sprites. One for the arms+gun, which controls gun aiming, shooting, etc; and one for the body, which includes torso+legs+head and does stuff like moving, jumping etc.

I like to outline my sprites black so that they contrast better with the background. How do I outline my character as a whole without overlapping borders? If i do the individual shader outline method, the outline for the arms+gun, who is in front, will obscure part of the body's sprite.

I thought about dynamically creating textures on the fly and adding a border to them, but that doesn't sound very optimal. Is there any other way?

Thanks.

asked Oct 29, 2019 in Engine by esdo (31 points)

1 Answer

+1 vote
Best answer

AFAIK there is no easy way to do this automatically when you have multiple sprites. I often see people bumping on these kinds of issues which hints that they would need an intermediate rendering pass to extract the silouhette of what they are drawing (or use stencil buffer, both unavailable in Godot).

You would need to either have a copy of your sprites behind them all, animating the same way, except they would be just silouhettes with the outline color. This might be the most lightweight approach if you want this game on mobile.

Another way is to render your character to a viewport and render the result back to the main viewport with an outline shader (achieving the same thing you would end up doing in an image editor with a two-pass render, instead of single-pass), but it's really cumbersome.

answered Oct 30, 2019 by Zylann (26,782 points)
selected Oct 30, 2019 by esdo

Would it be possible to just make the outline be rendered all in the same z-layer? Because then I could make all outlines be behind both the body and arms, so that the outline for the arms will not be visible if they are behind the body.

No, this is not how rendering works. Sprites are ALWAYS rendered one after the other, no matter their Z-order, they will be drawn one by one. In that situation you have to draw the outline seperataley from this. You'll have that problem if your sprites are drawn separately as long as you have nothing else to compare when drawing the outline. The fragment shader that renders it needs to know if it's on the edge of ALL the sprites composing your character, but right now it's not possible to know that in advance... until you draw them all first. See the problem here? :p
So either draw a mirrored silouhette of your sprites behind them all, or find a way to mimick stencil buffer so that an overlay can draw it on top...

Okay but cant outlines be rendered to a specific z-layer? That way I could place them on the background, so that overlapping outlines occur but are hidden behind the character sprites.

That's what I meant by "drawing a silouhette" of your sprite behind them. They will overlap, but it won't matter because they are behind and they are silouhettes anyways. I did a small proof of concept recently using a distance field: https://www.youtube.com/watch?v=8xfHAqFJnqY&feature=youtu.be
You might not need something as fancy but that's the approach I took here.

Ohhhh got it. I misinterpreted it in the first time reading.

Thanks for the help!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.