Search Unity

Use particles as mask for other particles

Discussion in 'Shaders' started by diane1804, Nov 27, 2018.

  1. diane1804

    diane1804

    Joined:
    May 11, 2016
    Posts:
    3
    Hi !

    It's the first time I create particle systems and shaders.
    I want to reproduce this effect in Unity : https://www.premiumbeat.com/blog/vector-fire-effects/

    In this link, a fire is created with :
    - a orange/red particle system for the fire base
    - some black particle systems to mask the sides of the fire base and improve the shape of flames.

    I have created 2 different particle systems, and I'm trying to use the black particles as a mask.
    I have 2 shaders : the mask shader (black particles) and the masked shader (orange particles).
    I use stencils to do the mask, but stencils doesn't fit the oval shape of my particles. So I have my flames, with the sides cut by squares particles instead of oval particles.

    Link result :



    My current result :
    upload_2018-11-27_15-38-14.png
    My current result with stencils shaders :
    upload_2018-11-27_15-35-59.png

    Is there another way to do this mask ?
    Can I write in a buffer the alpha value of the black particles and modify the alpha value of flames in function ? (flameParticle.alpha = 1 - blackParticle.alpha). I know how to modify the color of a fragment in a shader, but I don't know how to pass values between the 2 shaders.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    You need to be using a cutout / alpha tested shader. If you notice when you have the black particles selected, Unity's outline is those boxy shapes. That is the shape that the shader is writing to the stencil too. Using alpha testing will fix that and it'll be the shape of the alpha.

    clip(col.a - 0.5);

    However ...
    Yes.

    There's a technique called destination alpha that might be useful here. It requires very careful handling of the alpha in your scene though.

    Basically, when anything is being rendered it's writing to the RGBA channels of the buffer. The RGB color is easily apparent, as that's what appears on screen, but the alpha is also being written to. The problem is Unity's own shaders tend to be a little dirty here, with some writing 1, some writing 0, and some just writing whatever. Most are good and write 1 or skip writing to the alpha. You can use the frame debugger to view the alpha channel and find errant cases there.

    Then it's a matter of rendering your "black" particles to the alpha only, and setting the blend mode for your shader to use the destination alpha, DstAlpha, as part of the blend.

    Black particles:
    ColorMask A // only render to the alpha
    Blend SrcAlpha OneMinusSrcAlpha // generic alpha blending


    The alpha in the frame buffer where the black particles have been drawn should now be black, and everywhere else is white.

    Flame particles:
    ColorMask RGB
    Blend DstAlpha One


    Note, this means your particles are effectively using additive blending. There's no easy way to do per pixel alpha blending with this technique. So, while it's kind of neat, and I've used it in lue of stencils on some mobile projects, it's not perfect. So, I'd stick to using stencils.


    However the real solution might be to not use particles at all! Instead you can have a scrolling texture in a shader and accomplish a nearly identical effect. Having a repeating voronoi distance texture, sampled multiple times at slightly different scales and offsets, and then changing the clip based on distance along the UV will get you something very similar.

    This link is doing something similar:
    https://simonschreibt.de/gat/stylized-vfx-in-rime/