A waving texture?

Does anyone know how to make a waving texture?

I’m actually working with a 2D game and I’ve not worked with materials in Unity before, but I’m thinking I could really use some sort of waving effect on this one tile to animate it.

Something like this: http://youtu.be/IlqcEvX4MCI?t=9s
Or if I could just have it wave in the X axis, that would work too.

I have no idea how to go about doing this though. Is this even possible?

This looks like UV distortion to me. If you have a rather evenly tessellated grid, just add an offset to each vertex UV using sin/cos functions in the vertex shader for example. Use the original UV’s also as input for sin/cos to make it look more chaotic, as well as _Time to get the animation.

Rather than per vertex UV distortion, you can could also use per-pixel distortion as shown in the following presentation, starting at slide 36: http://www.gdcvault.com/play/1015898...Up-Our-Sleeves

Edit: Since I’m a fan of distortion shaders, I couldn’t resist to throw together a quick example. Assign a material with the following shader to a Plane GameObject and it looks like this:

Shader "Custom/NewShader" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
     
        CGPROGRAM
        #pragma surface surf Lambert vertex:vert

        sampler2D _MainTex;
        float4 _MainTex_ST;

        struct Input {
            float2 st_MainTex;
        };

        void vert (inout appdata_full v, out Input o)
        {
            UNITY_INITIALIZE_OUTPUT(Input,o);

            o.st_MainTex = TRANSFORM_TEX(v.texcoord, _MainTex);

            // add distortion
            // this is the part you need to modify, i  recomment to expose such
            // hard-coded values to the inspector for easier tweaking.
            o.st_MainTex.x += sin((o.st_MainTex.x+o.st_MainTex.y)*8 + _Time.g*1.3)*0.01;
            o.st_MainTex.y += cos((o.st_MainTex.x-o.st_MainTex.y)*8 + _Time.g*2.7)*0.01;
        }

        void surf (Input IN, inout SurfaceOutput o) {
            half4 c = tex2D (_MainTex, IN.st_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

Hope it helps!

1 Like

I know this was a month ago, but after I got that answer I realized I had no idea what I was doing with shaders.
I’m just now starting to learn them.

I tried plugging that shader into my game, but it does nothing.
What am I doing wrong?

Maybe your grid does not have enough vertex count (something like a 4 vertices plane)?
Try move the changing of coordinates part in the surface block, something like this:
void surf (Input IN, inout SurfaceOutput o) {
IN.st_MainTex.x + = sin ((o.st_MainTex.x + o.st_MainTex.y) * 8 + _Time.g * 1.3) * 0.01;
IN.st_MainTex.y + = cos ((o.st_MainTex.xo.st_MainTex.y) * 8 + _Time.g * 2.7) * 0.01;
half4 c = tex2D (_MainTex, IN.st_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}

I tried using it on a default plane, but it still didn’t have any effect.

I tried replacing the surf function with the one you posted and the material broke and turned into magenta.

It’s should work fine:

Shader "Custom/NewShader" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _SpeedX("SpeedX", float)=3.0
        _SpeedY("SpeedY", float)=3.0
        _Scale("Scale", range(0.005, 0.2))=0.03
        _TileX("TileX", float)=5
        _TileY("TileY", float)=5
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
       
        CGPROGRAM
        #pragma surface surf Lambert

        sampler2D _MainTex;
        float4 uv_MainTex_ST;

        float _SpeedX;
        float _SpeedY;
        float _Scale;
        float _TileX;
        float _TileY;

        struct Input {
            float2 uv_MainTex;
        };


        void surf (Input IN, inout SurfaceOutput o)
        {
            float2 uv = IN.uv_MainTex;
            uv.x += sin ((uv.x+uv.y)*_TileX+_Time.g *_SpeedX)*_Scale; 
            uv.x += cos (uv.y*_TileY+_Time.g *_SpeedY)*_Scale; 

            half4 c = tex2D (_MainTex, uv); 
            o.Albedo = c.rgb; 
            o.Alpha = c.a; 
        }
        ENDCG
    }
    FallBack "Diffuse"
}
2 Likes

Hey, it’s fantastic!
Easy-to-tweak variables, and it even runs on my android!
The only thing I need now is to make it unlit.

This shader works great for 2D water. I’m not that familiar with shaders however and am wondering how one could add transparency to this.

(This is really old but I just found it, so answering in case anyone still cares)

See where it says o.Alpha near the bottom? Instead of just setting that to c.a, set it to c.a*_Opacity, with _Opacity being another range slider like _Scale, only ranging 0 to 1.

Or, I guess that’s not even necessary if you put alpha transparency in the texture. Meanwhile, the depth sorting needs to be adjusted so that it’ll display transparent. So replace the Tags line with:

Tags { “RenderType”=“Transparent” “Queue”=“Transparent” }
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha

I actually do appreciate getting an answer to this issue. Of course, Unity has changed so much since then that the effect I was trying to create is no longer relevant through this process; there are better ways to achieve what I want.
But it is actually pleasing to see an answer to this problem I had way back when.
And hey, maybe I will want to use this effect in a future project.