Search Unity

Selective Distortion

Discussion in 'Shaders' started by dustinandrew, Nov 6, 2014.

  1. dustinandrew

    dustinandrew

    Joined:
    Apr 30, 2010
    Posts:
    102
    I'm using a distortion shader to create a lens effect. The only problem I have is that it distorts everything above and below it. Is there a way to only distort below and not above?

    Here is the lens normal map:


    Code (CSharp):
    1. // Per pixel bumped refraction.
    2. // Uses a normal map to distort the image behind, and
    3. // an additional texture to tint the color.
    4.  
    5. Shader "Distortion" {
    6. Properties {
    7.     _BumpAmt  ("Distortion", range (0,128)) = 10
    8.     _MainTex ("Tint Color (RGB)", 2D) = "white" {}
    9.     _BumpMap ("Normalmap", 2D) = "bump" {}
    10. }
    11.  
    12. CGINCLUDE
    13. #pragma fragmentoption ARB_precision_hint_fastest
    14. #pragma fragmentoption ARB_fog_exp2
    15. #include "UnityCG.cginc"
    16.  
    17. sampler2D _GrabTexture : register(s0);
    18. float4 _GrabTexture_TexelSize;
    19. sampler2D _BumpMap : register(s1);
    20. sampler2D _MainTex : register(s2);
    21.  
    22. struct v2f {
    23.     float4 vertex : POSITION;
    24.     float4 uvgrab : TEXCOORD0;
    25.     float2 uvbump : TEXCOORD1;
    26.     float2 uvmain : TEXCOORD2;
    27. };
    28.  
    29. uniform float _BumpAmt;
    30.  
    31.  
    32. half4 frag( v2f i ) : COLOR
    33. {
    34.     // calculate perturbed coordinates
    35.     half2 bump = UnpackNormal(tex2D( _BumpMap, i.uvbump )).rg; // we could optimize this by just reading the x & y without reconstructing the Z
    36.     float2 offset = bump * _BumpAmt * _GrabTexture_TexelSize.xy;
    37.     i.uvgrab.xy = offset * i.uvgrab.z + i.uvgrab.xy;
    38.    
    39.     half4 col = tex2Dproj( _GrabTexture, i.uvgrab.xyw );
    40.     half4 tint = tex2D( _MainTex, i.uvmain );
    41.     return col * tint;
    42. }
    43. ENDCG
    44.  
    45. Category {
    46.  
    47.     // We must be transparent, so other objects are drawn before this one.
    48.     Tags { "Queue"="Transparent" "RenderType"="Opaque" }
    49.  
    50.  
    51.     SubShader {
    52.  
    53.         // This pass grabs the screen behind the object into a texture.
    54.         // We can access the result in the next pass as _GrabTexture
    55.         GrabPass {                          
    56.             Name "BASE"
    57.             Tags { "LightMode" = "Always" }
    58.          }
    59.        
    60.          // Main pass: Take the texture grabbed above and use the bumpmap to perturb it
    61.          // on to the screen
    62.         Pass {
    63.             Name "BASE"
    64.             Tags { "LightMode" = "Always" }
    65.            
    66. CGPROGRAM
    67. #pragma vertex vert
    68. #pragma fragment frag
    69.  
    70. struct appdata_t {
    71.     float4 vertex : POSITION;
    72.     float2 texcoord: TEXCOORD0;
    73. };
    74.  
    75. v2f vert (appdata_t v)
    76. {
    77.     v2f o;
    78.     o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    79.     #if UNITY_UV_STARTS_AT_TOP
    80.     float scale = -1.0;
    81.     #else
    82.     float scale = 1.0;
    83.     #endif
    84.     o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
    85.     o.uvgrab.zw = o.vertex.zw;
    86.     o.uvbump = MultiplyUV( UNITY_MATRIX_TEXTURE1, v.texcoord );
    87.     o.uvmain = MultiplyUV( UNITY_MATRIX_TEXTURE2, v.texcoord );
    88.     return o;
    89. }
    90. ENDCG
    91.         }
    92.     }
    93.  
    94.     // ------------------------------------------------------------------
    95.     // Fallback for older cards and Unity non-Pro
    96.    
    97.     SubShader {
    98.         Blend DstColor Zero
    99.         Pass {
    100.             Name "BASE"
    101.             SetTexture [_MainTex] {    combine texture }
    102.         }
    103.     }
    104. }
    105.  
    106. }
    107.  
     
    mikelortega and domkia like this.
  2. dustinandrew

    dustinandrew

    Joined:
    Apr 30, 2010
    Posts:
    102
    Well, minutes after posting this, I found out that I have a sprite with a layer order that was making it render before the lens and get the distortion. So nevermind then, but here is a lens distortion and normal map if anyone needs it lol
     
  3. DanSuperGP

    DanSuperGP

    Joined:
    Apr 7, 2013
    Posts:
    408
    Hmm, it's not working for me. Were you applying this on a quad or a sprite?
     
  4. dustinandrew

    dustinandrew

    Joined:
    Apr 30, 2010
    Posts:
    102
    The distortion material was on a quad rendered between sprite layers.
     
  5. DanSuperGP

    DanSuperGP

    Joined:
    Apr 7, 2013
    Posts:
    408
    Thanks so much.

    It works wonderfully in Unity 4.6

    And not at all in Unity 5... crap...
     
  6. ai_enabled

    ai_enabled

    Joined:
    Sep 16, 2013
    Posts:
    15
    DanSuperGP, it works in Unity 5, the fix is pretty simply:
    replace
    Code (csharp):
    1. tex2Dproj( _GrabTexture, uvgrab.xyw);
    with
    Code (csharp):
    1. tex2Dproj( _GrabTexture, uvgrab.xyww);
     
  7. DanSuperGP

    DanSuperGP

    Joined:
    Apr 7, 2013
    Posts:
    408
    So awesome, thanks!