Search Unity

Alpha pixels being cut out in simple uv shift shader

Discussion in 'Shaders' started by cjddmut, Oct 20, 2015.

  1. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    179
    We have clouds in a game that are being animated by shifting the x uv during runtime. They are using sprite renderers! I wrote a very simple shader that accomplishes this except there's one issue, where the original transparent pixels are is being cut out. Is there a property or something or is this a limitation of sticking with the sprite renderer? (I understand I can create a quad mesh with the texture but there are some nice freebies with using sprites such as packing).

    Clouds.gif
    Note the bottom pixels being cut out where the original clouds are transparent!
    Here's the shader I wrote, maybe I am doing something dumb :)

    Code (CSharp):
    1. Shader "Custom/ShiftXUV"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Sprite Texture", 2D) = "white" {}
    6.         _maxSpeed ("Max Speed", Float) = 0
    7.     }
    8.     SubShader
    9.     {
    10.         Tags
    11.         {
    12.             "Queue"="Transparent"
    13.             "IgnoreProjector"="True"
    14.             "RenderType"="Transparent"
    15.             "PreviewType"="Plane"
    16.             "CanUseSpriteAtlas"="True"
    17.         }
    18.  
    19.         Cull Off
    20.         Lighting Off
    21.         ZWrite Off
    22.         Fog { Mode Off }
    23.         Blend One OneMinusSrcAlpha
    24.  
    25.         Pass
    26.         {
    27.             CGPROGRAM
    28.             #pragma vertex vert
    29.             #pragma fragment frag
    30.          
    31.             struct appdata
    32.             {
    33.                 float4 vertex : POSITION;
    34.                 half2 uv : TEXCOORD0;
    35.                 fixed3 speedAmount : COLOR;
    36.             };
    37.  
    38.             struct v2f
    39.             {
    40.                 float4 vertex : SV_POSITION;
    41.                 half2 texCoord : TEXCOORD0;
    42.                 fixed3 speedAmount : COLOR;
    43.             };
    44.  
    45.             sampler2D _MainTex;
    46.             uniform float _maxSpeed;
    47.             uniform float _time;
    48.          
    49.             v2f vert (appdata v)
    50.             {
    51.                 v2f o;
    52.                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    53.                 o.texCoord = v.uv;
    54.                 o.speedAmount = v.speedAmount;
    55.                 return o;
    56.             }
    57.          
    58.             fixed4 frag (v2f i) : SV_Target
    59.             {
    60.                 float2 uv = i.texCoord;
    61.                 uv.x = frac(uv.x + i.speedAmount.x * _maxSpeed * _time);
    62.  
    63.                 fixed4 col = tex2D(_MainTex, uv);
    64.                 col.rgb *= col.a;
    65.                 return col;
    66.             }
    67.             ENDCG
    68.         }
    69.     }
    70. }
    71.  
    Thanks!
     
    Last edited: Oct 20, 2015
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,336
    Nothing strikes me as wrong in the shader in terms of what would cause what you're seeing, though I don't do anything with sprites.

    A few notes though:
    • I would try to do most of the UV offset code in vert instead of in frag. This might solve the transparency issue you're seeing as well. Don't do a frac() on the whole uv in the vert shader though, rather uv + frac(speed * max * time);
    • You're using float _time, I assume this is something you're passing in yourself? You can just use _Time.y (it's a float4, use capital T, .y component not .x) instead as that's passed to all shaders automatically. http://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
    • Using a sprite atlas on panning materials is semi-dangerous. Once it's atlased there's no knowing where the actual bounds of the texture are so things like frac() to wrap the UVs as the texture is no longer between uvs 0.0 and 1.0, it might be between 0.25 and 0.375.
     
    cjddmut likes this.
  3. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    179
    Thanks for the tips!

    I didn't know about _Time.y and you're absolutely right that I'll run into issues once I actually atlas the different images. Unfortunately, even if I shift uvs in the vert function, I still have the alpha cut out where the original alpha pixels were so that doesn't solve that issue. :(
     
  4. Wompipomp

    Wompipomp

    Joined:
    Aug 31, 2014
    Posts:
    24
    Hi,

    if it helps you, your shader works for me and my "cloud" :)
    I made a arbitrary form with transparency and saved it as png. Afterwards I imported it as sprite and put it into the scene with your shader set in the sprite renderer and the shader works for me. No artifacts or similar.
    Maybe there is some problem with the image you are using or how you imported it.

    Cloud.png
     
  5. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    179
    I'll give it a shot!