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. Dismiss Notice

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!