Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Controlled blending for sprites

Discussion in 'Shaders' started by autowash, Nov 9, 2015.

  1. autowash

    autowash

    Joined:
    Oct 14, 2012
    Posts:
    18
    Hi!

    I just know the very basics of shader syntax, so I apologize if this is a basic question. I have a 2D scene and an orthographic camera... I figured the "Particle Multiply Double" shader would work nicely as a fake sprite based lighting, and it kind of does. Sort of like a flash light. My problem is that I have a background that's far in the distance (a sky), that should not be "illuminated". So, i have:

    A: A background (way back)
    B: A foreground (that I want to "illuminate" using my sprite)
    C: A round light shape sprite (currently with the multiply double shader)

    This picture show the setup I have, and what I want. (I faked the blending in photoshop, so it's perhaps not exactly what Unity would look like, but it gets the point across).

    ShaderBlendAddQuestion.jpg

    A and B are sprites also, and preferably I'd like them to remain sprites...

    I know layers are a Unity runtime feature and not accesible in shaders, but is there any way I can achieve this effect? Like some depth hack in the shader? Sprite sorting wouldn't work (right?) since I can't have A<B<C in geometry but B<C<A in blending... Was thinking about multiple cameras and rendering the background last, but how to "cut out" the other stuff in that case...

    Any tips greatly appreciated!
     
  2. Fuegan

    Fuegan

    Joined:
    Dec 5, 2012
    Posts:
    20
    Hello,

    I see two options for this, One would be messing with Depth (A > C > B) and rendering C later (Queue changed) with Ztest Greater instead of the default LEqual. But I never tested it with sprites so I can't be sure Depht is resolved as usual 3D stuff.

    The other solution would be to use the Stencil buffer (http://docs.unity3d.com/Manual/SL-Stencil.html). A and B would be rendered before C (C with a Queue changed). B could use a Stencil like
    Code (CSharp):
    1. Stencil
    2.             {
    3.                 Ref 2
    4.                 Comp always
    5.                 Pass replace
    6.             }
    and C with

    Code (CSharp):
    1. Stencil
    2.             {
    3.                 Ref 2
    4.                 Comp equal
    5.             }
    PS : I had a bug with Unity 5.2 when changing render Queue wouldn't be effective unless you reset the shader in the material (like drag&drop the shader on the material again to make sure it's reset).
     
    autowash likes this.
  3. autowash

    autowash

    Joined:
    Oct 14, 2012
    Posts:
    18
    It works using the stencil buffer, thanks a lot @Fuegan!

    I did have an issue if B is partially transparent, where it would write to the stencil buffer also some of the completely transparent pixels. I solved that by using an AlphaTest Greater .01 on the shader for B.