Search Unity

UV Offset Region Shader

Discussion in 'Shaders' started by dandeentremont, Sep 7, 2014.

  1. dandeentremont

    dandeentremont

    Joined:
    Jan 11, 2013
    Posts:
    16
    Hello everyone,

    I've built a little shader that allows UV offset animation on a specific rectangular region of a bitmap. It was mostly for personal enrichment, but it could also be good for saving a draw call or two.


    Code (csharp):
    1.  
    2. //ddUVOffetRegion shader: Daniel DeEntremont (dandeentremont@gmail.com)
    3. //Specify a rectangular region in a bitmap, which can be U/V offsetted independent of the rest of the bitmap!
    4. //Use the "Display Region" slider to show a green rectangle where the effect will take place.
    5. //Warning: Things get weird when the rectangle's min values are larger than the max values (You'll know when because the rectangle will become purple).
    6.  
    7. Shader "Custom/ddUVOffsetRegion" {
    8.     Properties {
    9.         _MainTex ("Base (RGB)", 2D) = "white" {}
    10.        
    11.         _DisplayRegion ("DisplayRegion", Range (0.0, 0.5) ) = 1
    12.         _RectMinX ("Rectangle Min X (Percent)", Float) = 25
    13.         _RectMaxX ("Rectangle Max X (Percent)", Float) = 75
    14.         _RectMinY ("Rectangle Min y (Percent)", Float) = 25
    15.         _RectMaxY ("Rectangle Max Y (Percent)", Float) = 75
    16.        
    17.         _OffsetU ("Offset U", Float) = 0
    18.         _OffsetV ("Offset V", Float) = 0
    19.        
    20.     }
    21.     SubShader {
    22.         Tags { "RenderType"="Opaque" }
    23.         LOD 200
    24.        
    25.         Cull Off
    26.        
    27.         CGPROGRAM
    28.         #pragma surface surf Lambert
    29.  
    30.         sampler2D _MainTex;
    31.         fixed _DisplayRegion;
    32.        
    33.         fixed _RectMinX;
    34.         fixed _RectMaxX;
    35.         fixed _RectMinY;
    36.         fixed _RectMaxY;
    37.        
    38.         fixed _OffsetU;
    39.         fixed _OffsetV;
    40.        
    41.         struct Input
    42.         {
    43.             float2 uv_MainTex;
    44.         };
    45.  
    46.         void surf (Input IN, inout SurfaceOutput o)
    47.         {
    48.             //Below divides all rectangle parameters by 100, so they are not super-sensitive in the unity editor
    49.             _RectMinX/=100;
    50.             _RectMaxX/=100;
    51.             _RectMinY/=100;
    52.             _RectMaxY/=100;
    53.            
    54.             //preRect x and y each represent 1 dimensional min and max ranges for rectangle. When they are multiplied together, they form a white rectangle mask (where they intersect).
    55.             float2 preRect;
    56.             preRect.x = (IN.uv_MainTex.x > _RectMinX) - (IN.uv_MainTex.x > _RectMaxX);
    57.             preRect.y = (IN.uv_MainTex.y > _RectMinY) - (IN.uv_MainTex.y > _RectMaxY);
    58.             half rectMask = preRect.x * preRect.y;
    59.            
    60.             //uv_OffsetCoord.x and y copy the uv coordinates of the main texture and are offsetted.
    61.             //Then, the old uv coordinates are blended with the new uv coordinates, using the rectangle as a mask.
    62.             float2 uv_OffsetCoord = IN.uv_MainTex;
    63.            
    64.             //add minimum rectangle limits so the region's lowest UV value is 0
    65.             uv_OffsetCoord.x -= _RectMinX;
    66.             uv_OffsetCoord.y -= _RectMinY;
    67.            
    68.             //multiply values so the highest UV value of the region is 1. Now the region is normalized to a 0-1 range.
    69.             uv_OffsetCoord.x *= (1 / ( _RectMaxX - _RectMinX ) );
    70.             uv_OffsetCoord.y *= (1 / ( _RectMaxY - _RectMinY ) );
    71.            
    72.            
    73.             //Offset the newly normalized coordinates.  
    74.             uv_OffsetCoord.x += _OffsetU;
    75.             uv_OffsetCoord.y += _OffsetV;
    76.            
    77.             //So now, the problem is, offsetting will cause the UV values will go lower than 0 or higher than 1.
    78.             //Well, fortunately, we can use frac() to continuously repeat the texture (between 0 and 1) forever!
    79.             uv_OffsetCoord.x = frac(uv_OffsetCoord.x);
    80.             uv_OffsetCoord.y = frac(uv_OffsetCoord.y);
    81.            
    82.             //Below runs the normalization process in reverse
    83.             uv_OffsetCoord.x *= ( _RectMaxX - _RectMinX );
    84.             uv_OffsetCoord.y *= ( _RectMaxY - _RectMinY );
    85.            
    86.             uv_OffsetCoord.x += _RectMinX;
    87.             uv_OffsetCoord.y += _RectMinY;
    88.            
    89.             //Blend old uv coordinates with new offsetted uv coordinates, using the rectangle as a mask
    90.             IN.uv_MainTex = (IN.uv_MainTex * (1-rectMask) ) + (uv_OffsetCoord * rectMask);
    91.            
    92.             //Apply image map to blended UV coordinates
    93.             half4 c = tex2D (_MainTex, IN.uv_MainTex);
    94.            
    95.             //displays additive green rectangle for setup
    96.             c.g += (rectMask * _DisplayRegion);
    97.            
    98.             o.Albedo = c.rgb;
    99.             o.Alpha = c.a;
    100.         }
    101.         ENDCG
    102.     }
    103.     FallBack "Diffuse"
    104. }
    105.  
     

    Attached Files:

    skullthug likes this.
  2. tealm

    tealm

    Joined:
    Feb 4, 2014
    Posts:
    45
    Awesome stuff man! I haven't tried it out yet - but looks very promising! Thanks for sharing.
     
  3. zt3ff3n

    zt3ff3n

    Joined:
    Feb 19, 2016
    Posts:
    17
    Old thread, I know. But this shader deserves more attention.
    I'm looking for a shader that allows this regional animation, but still has slots for emission, spec, etc.

    Would OP - or someone more talented than me know how to do it?
     
    JBR-games likes this.
  4. JBR-games

    JBR-games

    Joined:
    Sep 26, 2012
    Posts:
    559
    Would be great if it worked with PBR... Textures
     
  5. Quakeulf

    Quakeulf

    Joined:
    Mar 26, 2013
    Posts:
    40
    The is geniouse. :3