Search Unity

Distortion shader problem

Discussion in 'Shaders' started by pertsa, Apr 22, 2014.

  1. pertsa

    pertsa

    Joined:
    Jul 3, 2013
    Posts:
    15
    Hi,

    We have a shader that makes a nice lens like distortion effect. It works fine in most mobile platforms, like Asus Nexus 7 with Tegra, but freezes the fps totally in Asus Nexus 7 with Snapdragon. Both devices run Android 4.4. Any ideas what might go wrong?

    Code (csharp):
    1.  
    2. Shader "Custom/Aberration" {
    3.     Properties {
    4.         _DistortAmt  ("Distortion", Float) = 10.0
    5.         _DamageTex ("Base (RGBA)", 2D) = "white"
    6.         _DamageMin("Damage Min", float) = 0.0
    7.         _DamageMax("Damage Max", float) = 0.0
    8.     }
    9.     Category {
    10.    
    11.         // We must be transparent, so other objects are drawn before this one.
    12.         Tags { "Queue"="Transparent+1" "RenderType"="Opaque" }
    13.        
    14.         SubShader {
    15.        
    16.             // This pass grabs the screen behind the object into a texture.
    17.             // We can access the result in the next pass as _GrabTexture
    18.             GrabPass {                         
    19.                 Name "BASE"
    20.                 Tags { "LightMode" = "Always" }
    21.             }
    22.            
    23.             // Main pass: Take the texture grabbed above and use the bumpmap to perturb it
    24.             // on to the screen
    25.             Pass {
    26.                 Name "BASE"
    27.                 Tags { "LightMode" = "Always" }
    28.                 Tags { "RenderType" = "Opaque" }
    29.                 Blend SrcAlpha OneMinusSrcAlpha
    30.                 CGPROGRAM
    31.                 #pragma vertex vert
    32.                 #pragma fragment frag
    33.                 #pragma fragmentoption ARB_precision_hint_fastest
    34.                 #include "UnityCG.cginc"
    35.                     float _DistortAmt;
    36.                     sampler2D _GrabTexture;
    37.                     sampler2D _DamageTex;
    38.                     float _DamageMin;
    39.                     float _DamageMax;
    40.                     float4 _GrabTexture_TexelSize;
    41.                    
    42.                     struct appdata_t {
    43.                         float4 vertex : POSITION;
    44.                         float2 uv : TEXCOORD0;
    45.                         float3 normal : NORMAL;
    46.                     };
    47.                    
    48.                     struct v2f {
    49.                         float4 vertex : POSITION;
    50.                         float4 pos : TEXCOORD0;
    51.                         float3 normal : TEXCOORD1;
    52.                         float2 uv : TEXCOORD2;
    53.                         float view : TEXCOORD3;
    54.                     };
    55.                     v2f vert (appdata_t v) {
    56.                         v2f o;
    57.                         #if UNITY_UV_STARTS_AT_TOP
    58.                         float scale = -1.0;
    59.                         #else
    60.                         float scale = 1.0;
    61.                         #endif
    62.                        
    63.                         o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    64.                         o.uv = v.uv;
    65.                         o.pos.xy = (float2(o.vertex.x, o.vertex.y*scale)+o.vertex.w)*0.5;
    66.                         o.pos.zw = o.vertex.zw;
    67.                         o.normal = mul((float3x3)UNITY_MATRIX_MVP, v.normal);
    68.                         o.view = dot(normalize(v.normal),normalize(WorldSpaceViewDir(v.vertex)));
    69.                         return o;
    70.                     }
    71.                     half4 frag( v2f i ) : COLOR {
    72.                         float4 c = tex2D(_DamageTex, i.uv);
    73.                         float2 offset = i.normal.xy*(1.0-i.view) * _DistortAmt * _GrabTexture_TexelSize.xy;
    74.                         float4 posOrig = i.pos;
    75.                         i.pos.xy = i.pos.z * offset + i.pos.xy;
    76.                         half4 dist = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.pos));
    77.                         return half4(dist.rgb, smoothstep(_DamageMin, _DamageMax, c.r));
    78.                     }
    79.                 ENDCG
    80.             }
    81.         }
    82.         Fallback "Custom/CheapoAberration"
    83.     }
    84. }
    85.  
    br, pertsa
     
  2. pertsa

    pertsa

    Joined:
    Jul 3, 2013
    Posts:
    15
    In addition to previous, I noticed that in Android build shader worked OK on Tegra when compiled with Unity 4.2.2. But when I build with Unity 4.3.4, it drops the framerate to near zero on Tegra device too.

    br, pertti
     
  3. RC-1290

    RC-1290

    Joined:
    Jul 2, 2012
    Posts:
    639
    It might not be the performance problem you're dealing with, but I see your GrabPass doesn't specify a texture name, only a pass name, so it's doing that expensive operation every time.
     
  4. pertsa

    pertsa

    Joined:
    Jul 3, 2013
    Posts:
    15
    Well spotted and that improved things a bit. Unfortunately on device performance is still not acceptable.

    I tend to believe that we must come up with a replacement shader for the "glass" on mobile. Any tips highly appreciated.

    br, pertsa
     
  5. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Don't use grabpass on mobile, period. Instead, render to a texture, and use that.
     
  6. Aldrick

    Aldrick

    Joined:
    Feb 19, 2014
    Posts:
    64
    I find grabpass doesn't work on ios,by causing the screen black.Do you have any ideas about it?
     
  7. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    889
    A small hint only. You should use all texture lookups in the first place of code if its possible.

    Code (CSharp):
    1. half4 frag( v2f i ) : COLOR {
    2.                         float4 c = tex2D(_DamageTex, i.uv);
    3.                         half4 d = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.pos));
    4. ..
    5.                     }
    That supports the optimized memory and multi shader threading on mobil and desktop gpu.
    Should be not the solution for your issue, but can raise performance drastically.