Search Unity

Question Draw sun sprite in front of atmosphere sprite but behind sprites behind the atmosphere?

Discussion in 'Shaders' started by RequiemOfTheSun, May 6, 2021.

  1. RequiemOfTheSun

    RequiemOfTheSun

    Joined:
    Sep 16, 2012
    Posts:
    4
    Hi all,

    I'm struggling to get something to draw how I'd like and I'm not educated enough about shaders to know if what I'd like to do is in the realm of possibilities. I'd love any advice or guidance.

    Description
    I'm trying to draw a dynamic horizon using 2D sprites. I've modeled a solar system with a sun and planets. You can stand on a 2D planet and I've drawn a horizon with an atmosphere and planets orbiting a sun. I have the planet sprites draw in front and behind the suns sprite based on their positions in the solar system.

    Problem
    The sun sprite shouldn't be affected by the atmosphere. However if I position the sun sprite correctly so it's in front of some planet sprites and behind others then the atmosphere is going to draw over the sun, obscuring it in ways that don't look right.

    Bad Aliased Sprite Mask Solution
    Here's my current solution that I'm not happy with. I've placed the sun sprite above the atmosphere and then added masks to each planet sprite that will mask the sun when they pass in front. This fakes things pretty well, the sun draws without being obscured by the atmosphere and the planets appear to pass in front of the sun.

    The reason I'm unhappy with this is Unity masks don't support transparency, instead they use the stencil buffer. So when the masks pass in front of the sun there is a very sharp aliased procession of pixels that I'd rather have be a smooth antialiased edge. Here you can see the highly aliased borders where the planets are in front of the sun. This razor sharp pixel edge looks even worse in motion.

    Mask Aliased Sun.png

    Can Shaders Do Better?
    I see two options where my lack of knowledge has me wondering if I could improve things using shaders. I've started into learning shaders but I'd like to see if anyone with experience at least knows if what I'm thinking about is possible.

    1) Atmosphere Fix Shader: Could I place the sun sprite back behind the atmosphere and have the atmosphere shader not draw over the unobstructed parts of the sun sprite?

    2) Sun Alpha Mask Shader: Is it possible to create shaders like Unity's Sprite Mask but which allow me to have alpha gradients to smooth out the aliased edges?

    Anyone know if either of these are possible, or have any other thoughts? Any help is appreciated!
     
    Last edited: May 6, 2021
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Yes, this is possible. The easiest way would be to use stencils ... but that's already what Unity's mask system uses and is why it has aliased edges. More complex setups would be possible but...

    ... most of the other options are basically reproducing this. And there are several assets on the asset store that do "soft" masks that use alpha blending. There are even a few for free if you look around on the internet.

    The most popular seems to be this one, though it's limited to Unity's UI system:
    https://assetstore.unity.com/packages/tools/gui/soft-mask-80667

    There's also this one which seems to work on any sprite?
    https://assetstore.unity.com/packages/tools/particles-effects/sprite-alpha-mask-112704

    A basic implementation would be to render a sprite's alpha to a render texture, then use that to mask another sprite that uses a custom shader that reads that render texture.
     
    Last edited: May 6, 2021
  3. RequiemOfTheSun

    RequiemOfTheSun

    Joined:
    Sep 16, 2012
    Posts:
    4
    That sounds pretty promising. So I could generate a render texture as one shaders output and get that as input to another shader.

    I'll go ahead and buy that second asset you've linked thanks! Perhaps it works for my needs, if it doesn't maybe I'll learn some more about the domain of alpha sprite masks.