Search Unity

Is blending like this possible?

Discussion in 'Shaders' started by Admiral-Skye, May 26, 2019.

  1. Admiral-Skye

    Admiral-Skye

    Joined:
    Feb 10, 2013
    Posts:
    32
    I have tried and given up several times on trying to do en blending effect I want. I'm trying to replace the grayscale of particles with a gradient map I made but it just doesn't blend the way I want to. Additive is to bright and the edges aren't correctly transparent, with alpha blend the particles don't blend with each other, and using color over lifetime just doesn't look right at all. It's a combination of alpha blend and additive I'm trying to do but everything I tried hasn't worked.

    I was thinking having the particles additive blend with themselves and alpha blend with everything else but I haven't been able to find something and I'm starting to think it isn't possible unless I'm just searching the wrong words.

    Here's an image showing the results of different types of blending I've tried compared to what I want and the gradient map for this example. blend2.png
     
  2. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,285
    I think maybe you have those visible polygon edges on your particles because you have your wrap mode set to repeat instead of clamp on your gradient map texture.
     
  3. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,285
    Also, why the 2d gradient map? Usually for a color ramp remap you would have a 1d texture.
     
  4. Admiral-Skye

    Admiral-Skye

    Joined:
    Feb 10, 2013
    Posts:
    32
    Even with the edges fixed, additive doesn't get the results I want. I want to blend the particle's color with itself only, not make them brighter.

    I made the ramp 2d here so it's easy to see, the actual ramp is actually 1d.
     
    richardkettlewell likes this.
  5. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,285
    It looks like you want alpha blended but for some reason your alpha blended test isn't working correctly. Perhaps it is a premultiplied alpha issue, but to know that we would need to know what shader you are using and what material settings.

    Getting closer! :)
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    It seems to me like what your expected results are what you'd get from drawing additive greyscale particles and applying the gradient to the final rendered results of the entire particle system.

    That's not what the shader is doing, or even capable of on it's own. Instead at best you're applying the gradient to each particle individually with no knowledge of the other particles in the scene. You can get something that's similar, but you will never exactly match your original goal.

    My suggestion would be to try using a soft additive blend along with the alpha from color over lifetime:
    Code (CSharp):
    1. Shader "Particles\Gradient Map"
    2. {
    3.     Properties {
    4.         [NoScaleOffset] _Gradient ("Gradient Map", 2D) = "white" {}
    5.     }
    6.     SubShader {
    7.         Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    8.  
    9.         Pass {
    10.             ZWrite Off
    11.             Blend OneMinusDstColor One
    12.  
    13.             CGPROGRAM
    14.             #pragma vertex vert
    15.             #pragma fragment frag
    16.  
    17.             #include "UnityCG.cginc"
    18.  
    19.             struct v2f {
    20.                 float4 pos : SV_Position;
    21.                 float3 uvAndAlpha : TEXCOORD0;
    22.             };
    23.  
    24.             void vert (appdata_full v, out v2f o)
    25.             {
    26.                 o.pos = UnityObjectToClipPos(v.vertex);
    27.                 o.uvAndAlpha = float3(v.texcoord.xy * 2.0 - 1.0, v.color.a);
    28.             }
    29.  
    30.             sampler2D _Gradient;
    31.  
    32.             fixed4 frag (v2f i) : SV_Target
    33.             {
    34.                 float circleGradient = 1.0 - dot(i.uvAndAlpha.xy, i.uvAndAlpha.xy);
    35.                 float gradientUV = saturate(circleGradient * i.uvAndAlpha.z);
    36.                 fixed4 gradientColor = tex2D(_Gradient, gradientUV);
    37.  
    38.                 gradientColor.rgb *= gradientColor.a;
    39.  
    40.                 return gradientColor;
    41.             }
    42.  
    43.             ENDCG
    44.         }
    45.     }
    46. }
    Here's an example using a rainbow colored gradient.
    upload_2019-5-28_11-51-47.png

    And using a gradient based off of the one you posted above:
    upload_2019-5-28_11-57-22.png
     
    Last edited: May 28, 2019
    richardkettlewell likes this.
  7. Admiral-Skye

    Admiral-Skye

    Joined:
    Feb 10, 2013
    Posts:
    32
    Before I saw bgolus' suggestion I was trying a different approach. I tried using a Render Texture with a black background. I managed to get it close to what I wanted but it renders above everything else. It seems I'm trying to do something that's too advanced for me at the moment.



    While your solution is nice, I kinda want the black borders to be visible and if I invert the ramp that the center is black instead. But I guess I'm asking for too much
     
  8. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    If you want the black edge like you have above, and you want to use a particle system, then the render texture approach is the "best" solution. The issue of it rendering on top is easily solved by user the render texture as the texture on a bit of geometry in the world rather that as an overlay in OnRenderImage (how I'm guessing you're trying to do it?).

    The other option is to not use particles at all, and instead use a shader based flame effect. Something like "Rime Fire" as shown here:
    https://simonschreibt.de/gat/stylized-vfx-in-rime/#update1

    Rime wasn't the first to use this style of fire, but is certainly one of the first to discuss it's implementation publicly. It's been a relatively common tech art trick for a long time, and if you look at effects in several AAA games you may see some similar stuff that's done the same way.

    There's also other purely shader based techniques to make believable flame-like effects. Here's a really impressive one:
    https://www.shadertoy.com/view/XsXSWS
     
  9. Admiral-Skye

    Admiral-Skye

    Joined:
    Feb 10, 2013
    Posts:
    32
    The primary use for this effect is for this.

    I want to make a fist with a dense nebula-like trail as it flies. The very last shader in that page seemed like it could fit this. I'd have to look into making a volumetric shader if that's the case.