does anyone know of a shader that can be put on a quad and make this happen to things behind it / seen through it: 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?)
This effect is most often referred to as distortion. google for something like unity distortion shader, it should yield useful results.
TBH the nearest I could find was the screen wipe code http://wiki.unity3d.com/index.php/ScreenWipes which isn't a shader Looks like this hasn't been done much
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. Spoiler: Old Unity 5 Shader Example, see shader files in the package below for the latest version Code (CSharp): [code=CSharp]// // Created with Unity 5.1 // Example code to help answer the forum post at: // http://forum.unity3d.com/threads/horizontal-wave-distortion.295769/ // // This source code is not a full fledged distortion solution. // It's just an example and hopefully proves useful for someone. // Shader "Custom/GrabPass Disortion" { Properties { _MainTex ("Texture (R,G=X,Y Distortion; B=Mask; A=Unused)", 2D) = "white" {} _IntensityAndScrolling ("Intensity (XY); Scrolling (ZW)", Vector) = (0.1,0.1,1,1) [Toggle(MASK)] _MASK ("Texture Blue channel is Mask", Float) = 0 [Toggle(DEBUGUV)] _DEBUGUV ("Debug Texture Coordinates", Float) = 0 } SubShader { Tags {"Queue" = "Transparent" "IgnoreProjector" = "True"} Lighting Off Fog { Mode Off } ZWrite Off LOD 200 // See http://docs.unity3d.com/Manual/SL-GrabPass.html GrabPass { "_GrabTexture" } Pass { CGPROGRAM //#pragma target 3.0 #pragma vertex vert #pragma fragment frag #pragma shader_feature MASK #pragma shader_feature DEBUGUV #include "UnityCG.cginc" // _MainTex is our distortion texture and // should use "Bypass sRGB Sampling" import setting. sampler2D _MainTex; float4 _MainTex_ST; // texture tiling and offset // _GrabTexture contains the contents of the screen // where the object is about to be drawn. sampler2D _GrabTexture; // x=horizontal intensity, y=vertical intensity // z=horizontal scrolling speed, w=vertical scrolling speed float4 _IntensityAndScrolling; struct appdata_t { float4 vertex : POSITION; half2 texcoord : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; half2 texcoord : TEXCOORD0; half2 screenuv : TEXCOORD1; #if MASK half2 maskuv : TEXCOORD2; #endif }; v2f vert (appdata_t v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); // Apply texture tiling and offset. o.texcoord += _Time.gg * _IntensityAndScrolling.zw; // Apply texture scrolling. #if MASK // We don't scroll this texture lookup, because we want the mask to be static. o.maskuv = v.texcoord; #endif half4 screenpos = ComputeGrabScreenPos(o.vertex); o.screenuv = screenpos.xy / screenpos.w; return o; } fixed4 frag (v2f i) : COLOR { half2 distort = tex2D(_MainTex, i.texcoord).xy; // distort*2-1 transforms range from 0..1 to -1..1. // negative values move to the left, positive to the right. half2 offset = (distort.xy * 2 - 1) * _IntensityAndScrolling.xy; #if MASK // _MainTex stores in the blue channel the mask. // The mask intensity represents how strong the distortion should be. // black=no distortion, white=full distortion half mask = tex2D(_MainTex, i.maskuv).b; offset *= mask; #endif // get screen space position of current pixel half2 uv = i.screenuv + offset; half4 color = tex2D(_GrabTexture, uv); UNITY_OPAQUE_ALPHA(color.a); #if DEBUGUV color.rg = uv; color.b = 0; #endif return color; } ENDCG } } } Spoiler: Old Unity 4 Shader Example Code (CSharp): // This source code is NOT a full fledged distortion solution. // It's just an example and hopefully proves useful for someone. // // I'm not sure if Unity Pro is required due to the usage of "GrabPass". Shader "Custom/DistortionExample" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _IntensityAndScrolling ("Intensity (XY), Scrolling (ZW)", Vector) = (0.1,0.1,1,1) } SubShader { Tags {"Queue" = "Transparent" "IgnoreProjector" = "True"} Lighting Off LOD 200 // See http://docs.unity3d.com/Manual/SL-GrabPass.html GrabPass { "_GrabTexture" } CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; sampler2D _GrabTexture; // x=horizontal intensity, y=vertical intensity // z=horizontal scrolling speed, w=vertical scrolling speed float4 _IntensityAndScrolling; struct Input { float2 uv_MainTex; float4 screenPos; }; void surf (Input IN, inout SurfaceOutput o) { // get screen space position of current pixel half2 screenUV = IN.screenPos.xy / IN.screenPos.w; #if UNITY_UV_STARTS_AT_TOP screenUV.y = 1-screenUV.y; #endif // _MainTex should use "Bypass sRGB Sampling" import setting. // d.x = horizontal offset 0..1 // d.y = vertical offset 0..1 float4 d = tex2D (_MainTex, IN.uv_MainTex+_Time.gg*_IntensityAndScrolling.zw); // d.x*2-1 transforms range from 0..1 to -1..1. // negative values move to the left, positive to the right. screenUV.x += (d.x*2-1) * _IntensityAndScrolling.x; screenUV.y += (d.y*2-1) * _IntensityAndScrolling.y; half4 c = tex2D (_GrabTexture, screenUV); o.Emission = c.rgb; o.Alpha = 1; } ENDCG } FallBack "Diffuse" } You can download the Unity project of this example at: http://www.console-dev.de/bin/UnityGrabPassDistortion.zip EDIT, April 15th 2017: Package updated to allow to tint distortion areas. Project uses Unity 5.4. 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.
Hi Peter, Thanks for the shader Since Unity Grab Pass would be not so cheap about performance, you know any trick without grabpass? Thanks,
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.
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.
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).
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.
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.
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.
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.
Original reply really good solution for waves. Eventually I found an example of what I was after here: http://haxeflixel.com/demos/FlxWaveSprite/ (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)
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)
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.
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!
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?
If you downloaded the provided zip archive already, you can find the relevant or interesting part in "Assets/GrabPassDistortion/GrabPassDistortion.cginc".
Yes Peter, i did download the files, thank you man !! 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.)
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.
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.
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 i just started to read some xml tutorials and some C++ thank you Peter ..... i'll see what i can do then Dimitri.
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?
Hi Peter, Just a quick question, in your example the distortion affect changes over time, but when I used the script you provided it doesn't change over time. I noticed there were no references to _Time at all in the code and I'm not sure where to add them. Do you know what to do? Another thing, is it possible to give the distortion effect a color? As in everything being distorted get a slight shade of blue?
The animation is entirely done in shader code, there is no C# code involved. If you open GrabPassDistortion.cginc you should find the following line in the vertex shader: Code (CSharp): o.texcoord.xy += _Time.gg * _IntensityAndScrolling.zw; // Apply texture scrolling. This line is responsible scroll the texture coordinates and _Time.gg is an Unity built-in shader variable. I just tested the project with Unity 5.4 and it does animate the distortion here. Perhaps you use a different Unity version? Another reason could be that you didn't press Play, because if you're in edit mode only, you need to enable the Animated Materials option in Unity's Scene View, which tells Unity whether to advance the _Time.gg variable while the game is not playing. I updated the example to be able to tint the distortion. See this post for the download link (it's the same link as before though). I hope that's what you're looking for.
Hey @Peter77 thank you so much for this easy to use distorsion shader. I'm really happy to use it in my current game project. Works very well and the FX iwanted s perfect ! I'm using it with 2D sprites and there is a slight problem regarding it. When I use it on 2 objects at same time (for example 2 sprites) and the Shader distorsion texture is overlaping another distorsion texture, there is ugly cut line where the 2 textures intersects and I'm wondering if it is possible to make them disappear. I saw that has to do with the Sprite Sorting layer itself and I need to tweak it to a value that is under the first distorsion rendered, but when there are 3 objects things get complicated and don't work out. Have you any solution to this ? I would appreciate it alot. Thank you for your support !
@Peter77 Oh, sorry. I'm dumb, I didn't see the new shader that works with Layers. Thank you so much, sorry for any annoyance ! Is it taking a huge performance cost for fewer number or layers, or it's fine with only max 5 distorsion at screen at same time ?
Thanks for the shader, i am trying to test this but cannot seem to see it in the camera view, it does show however in the scene view and seems to do what i would like but do not understand why it behaves this way. (Target platform is Android) EDIT : Seems playing with the Distance Fade values fixed it , i leave this here just in case someone else has this issue.
What Unity version do you use? EDIT: OK, I just checked the example. The reason why you probably don't see anything in the "Game View" other than a text saying "Press PLAY and switch to Scene View" is because I didn't implement functionality to move the camera around in playmode. If that's not what you meant, a step-by-step list how to reproduce the issue would be appreciated in order to help.