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

[SOLVED] Bumped Distort shader looses distortion!?

Discussion in 'General Graphics' started by Inferi, Feb 22, 2017.

  1. Inferi

    Inferi

    Joined:
    Sep 28, 2015
    Posts:
    145
    As I was adding a dustcloud that was supposed to give the effect of sand blowing up from thrusters hitting the ground, I saw that the "FX/Glass/Stained BumpDistort" shader is not working as it should "See clip below":



    Without the dustcloud, it all looks great.

    Anyone have any idea what to do here!?
     
  2. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    The grab pass is happening before the transparent geometry is being rendered (at least that's what it looks like from the video above). Which is why you see those squares coming down without seeing the alpha particles behind them.

    Are you using the FX/Glass/Stained BumpDistort shader, or was that just an example? If so, that would be a problem since that shader doesn't take vertex color into consideration, so you won't have any kind of control over the fading of the particles. It's best to write your own shader by adding a grab pass to an Alpha Blended particle shader.

    If you are already using a custom shader for this, would you mind posting the shader code so we can have a look?

    I remember having this exact issue a few years back and it was solved by changing the render order of the shader so that it would render after transparent geometry.

    I also have a few shader examples of particle distortion that I'd be happy to share if you need.
     
  3. Inferi

    Inferi

    Joined:
    Sep 28, 2015
    Posts:
    145

    Yes, I use FX/Glass/Stained BumpDistort shader.
    I changed the Render Queue on the material to 5000 and that fixed the problem.
    Will this give me problems in the future if I do it that way? Do I still need to write my own shader for this anyways?

    I am always interested in shader code so if you like to share some, it would be great. I will hopefully sit down and start coding shaders someday too :)
     
  4. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    5000 might be a bit overkill (Transparent is 3000), but it won't cause you any issues unless you have something you don't want the distortion particles to render in front of, though I doubt that would be the case. I tend to go with "Overlay" (4000) with distortion particles just to be safe.

    As far as using the Glass shader for particles, it won't cause issues with performance, but you also won't be able to adjust the fade using the particle opacity/color over lifetime feature.

    This is the shader I use for most of my distortion particles. It uses vertex color alpha to scale both opacity and distortion power, which helps in certain cases like ripples where you want the distortion amount to decay over time. It also allows you to color the distortion using the Color/Color Over Time RGB values. It uses a slider "Glow Power" to allow you to increase the brightness of the GrabPass texture, it just multiplies it by the value given (useful for simulating light propagation in raindrops and other water-related use cases). You can scale the base distortion power using the "Distortion" slider. Finally, "Soft Particles Factor" works similar to the native particle shader's version. This allows you to smoothly fade the particles into intersecting geometry, getting rid of the hard edges you sometimes see (though this requires a camera that renders to the depth buffer).

    Code (CSharp):
    1. Shader "Particles/Distortion"
    2. {
    3.     Properties{
    4.         _TintColor("Tint Color", Color) = (0.5,0.5,0.5,0.5)
    5.         _GlowPower("GlowPower", Range(1, 10)) = 1
    6.         _EmisCol("Emisison Color", Color) = (0.0, 0.0, 0.0, 0.0)
    7.         _MainTex("Base (RGB)", 2D) = "white" {}
    8.     _Distortion("Distortion", Range(0,128)) = 10 //The range can be whatever you want, not sure why I put 128, but yea.
    9.         _BumpMap("Normalmap", 2D) = "bump" {}
    10.     _InvFade("Soft Particles Factor", Range(0.01,3.0)) = 1.0
    11.     }
    12.  
    13.         Category{
    14.         Tags{ "Queue" = "Overlay" "RenderType" = "Transparent" }
    15.         Blend SrcAlpha OneMinusSrcAlpha
    16.         ColorMask RGBA
    17.         Cull Off Lighting Off ZWrite Off Fog{ Color(0,0,0,0) }
    18.         BindChannels{
    19.         Bind "Color", color
    20.         Bind "Vertex", vertex
    21.         Bind "TexCoord", texcoord
    22.     }
    23.  
    24.         SubShader{
    25.         // This pass grabs the screen behind the object into a texture.
    26.         // We can access the result in the next pass as _GrabTexture
    27.         GrabPass{}
    28.  
    29.         // Main pass: Take the texture grabbed above and use the bumpmap to perturb it
    30.         // on to the screen
    31.         Pass{
    32.  
    33.         CGPROGRAM
    34. #pragma vertex vert
    35. #pragma fragment frag
    36. #pragma fragmentoption ARB_precision_hint_fastest
    37. #pragma multi_compile_particles
    38.  
    39. #include "UnityCG.cginc"
    40.  
    41.         sampler2D _MainTex;
    42.     fixed4 _TintColor;
    43.     fixed4 _EmisCol;
    44.     float _Distortion;
    45.     struct appdata_t {
    46.         float4 vertex : POSITION;
    47.         float4 color : COLOR;
    48.         float2 texcoord : TEXCOORD0;
    49.  
    50.     };
    51.  
    52.     struct v2f {
    53.         float4 vertex : POSITION;
    54.         float4 color : COLOR;
    55.         float4 uvgrab : TEXCOORD0; //UV for the GrabPass{} texture
    56.         float2 uvbump : TEXCOORD1;
    57.         float2 uvmain : TEXCOORD2;
    58. #ifdef SOFTPARTICLES_ON
    59.         float4 projPos : TEXCOORD3;
    60. #endif
    61.     };
    62.  
    63.     float4 _MainTex_ST;
    64.     float4 _BumpMap_ST;
    65.     float _GlowPower;
    66.     v2f vert(appdata_t v)
    67.     {
    68.         v2f o;
    69. #if UNITY_UV_STARTS_AT_TOP
    70.         float scale = -1.0;
    71. #else
    72.         float scale = 1.0;
    73. #endif
    74.         o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    75. #ifdef SOFTPARTICLES_ON
    76.         o.projPos = ComputeScreenPos(o.vertex);
    77.         COMPUTE_EYEDEPTH(o.projPos.z);
    78. #endif
    79.         o.color = v.color;
    80.         o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
    81.         o.uvgrab.zw = o.vertex.zw;
    82.         o.uvbump = TRANSFORM_TEX(v.texcoord, _BumpMap);
    83.         o.uvmain = TRANSFORM_TEX(v.texcoord, _MainTex);
    84.         return o;
    85.     }
    86.  
    87.     //Only necesary if you plan on having soft particles and intersection fading
    88.     sampler2D _CameraDepthTexture;
    89.     float _InvFade;
    90.  
    91.     //This is a reference to the GrabPass{} texture used earlier
    92.     sampler2D _GrabTexture;
    93.     float4 _GrabTexture_TexelSize;
    94.  
    95.     sampler2D _BumpMap;
    96.     fixed4 frag(v2f i) : COLOR
    97.     {
    98.  
    99. #ifdef SOFTPARTICLES_ON
    100.         float sceneZ = LinearEyeDepth(UNITY_SAMPLE_DEPTH(tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos))));
    101.     float partZ = i.projPos.z;
    102.     float fade = saturate(_InvFade * (sceneZ - partZ));
    103.     i.color.a *= fade;
    104. #endif
    105.  
    106.     half4 tint = tex2D(_MainTex, i.uvmain);
    107.     half2 bump = UnpackNormal(tex2D(_BumpMap, i.uvbump)).rg; // we could optimize this by just reading the x & y without reconstructing the Z
    108.     float h2 = _Distortion * 100;
    109.     float2 offset = (bump * h2 * _GrabTexture_TexelSize.xy) * (i.color.a * tint.a);
    110.     i.uvgrab.xy = offset * i.uvgrab.z + i.uvgrab.xy;
    111.  
    112.     half4 col = tex2Dproj(_GrabTexture, UNITY_PROJ_COORD(i.uvgrab)); //col now represents the GrabPass{} texture
    113.    
    114.     col.rgb *= _GlowPower;
    115.     col.rgb *= i.color.rgb;
    116.     col.rgb += _EmisCol.rgb;
    117.  
    118.     col.rgb = abs(col.rgb); //Using absolute value in some of these calculations to avoid artifacts when glow power reaches higher levels
    119.     fixed4 cRet = col;
    120.     cRet.rgb *= (tint.rgb * i.color.rgb);
    121.     cRet.a = col.a * i.color.a * tint.a;
    122.     cRet.a *= _TintColor.a;
    123.     cRet.a = abs(cRet.a);
    124.     return  cRet;
    125.     }
    126.         ENDCG
    127.     }
    128.     }
    129.     }
    130. }
    131.  
    You can just copy that code and paste it into a new shader and you'll be good to go. Feel free to use this in any of your projects commercial/free. One thing to note, however, I made this shader about three years ago so I'm sure there are plenty of ways to optimize it.

    I used to be deathly afraid of shader code until I started messing around with it and looking up the Unity docs on shaders (Also the NVIDIA cg code section is very helpful). Once you get into it and find practical uses for all the syntax it actually becomes pretty enjoyable.

    Anyway, long story short, hope this helps you out a bit ;).
     
    ShoniverGames and Inferi like this.
  5. Inferi

    Inferi

    Joined:
    Sep 28, 2015
    Posts:
    145

    I thank you very much :)
     
  6. Konst

    Konst

    Joined:
    Aug 26, 2013
    Posts:
    78
    @McMayhem or someone would you please help to fix this cool shader to be able to work with VR single-pass stereo render? It is only renders for left eye correctly even after next code added:
    #if UNITY_SINGLE_PASS_STEREO
    i.uvgrab.xy = TransformStereoScreenSpaceTex(i.uvgrab.xy, i.uvgrab.w);
    #endif
    Thanks a lot!