Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Shader for animated tiles

Discussion in 'Shaders' started by Biktor, Oct 22, 2014.

  1. Biktor

    Biktor

    Joined:
    Apr 10, 2014
    Posts:
    7
    I'm a noob in shaders programming, making a game with 2DToolkit and I want to get a shader to animate tiles in a tilemap ( I know I could control the animation with c# script but I want to do with a shader)

    Is this possible?
    Here is my shader:

    Code (CSharp):
    1. Shader "Custom/AnimSprite"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Main Texture (RGB)", 2D) = "white" {}
    6.      
    7.         // Create the properties below
    8.         _TotalFrames ("Total FRames", float) = 0.0
    9.         _InitFrame ("Init Frame", float) = 0.0
    10.         _FPS ("FPS", float) = 0.0
    11.     }
    12.     SubShader
    13.     {
    14.         Tags { "RenderType"="Opaque" }
    15.         LOD 200
    16.      
    17.         CGPROGRAM
    18.         #pragma surface surf Lambert
    19.  
    20.         sampler2D _MainTex;
    21.      
    22.         //Create the connection to the properties inside of the
    23.         //CG program
    24.         float _TotalFrames;
    25.         float _InitFrame;
    26.         float _FPS;
    27.    
    28.         int _Tick;
    29.  
    30.         struct Input
    31.         {float2 uv_MainTex;};
    32.  
    33.         void surf (Input IN, inout SurfaceOutput o)
    34.         {
    35.             //Lets store our UVs in a seperate variable
    36.             float2 spriteUV = IN.uv_MainTex;
    37.          
    38.             //Lets calculate the width of a single frame in our
    39.             //sprite sheet and get a uv percentage that each frame takes up.
    40.             float frameUVPercentage = 1.0/_TotalFrames;
    41.          
    42.             //Animate the uv's tiling
    43.             float xValue = spriteUV.x;
    44.        
    45.             _Tick = _Time.y * _FPS;
    46.        
    47.             xValue += frameUVPercentage * _Tick;
    48.  
    49.             spriteUV = float2(xValue, spriteUV.y);
    50.          
    51.             half4 c = tex2D (_MainTex, spriteUV);
    52.             o.Albedo = c.rgb;
    53.             o.Alpha = c.a;
    54.         }
    55.         ENDCG
    56.     }
    57.     FallBack "Diffuse"
    58. }
    Using _Time.y the _Tick is increasing and I don't know how to reset the _Tick value.
    I have read about the use of sin with _Time but my idea is increasing the texture tiling and upon reaching at the final tiling, reset the tiling to the first tile.

    Something like that:



    Thank you.
     
    Last edited: Oct 23, 2014
  2. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    You'll have to do it with a script. Shaders don't have global variables that they can set, so there is no option to reset the _Tick value. All global variables should be supplied externally. In other words, a shader has no memory. I doesn't know what it did last frame.

    If you let the time control the uv directly, you could do something like this:
    Code (csharp):
    1.  
    2. spriteUV.x = (spriteUV.x + (frac(_Time.y * speed) * 10.0)) / 10.0;
    3.  
     
  3. Biktor

    Biktor

    Joined:
    Apr 10, 2014
    Posts:
    7
    Thank you very much jvo3dc, now I understand better the shader's operations.
     
  4. Biktor

    Biktor

    Joined:
    Apr 10, 2014
    Posts:
    7
    Here is a new version, closer from my target, but...

    Code (CSharp):
    1. Shader "Custom/AnimSprite"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Main Texture (RGB)", 2D) = "white" {}
    6.        
    7.         // Create the properties below
    8.         _TotalFrames ("Total FRames", float) = 0.0
    9.         _FPS ("FPS", float) = 0.0
    10.     }
    11.     SubShader
    12.     {
    13.         Tags { "RenderType"="Opaque" }
    14.         LOD 200
    15.        
    16.         CGPROGRAM
    17.         #pragma surface surf Lambert
    18.  
    19.         sampler2D _MainTex;
    20.        
    21.         //Create the connection to the properties inside of the
    22.         //CG program
    23.         float _TotalFrames;
    24.         float _FPS;
    25.      
    26.         float _Tick;
    27.  
    28.         struct Input
    29.         {float2 uv_MainTex;};
    30.  
    31.         void surf (Input IN, inout SurfaceOutput o)
    32.         {  
    33.             //ANIMATION
    34.             //Lets calculate the width of a single cell in our
    35.             //sprite sheet and get a uv percentage that each cel takes up.
    36.             float frameUVPercentage = 1.0/_TotalFrames;
    37.             //Lets store our UVs in a variable
    38.             float2 spriteUV = IN.uv_MainTex;
    39.             _Tick = frac(( _Time.y + spriteUV.x ) * _FPS) - frameUVPercentage;
    40.             spriteUV.x = (( spriteUV.x + frameUVPercentage ) + ( 0 * frameUVPercentage ) ) + ( floor( _Tick * _TotalFrames ) * frameUVPercentage );
    41.            
    42.             half4 c = tex2D (_MainTex, spriteUV);
    43.             o.Albedo = c.rgb;
    44.             o.Alpha = c.a;
    45.         }
    46.         ENDCG
    47.     }
    48.     FallBack "Diffuse"
    49. }
    Here the package:
     

    Attached Files: