1. We've introduced thread tags, search within a thread and similar thread search. Read more here.
    Dismiss Notice
  2. Learn how you'll soon be able to publish your games to China in four simple steps with Xiaomi. Sign up now for early access.
    Dismiss Notice
  3. Get further faster with the Unity Plus Accelerator Pack, free for new Unity Plus subscribers for a limited time. Click here for more details.
    Dismiss Notice
  4. We've released our first Timeline Experimental Preview, our new tool for creating cutscenes and more! To check it out click here.
    Dismiss Notice
  5. Unity 5.5 is now released.
    Dismiss Notice
  6. Check out all the fixes for 5.5 in patch releases 1 & 2.
    Dismiss Notice
  7. Unity 5.6 beta is now available for download.
    Dismiss Notice

Horizontal wave distortion

Discussion in 'Shaders' started by hawken, Feb 4, 2015.

  1. hawken

    hawken

    Joined:
    Aug 22, 2013
    Posts:
    267
    does anyone know of a shader that can be put on a quad and make this happen to things behind it / seen through it:

    [​IMG]

    All the better if it could be animated and use layers too. Simple horizontal pixel shifting.


    (this is a duplicate thread because I can't edit my old one, can a mod merge these?)
     
  2. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    511
    This effect is most often referred to as distortion. google for something like unity distortion shader, it should yield useful results.
     
  3. hawken

    hawken

    Joined:
    Aug 22, 2013
    Posts:
    267
  4. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    511
    I put an example together for you (see below for the download link).

    Here is how it looks:

    (sorry for the bad hiccups in the video, my recorder obviously sucks)

    The idea is to have a texture that describes how strong the distortion is at a certain pixel (black=full distortion to the left, white=full distortion to the right. In the following example, the Red channel represents horizontal and Green channel the vertical distortion. The Blue channel represents a mask (black=no distortion, white=full distortion). The distortion texture is scrolled using the built-in _Time variable, so you get motion into it.

    Code (CSharp):
    1.  
    2. [code=CSharp]//
    3. // Created with Unity 5.1
    4. // Example code to help answer the forum post at:
    5. // http://forum.unity3d.com/threads/horizontal-wave-distortion.295769/
    6. //
    7. // This source code is not a full fledged distortion solution.
    8. // It's just an example and hopefully proves useful for someone.
    9. //
    10. Shader "Custom/GrabPass Disortion" {
    11. Properties {
    12.         _MainTex ("Texture (R,G=X,Y Distortion; B=Mask; A=Unused)", 2D) = "white" {}
    13.         _IntensityAndScrolling ("Intensity (XY); Scrolling (ZW)", Vector) = (0.1,0.1,1,1)
    14.         [Toggle(MASK)] _MASK ("Texture Blue channel is Mask", Float) = 0
    15.         [Toggle(DEBUGUV)] _DEBUGUV ("Debug Texture Coordinates", Float) = 0
    16. }
    17.  
    18. SubShader {
    19.         Tags {"Queue" = "Transparent" "IgnoreProjector" = "True"}
    20.         Lighting Off
    21.         Fog { Mode Off }
    22.         ZWrite Off
    23.         LOD 200
    24.      
    25.         // See http://docs.unity3d.com/Manual/SL-GrabPass.html
    26.         GrabPass { "_GrabTexture" }
    27.  
    28.     Pass {
    29.         CGPROGRAM
    30.             //#pragma target 3.0
    31.             #pragma vertex vert
    32.             #pragma fragment frag
    33.             #pragma shader_feature MASK
    34.             #pragma shader_feature DEBUGUV
    35.             #include "UnityCG.cginc"
    36.  
    37.             // _MainTex is our distortion texture and
    38.             // should use "Bypass sRGB Sampling" import setting.
    39.             sampler2D _MainTex;
    40.             float4 _MainTex_ST; // texture tiling and offset
    41.          
    42.             // _GrabTexture contains the contents of the screen
    43.             // where the object is about to be drawn.
    44.             sampler2D _GrabTexture;
    45.          
    46.             // x=horizontal intensity, y=vertical intensity
    47.             // z=horizontal scrolling speed, w=vertical scrolling speed
    48.             float4 _IntensityAndScrolling;
    49.                  
    50.             struct appdata_t {
    51.                 float4 vertex  : POSITION;
    52.                 half2 texcoord : TEXCOORD0;
    53.             };
    54.  
    55.             struct v2f {
    56.                 float4 vertex  : SV_POSITION;
    57.                 half2 texcoord : TEXCOORD0;
    58.                 half2 screenuv : TEXCOORD1;
    59.             #if MASK
    60.                 half2 maskuv   : TEXCOORD2;
    61.             #endif
    62.             };
    63.          
    64.             v2f vert (appdata_t v)
    65.             {
    66.                 v2f o;
    67.                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    68.              
    69.                 o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); // Apply texture tiling and offset.
    70.                 o.texcoord += _Time.gg * _IntensityAndScrolling.zw; // Apply texture scrolling.
    71.  
    72.             #if MASK
    73.                 // We don't scroll this texture lookup, because we want the mask to be static.
    74.                 o.maskuv = v.texcoord;
    75.             #endif
    76.                              
    77.                 half4 screenpos = ComputeGrabScreenPos(o.vertex);
    78.                 o.screenuv = screenpos.xy / screenpos.w;
    79.                 return o;
    80.             }
    81.                  
    82.             fixed4 frag (v2f i) : COLOR
    83.             {        
    84.                 half2 distort = tex2D(_MainTex, i.texcoord).xy;
    85.              
    86.                 // distort*2-1 transforms range from 0..1 to -1..1.
    87.                 // negative values move to the left, positive to the right.
    88.                 half2 offset = (distort.xy * 2 - 1) * _IntensityAndScrolling.xy;
    89.                          
    90.             #if MASK
    91.                 // _MainTex stores in the blue channel the mask.
    92.                 // The mask intensity represents how strong the distortion should be.
    93.                 // black=no distortion, white=full distortion
    94.                 half  mask = tex2D(_MainTex, i.maskuv).b;            
    95.                 offset *= mask;
    96.             #endif                        
    97.                                                                              
    98.                 // get screen space position of current pixel
    99.                 half2 uv = i.screenuv + offset;
    100.                 half4 color = tex2D(_GrabTexture, uv);
    101.                 UNITY_OPAQUE_ALPHA(color.a);
    102.              
    103.              
    104.             #if DEBUGUV
    105.                 color.rg = uv;
    106.                 color.b = 0;
    107.             #endif
    108.              
    109.  
    110.                 return color;
    111.             }
    112.         ENDCG
    113.     }
    114. }
    115. }
    116.  

    Code (CSharp):
    1. // This source code is NOT a full fledged distortion solution.
    2. // It's just an example and hopefully proves useful for someone.
    3. //
    4. // I'm not sure if Unity Pro is required due to the usage of "GrabPass".
    5. Shader "Custom/DistortionExample" {
    6.     Properties {
    7.         _MainTex ("Base (RGB)", 2D) = "white" {}
    8.         _IntensityAndScrolling ("Intensity (XY), Scrolling (ZW)", Vector) = (0.1,0.1,1,1)
    9.     }
    10.     SubShader {
    11.         Tags {"Queue" = "Transparent" "IgnoreProjector" = "True"}
    12.         Lighting Off
    13.         LOD 200
    14.  
    15.         // See http://docs.unity3d.com/Manual/SL-GrabPass.html
    16.         GrabPass { "_GrabTexture" }
    17.  
    18.         CGPROGRAM
    19.         #pragma surface surf Lambert
    20.  
    21.         sampler2D _MainTex;
    22.         sampler2D _GrabTexture;
    23.  
    24.         // x=horizontal intensity, y=vertical intensity
    25.         // z=horizontal scrolling speed, w=vertical scrolling speed
    26.         float4 _IntensityAndScrolling;
    27.  
    28.         struct Input
    29.         {
    30.             float2 uv_MainTex;
    31.             float4 screenPos;
    32.         };
    33.  
    34.         void surf (Input IN, inout SurfaceOutput o)
    35.         {
    36.             // get screen space position of current pixel
    37.             half2 screenUV = IN.screenPos.xy / IN.screenPos.w;
    38.         #if UNITY_UV_STARTS_AT_TOP
    39.             screenUV.y = 1-screenUV.y;
    40.         #endif
    41.    
    42.             // _MainTex should use "Bypass sRGB Sampling" import setting.
    43.             // d.x = horizontal offset 0..1
    44.             // d.y = vertical offset 0..1
    45.             float4 d = tex2D (_MainTex, IN.uv_MainTex+_Time.gg*_IntensityAndScrolling.zw);
    46.    
    47.             // d.x*2-1 transforms range from 0..1 to -1..1.
    48.             // negative values move to the left, positive to the right.
    49.             screenUV.x += (d.x*2-1) * _IntensityAndScrolling.x;
    50.             screenUV.y += (d.y*2-1) * _IntensityAndScrolling.y;
    51.    
    52.             half4 c = tex2D (_GrabTexture, screenUV);
    53.             o.Emission = c.rgb;
    54.             o.Alpha = 1;
    55.         }
    56.         ENDCG
    57.     }
    58.     FallBack "Diffuse"
    59. }
    60.  

    You can download the Unity project of this example at:
    http://www.console-dev.de/bin/UnityGrabPassDistortion.zip

    EDIT, September 18th 2015: Package updated with a couple of more features, such as distance fade, culling mode and a particle shader. The package also contains examples that show what causes artifacts/problems with the shaders or perhaps distortion effects in general.
     
    Last edited: Sep 18, 2015
  5. hawken

    hawken

    Joined:
    Aug 22, 2013
    Posts:
    267
    Thanks Peter, you're a legend :D
     
  6. Unreal-Vision

    Unreal-Vision

    Joined:
    May 6, 2013
    Posts:
    57
    Hi Peter,

    Thanks for the shader :)

    Since Unity Grab Pass would be not so cheap about performance, you know any trick without grabpass?

    Thanks,
     
  7. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    511
    I believe it depends on what kind of effect you try to achieve, I don't think there is a generic recipe.

    If you try to get things fast, you often end up faking in very creative ways that will just work in specific places. Thinking about the water refraction in Super Mario Galaxy:
    See http://www.codersnotes.com/graphics/mario-refraction for the entire text.
     
  8. zuizuimei

    zuizuimei

    Joined:
    Aug 15, 2013
    Posts:
    16
    I found problem in our project under unity3d 5.2. the DistortionPlane_Masking move with the screen size. it is very werid. when i import that to one new probject, still under unity3d 5.2, it is okay. you can see my screenshots.
     

    Attached Files:

  9. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    511
    I tried to reproduce the problem, but it does not occur over here. I uploaded a new version (couple of new features and more examples) a minute ago (see post above for the link), you could give it a try if it changes anything for you (I don't think it will though).
     
  10. zuizuimei

    zuizuimei

    Joined:
    Aug 15, 2013
    Posts:
    16
    Thank you for your kindness, i know how to reproduce that. the problem just occurs after i switch to android platform. 100% occurs. i don't know if it is related to unity3d version or some api. hope you can help me about that.
     
  11. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    511
    I was able to reproduce it now as well. It's a new problem they introduced with Unity 5.2, it works well in Unity 5.1 though.

    I submitted a bug-report to Unity:
    (Case 728833) Regression: GrabPass offsets when resizing the screen

    I'll leave a note here when I get a response from them.
     
  12. zuizuimei

    zuizuimei

    Joined:
    Aug 15, 2013
    Posts:
    16
    Thank you. :)
     
  13. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    511
    Unity just replied to the bug-report with:
    The next patch release would be Unity 5.2.0p2. If they stick to their patch release plan, it could be available around September 23rd.
     
    Last edited: Sep 20, 2015
  14. CF-Games

    CF-Games

    Joined:
    Jun 2, 2013
    Posts:
    34
    Hi Peter and thanks for the shader. I'm however having some problems with the mask not working properly. Even with the mask on, it still looks like the first example where the edges are visible instead of it being a smooth transition. It works fine when I open your project as is, but when I import your shaders and use it in my existing project, the mask doesn't seem to work properly. It use to work fine in 5.1, but I started having this problem when I upgraded to 5.2. Is there something special I have to set in my project settings?

    EDIT: Installed 5.2.1 which came out today and it seems to have fixed the issue.
     
    Last edited: Sep 23, 2015
  15. hawken

    hawken

    Joined:
    Aug 22, 2013
    Posts:
    267
    Original reply really good solution for waves. Eventually I found an example of what I was after here: http://haxeflixel.com/demos/FlxWaveSprite/

    [​IMG]

    (a really simple horizontal wave)

    Any clues on how to do this? Maybe it just applies this effect to anything behind it, or even a culling selection based on layer? (needs to work with sprites and meshes)
     
  16. josessito

    josessito

    Joined:
    Feb 14, 2014
    Posts:
    55
    Hi Peter, I hate to ask more help from you, your shader was awesome, until I updated to unity 5.3. Now it is not working anymore. I tried to look into it by its waaay over my head. Maybe is a quick fix but I don't know where to begin. If you can take a look I would be really grateful, but I would understand if you can get to it.

    thanks!

    Edit: The shader looks fine in the editor window, but not in the game (there seems to be some sort of offset and the mask is not working, I believe)
     
  17. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    511
    I tested a windows standalone build but it works just fine here, proper offset and mask is working too. If you can throw together an example, where it's not working and send me the project, I can take a look at it.
     
  18. josessito

    josessito

    Joined:
    Feb 14, 2014
    Posts:
    55
    Hi Peter, I did a few test and the problem was in my camera. I switch off hdr and everything is working now...
    Thanks again!
     
  19. mitsoswu

    mitsoswu

    Joined:
    Dec 5, 2015
    Posts:
    6
    Hello Peter !!! ;)

    Is it posible to extract this shader from unity5 and use it in a "direct x 9" game?
    I wanna use this effect in my engine exhaust.to make heat distortion.

    If yes, which files do i need to extract ... and what needs to be done then, to combine them?
     
  20. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    511
    If you downloaded the provided zip archive already, you can find the relevant or interesting part in "Assets/GrabPassDistortion/GrabPassDistortion.cginc".
     
  21. mitsoswu

    mitsoswu

    Joined:
    Dec 5, 2015
    Posts:
    6
    Yes Peter, i did download the files, thank you man !! :D

    So, you mean that i only need, this GrabPassDistortion.cginc file?
    Thats all?..
    You know, this game i'm talking about mostly uses bmp textures, for example: to create smoke effect particles.
    As far as i've seen, this "GrabPass" fiĺe, is a text file....... Right? I did right click with my mouse and i opened it with wordpad and there was text.
    You think i should try as it is first?
    (Sorry for my noobish questions man, but i am very new to this.)
     
    Last edited: Dec 18, 2015
  22. mitsoswu

    mitsoswu

    Joined:
    Dec 5, 2015
    Posts:
    6
    :( that didn't work out yet..... but i am trying to find my way, on this .....

    ..hope someone would help me some day... would realy appreciate it .
    thanks for that package anyway Peter.
     
    Last edited: Dec 23, 2015
  23. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    511
    Shaders in the provided package are specifically created for Unity 5. They make use of features that are not supported in Unity 4, such as "shader_feature".

    All files under the "Assets/GrabPassDistortion/" directory are relevant, but what I tried to say is that GrabPassDistortion.cginc contains the interesting shader source code. If you want to use it outside Unity 5, you could look at this file to figure out what it's doing and try to back-port it to Unity 4 or rewrite it for another engine.

    Hope it helps.
     
  24. mitsoswu

    mitsoswu

    Joined:
    Dec 5, 2015
    Posts:
    6
    Oh... i see... yes i saw that page.

    Yes the truth is that i want to use it in a simulator, (not in unity5), that works in "directx 9"
    and most of the effects there, are using bmp textures to represent, for example: a smoke effect. And a wordpad file, with the parameters for that particular effect.

    (plus the fact that i don't know S*** about coding) .... LOL :p
    i just started to read some xml tutorials and some C++

    thank you Peter ..... i'll see what i can do then

    Dimitri.
     
  25. Bamboy

    Bamboy

    Joined:
    Sep 4, 2012
    Posts:
    14
    This is very useful, Peter. Are we allowed to use this for commercial purposes?
     
  26. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    511
    Sure!
     
  27. Aldrick

    Aldrick

    Joined:
    Feb 19, 2014
    Posts:
    33
    When we use grabpass to make distortion shader,it goes well on windows edtior and android devices,but it makes the whole screen black on ios platform.Any one has some insight about this?