Search Unity

waving flag shader: feedback please!

Discussion in 'Shaders' started by cboe, Mar 22, 2009.

  1. cboe

    cboe

    Joined:
    Nov 18, 2008
    Posts:
    15
    hi, i've just written my first shader, it's for displaying a waving flag. here's the code:

    if someone with more experience could check my code and has any suggestions on how to improve it, i'd be very grateful

    Code (csharp):
    1. Shader "Selfmade/FlagWave"
    2. {
    3.  
    4. Properties
    5. {
    6.     _Color ("Main Color", Color) = (1,1,1,1)
    7.     _MainTex ("Texture", 2D) = "white" { }
    8. }
    9.  
    10. SubShader
    11. {
    12.     Pass
    13.     {
    14.         CULL Off
    15.        
    16.         CGPROGRAM
    17.         #pragma vertex vert
    18.         #pragma fragment frag
    19.         #include "UnityCG.cginc"
    20.         #include "AutoLight.cginc"
    21.        
    22.         float4 _Color;
    23.         sampler2D _MainTex;
    24.        
    25.         //float4 _Time;
    26.        
    27.         // vertex input: position, normal
    28.         struct appdata {
    29.             float4 vertex : POSITION;
    30.             float4 texcoord : TEXCOORD0;
    31.         };
    32.        
    33.         struct v2f {
    34.             float4 pos : POSITION;
    35.             float2 uv: TEXCOORD0;
    36.         };
    37.        
    38.         v2f vert (appdata v) {
    39.             v2f o;
    40.            
    41.             float angle= _Time * 50;
    42.            
    43.             v.vertex.y =  v.texcoord.x * sin(v.vertex.x + angle);
    44.             v.vertex.y += sin(v.vertex.z / 2 + angle);
    45.             v.vertex.y *= v.vertex.x * 0.1f;
    46.            
    47.             o.pos = mul( glstate.matrix.mvp, v.vertex );
    48.             o.uv = v.texcoord;
    49.             return o;
    50.         }
    51.        
    52.         float4 frag (v2f i) : COLOR
    53.         {
    54.             half4 color = tex2D(_MainTex, i.uv);
    55.             return color;
    56.         }
    57.  
    58.         ENDCG
    59.        
    60.  
    61.         //SetTexture [_MainTex] {combine texture}
    62.     }
    63. }
    64. Fallback "VertexLit"
    65. }

    thx
     
  2. anti-alias

    anti-alias

    Joined:
    Nov 8, 2008
    Posts:
    62
    Hello cboe,

    it is quite nice. As improvement I would make 1 edge of the flag fixed as in reality.
     
  3. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Was any progress made on this? I would be a useful shader if it was pinned at the side the flag was attached to the pole.

    EDIT: ok, this shader doesn't work or do anything. I know it was written a long time ago, but has anyone got any ideas as to whats wrong with it in Unity 2.6.1 ?

    Cheers :)
     
  4. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Hello Seon,

    This sort of shader is used in often in vertex shader 101 tutorials. You can probably find numerous example shaders, maybe even pinned to one side as you want, searching about with google.

    In fact I think the first time I saw one was on NeHe's famous OpenGL tutorial site. I remember it giving good insight in to how it works.

    http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=11
     
  5. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    There's nothing wrong with it...works fine as-is.

    --Eric
     
  6. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Hmm, i have it applied to a mesh and its not doing anything :(

    I must be missing something very obvious!

    I have a flag mesh, i have created a material for it called flag, have selected the FlagWave shader for it, and have added a texture to the texture slot.

    I see NO movement and I see no flag, other than when I select the object, i see the wireframe of the mesh.
     
  7. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Does your mesh have a reasonable number of vertices so the effect has something to work with? And you pressed Play? Also, one end of the flag can be pinned if you create the mesh the right way, such as using this.

    --Eric
     
  8. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    yes, i think its enough. here is an example image.



    and here is a screenie of my editor panel

     
  9. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Ok, I got it working just using that pane creation script, but the same settings on my flag mesh don't do anything... oh well!

    Thanks for your help Eric!
     
  10. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    The mesh is oriented wrong...the shader is animating the vertex.y coordinates. You can rotate the mesh vertical, but it has to be created as a horizontal plane.

    --Eric
     
  11. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Yeah, I finally worked that out myself. Figures! My Trig is S***e! So didnt really glance in that area of the shader to see it was trying to displace the wrong axis.

    So, now that I have established that my trig is S***e... I want to get the flag displacing on the z axis too (and maybe even the x) to give it 3 axis movement.

    Anyone wanna give the math a try? my attempts so far are moving the z correctly, but squishing the flag on the z too...

    Code (csharp):
    1. v.vertex.z =  v.texcoord.x * cos(v.vertex.x + angle); // this is where I am going wrong I think....
    2. v.vertex.z += cos(v.vertex.x / 2 + angle);
    3. v.vertex.z *= v.vertex.x * 0.1f; // ok, this is scaling movement down closer to U = 0
    4.  
    Suggestions?
     
  12. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Can you just clarify exactly what you are doing here? Are you aiming to get a single ripple (from the cosine shape) that runs from the top of the flag to the bottom?
     
  13. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Well yes, though wether its Cos or Sin, I have no idea!

    I was to extend the maths in the original shader to add an extra ripple from V0 - V1 that is also stronger at U1 and muted at U0.

    I have found some different math code (online) that ripples really well and has adjustments for ripples on 3 axis, but again it produces the same results on all axis other than y.

    Code (csharp):
    1.       float sinOff=v.vertex.x+v.vertex.y+v.vertex.z;
    2.       float t=-_Time*50;
    3.       float sin1=sin(t*1.45+sinOff);
    4.       float sin2=sin(t*3.12+sinOff);
    5.       float sin3=sin(t*2.2+sinOff);
    6.       float fx=v.texcoord.x;
    7.       float fy=v.texcoord.x*v.texcoord.y;
    8.  
    9.       //v.vertex.x=sin1*fx*0.5;
    10.       v.vertex.y=sin2*fx*0.5-fy*0.9;
    11.       v.vertex.z=-sin3*fx*0.5;
    12.  
    Produces this result:-


    Now commenting out this line puts it back to single y axis ripple that works fine.

    Code (csharp):
    1.  //v.vertex.z=-sin3*fx*0.5;
    Produces this result:-



    My parents used to tell me in school that I needed to pay attention in Maths classes and I used to argue, what's the point, like I am ever going to use this stuff in the real world! Sheesh... life is full of regrets hey !
     
  14. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    You shouldn't set vertex.y at any point - this is what is squashing the flag. If you want a two-dimensional ripple, add the two sin values together and assign them to vertex.z:-
    Code (csharp):
    1.  v.vertex.z = sin3*fx*0.5 + sin2*fx*0.5;
    ...or something along those lines.
     
  15. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Hey Andeee, it's Y I need in this case because of how the mesh is created (as a flat X*Z plane).

    Ok, I have it working now, I was replacing X Z values rather that adding to them. That didn't work, this does!

    Quicktime movie of flag blowing - http://games.sector3.com.au/examples/flag_blowing.mov.zip

    Here is a new shader that animates flag on all axis, and works a treat!

    Code (csharp):
    1. // Original shader by cboe - Mar, 23, 2009
    2. // Enhanced to 3 axis movement by Seon - Jan, 21, 2010
    3. //
    4. // Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
    5. // Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.  
    6. //
    7. // Enjoy!
    8.  
    9. Shader "Selfmade/FlagWave"
    10. {
    11.  
    12. Properties
    13. {
    14.     _Color ("Main Color", Color) = (1,1,1,1)
    15.     _MainTex ("Texture", 2D) = "white" { }
    16. }
    17.  
    18. SubShader
    19. {
    20.     Pass
    21.     {
    22.        CULL Off
    23.        
    24.       CGPROGRAM
    25.       #pragma vertex vert
    26.       #pragma fragment frag
    27.       #include "UnityCG.cginc"
    28.       #include "AutoLight.cginc"
    29.        
    30.       float4 _Color;
    31.       sampler2D _MainTex;
    32.  
    33.       // vertex input: position, normal
    34.       struct appdata {
    35.           float4 vertex : POSITION;
    36.           float4 texcoord : TEXCOORD0;
    37.       };
    38.        
    39.       struct v2f {
    40.           float4 pos : POSITION;
    41.           float2 uv: TEXCOORD0;
    42.       };
    43.        
    44.       v2f vert (appdata v) {
    45.           v2f o;
    46.  
    47.           float sinOff=v.vertex.x+v.vertex.y+v.vertex.z;
    48.           float t=-_Time*50;
    49.           float fx=v.texcoord.x;
    50.           float fy=v.texcoord.x*v.texcoord.y;
    51.  
    52.           v.vertex.x+=sin(t*1.45+sinOff)*fx*0.5;
    53.           v.vertex.y=sin(t*3.12+sinOff)*fx*0.5-fy*0.9;
    54.           v.vertex.z-=sin(t*2.2+sinOff)*fx*0.2;
    55.    
    56.           o.pos = mul( glstate.matrix.mvp, v.vertex );
    57.           o.uv = v.texcoord;
    58.  
    59.          return o;
    60.       }
    61.        
    62.       float4 frag (v2f i) : COLOR
    63.       {
    64.          half4 color = tex2D(_MainTex, i.uv);
    65.          return color;
    66.       }
    67.  
    68.       ENDCG
    69.  
    70.       SetTexture [_MainTex] {combine texture}
    71.     }
    72. }
    73.     Fallback "VertexLit"
    74. }
     
  16. ggunhouse

    ggunhouse

    Joined:
    Nov 18, 2009
    Posts:
    59
    I've used this shader in my Virtual Egyptian Temple (http://www.medievalist.net/unityworlds/egyptiantemple.htm). I've been searching for a way to make the flags wave for ages, so I was very glad to find this shader here. Ideally, I'd like to have each of the four flags be a little out-of-synch with the others. If anyone can advise me how I might do that, I'd appreciate it (I am new to Unity). Thanks again.
     
  17. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I made the small addition of a WaveSpeed variable, so you can make different materials which have slightly different speeds:

    Code (csharp):
    1. // Original shader by cboe - Mar, 23, 2009
    2. // Enhanced to 3 axis movement by Seon - Jan, 21, 2010
    3. // Added _WaveSpeed - Jan, 26, 2010
    4. //
    5. // Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
    6. // Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.  
    7. //
    8. // Enjoy!
    9.  
    10. Shader "Selfmade/FlagWave"
    11. {
    12.  
    13. Properties
    14. {
    15.     _Color ("Main Color", Color) = (1,1,1,1)
    16.     _MainTex ("Texture", 2D) = "white" { }
    17.     _WaveSpeed ("Wave Speed", Range(0.0, 150.0)) = 50.0
    18. }
    19.  
    20. SubShader
    21. {
    22.     Pass
    23.     {
    24.        CULL Off
    25.        
    26.       CGPROGRAM
    27.       #pragma vertex vert
    28.       #pragma fragment frag
    29.       #include "UnityCG.cginc"
    30.       #include "AutoLight.cginc"
    31.        
    32.       float4 _Color;
    33.       sampler2D _MainTex;
    34.       float _WaveSpeed;
    35.  
    36.       // vertex input: position, normal
    37.       struct appdata {
    38.           float4 vertex : POSITION;
    39.           float4 texcoord : TEXCOORD0;
    40.       };
    41.        
    42.       struct v2f {
    43.           float4 pos : POSITION;
    44.           float2 uv: TEXCOORD0;
    45.       };
    46.        
    47.       v2f vert (appdata v) {
    48.           v2f o;
    49.  
    50.         float sinOff=v.vertex.x+v.vertex.y+v.vertex.z;
    51.         float t=-_Time*_WaveSpeed;
    52.         float fx=v.texcoord.x;
    53.         float fy=v.texcoord.x*v.texcoord.y;
    54.  
    55.         v.vertex.x+=sin(t*1.45+sinOff)*fx*0.5;
    56.         v.vertex.y=sin(t*3.12+sinOff)*fx*0.5-fy*0.9;
    57.         v.vertex.z-=sin(t*2.2+sinOff)*fx*0.2;
    58.    
    59.           o.pos = mul( glstate.matrix.mvp, v.vertex );
    60.           o.uv = v.texcoord;
    61.  
    62.          return o;
    63.       }
    64.        
    65.       float4 frag (v2f i) : COLOR
    66.       {
    67.          half4 color = tex2D(_MainTex, i.uv);
    68.          return color;
    69.       }
    70.  
    71.       ENDCG
    72.  
    73.       SetTexture [_MainTex] {combine texture}
    74.     }
    75. }
    76.    Fallback "VertexLit"
    77. }
    --Eric
     
  18. ggunhouse

    ggunhouse

    Joined:
    Nov 18, 2009
    Posts:
    59
    Thanks for that update Eric. It's just what I was hoping for. Unfortunately, it is not working perfectly for me. Here's what happens:
    - I change the material of one of the flags and change the speed of its waving. That works. I end up with one of my four flags waving at a different rate from the others, both in the editor and in the web player.
    - I change the material on another flag and change the speed of its waving. That works when I play the scene in the editor. I see two of the flags waving at different rates from each other and from the original setting (so, three different rates of flag waving). However, I only see this when playing the scene in the editor. If I build the scene to view it in the web player, the last flag I set does not wave independently. Its rate is identical to the rate of the first flag I changed. In other words, there are only two rates of flag waving (the original rate, and the first one I changed). When I return from the web player to the editor, I find that the level I set for the last flag has changed to be equal to the setting for the first flag I changed. Hope that makes sense.
    Perhaps I'm doing something wrong, or maybe there's a bug somewhere.
     
  19. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    The wave speed is part of the material, so you need a different material for each flag that should have a different speed. If you change the speed in one material, it changes for every object using that material.

    --Eric
     
  20. ggunhouse

    ggunhouse

    Joined:
    Nov 18, 2009
    Posts:
    59
    My previous message must not have been clear. I HAVE assigned three different materials, and set three different wave speeds. What I'm saying is that the third wave speed, though it starts out different, re-sets to match the speed I assigned to one of the other materials. I end up with two of my materials having exactly the same wave speed, though I had originally set them at different speeds. This happens after I build the web-player version. Do you not get this odd result? I've tried it over and over again and the result is always the same for me.
     
  21. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Apparently not...I tried this and they're waving at different speeds.

    --Eric
     
  22. ggunhouse

    ggunhouse

    Joined:
    Nov 18, 2009
    Posts:
    59
    I'll try some different things at my end, and test it on a different machine. In any case, I'm pretty satisfied with having the flags wave at two different speeds. That's an improvement over having them all in synch. So thanks again for the update.
     
  23. Ayrik

    Ayrik

    Joined:
    Aug 31, 2008
    Posts:
    430
    This shader seems to work great, but it doesn't recalculate the normals. I've tried to do a few things, but I don't know enough about Unity's shader system to write anything. I spent quite a bit of time getting it to work but couldn't. Any chance anyone would want to help me with that?
     
  24. fontmaster

    fontmaster

    Joined:
    Dec 8, 2009
    Posts:
    1
    Following Eric5h5 implementation I did a little ajustment in time value function because flag animation looks bouncy.

    I changed the slider WaveLength value to a float WaveLength number value.

    Enjoy!


    Code (csharp):
    1. // Original shader by cboe - Mar, 23, 2009
    2. // Enhanced to 3 axis movement by Seon - Jan, 21, 2010
    3. // Added _WaveSpeed - Jan, 26, 2010 Eric5h5
    4. // Ajustement time function - April, 19, 2010 Fontmaster
    5. //
    6. // Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
    7. // Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.
    8. //
    9. // Enjoy!
    10.  
    11. Shader "FX/FlagWave"
    12. {
    13.  
    14. Properties
    15. {
    16.     _Color ("Main Color", Color) = (1,1,1,1)
    17.     _MainTex ("Texture", 2D) = "white" { }
    18.     _WaveSpeed ("Wave Speed", float) = 50.0
    19. }
    20.  
    21. SubShader
    22. {
    23.     Pass
    24.     {
    25.        CULL Off
    26.        
    27.       CGPROGRAM
    28.       #pragma vertex vert
    29.       #pragma fragment frag
    30.       #include "UnityCG.cginc"
    31.       #include "AutoLight.cginc"
    32.        
    33.       float4 _Color;
    34.       sampler2D _MainTex;
    35.       float _WaveSpeed;
    36.  
    37.       // vertex input: position, normal
    38.       struct appdata {
    39.           float4 vertex : POSITION;
    40.           float4 texcoord : TEXCOORD0;
    41.       };
    42.        
    43.       struct v2f {
    44.           float4 pos : POSITION;
    45.           float2 uv: TEXCOORD0;
    46.       };
    47.        
    48.       v2f vert (appdata v) {
    49.           v2f o;
    50.  
    51.         float sinOff=v.vertex.x+v.vertex.y+v.vertex.z;
    52.         float t=_Time*_WaveSpeed;
    53.         if(t < 0.0) t *= -1.0;
    54.         float fx=v.texcoord.x;
    55.         float fy=v.texcoord.x*v.texcoord.y;
    56.  
    57.         v.vertex.x+=sin(t*1.45+sinOff)*fx*0.5;
    58.         v.vertex.y=sin(t*3.12+sinOff)*fx*0.5-fy*0.9;
    59.         v.vertex.z-=sin(t*2.2+sinOff)*fx*0.2;
    60.    
    61.           o.pos = mul( glstate.matrix.mvp, v.vertex );
    62.           o.uv = v.texcoord;
    63.  
    64.          return o;
    65.       }
    66.        
    67.       float4 frag (v2f i) : COLOR
    68.       {
    69.          half4 color = tex2D(_MainTex, i.uv);
    70.          return color;
    71.       }
    72.  
    73.       ENDCG
    74.  
    75.       SetTexture [_MainTex] {combine texture}
    76.     }
    77. }
    78.    Fallback "VertexLit"
    79. }
     
    NeatWolf likes this.
  25. Jesse_Pixelsmith

    Jesse_Pixelsmith

    Joined:
    Nov 22, 2009
    Posts:
    296
    Is it possible for this shader to accept lighting info? Or at least be able to adjust the brightness with the color option?
     
  26. lucidcoder

    lucidcoder

    Joined:
    Mar 23, 2010
    Posts:
    138


    Using the latest shader posted above, on one side of the flag mesh I see the flat plane that the flag is based on. The other side looks like a normal waving flag, however.
     
  27. lucidcoder

    lucidcoder

    Joined:
    Mar 23, 2010
    Posts:
    138
    Bump, in reference to my previous post, does anyone know how to fix this? Currently on the latest widely available Unity 3 build.
     
  28. Michele

    Michele

    Joined:
    Apr 28, 2008
    Posts:
    73
    Great Work! I have only a question... How can I modify this shader to render the flag movement on a transparent Texture?
     
  29. Game_Smith_legacy

    Game_Smith_legacy

    Joined:
    Feb 14, 2011
    Posts:
    2
    I have the same question as Michele. The programmer on my team made the following adjustment:

    Code (csharp):
    1.  
    2. // Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
    3.  
    4. // Original shader by cboe - Mar, 23, 2009
    5. // Enhanced to 3 axis movement by Seon - Jan, 21, 2010
    6. // Added _WaveSpeed - Jan, 26, 2010 Eric5h5
    7. // Ajustement time function - April, 19, 2010 Fontmaster
    8. //
    9. // Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
    10. // Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.
    11. //
    12. // Enjoy!
    13.  
    14. Shader "FX/FlagWave"
    15. {
    16.  
    17. Properties
    18. {
    19.     _Color ("Main Color", Color) = (1,1,1,1)
    20.     _MainTex ("Texture", 2D) = "white" { }
    21.     _WaveSpeed ("Wave Speed", float) = 50.0
    22. }
    23.  
    24. SubShader
    25. {
    26.     Pass
    27.     {
    28.        [B]Blend SrcAlpha OneMinusSrcAlpha[/B]   //<---- New Line of Code
    29.        CULL Off
    30.        
    31.       Program "vp" {
    32. // Vertex combos: 1
    33. //   opengl - ALU: 71 to 71
    34. //   d3d9 - ALU: 66 to 66
    35. SubProgram "opengl " {
    36. Keywords { }
    37. Bind "vertex" Vertex
    38. Bind "texcoord" TexCoord0
    39. Vector 5 [_Time]
    40. Float 6 [_WaveSpeed]
    41. "!!ARBvp1.0
    42. # 71 ALU
    43. PARAM c[13] = { { 24.980801, -24.980801, 0.15915491, 0 },
    44.        state.matrix.mvp,
    45.        program.local[5..6],
    46.        { 0, 0.5, 1, 3.1199999 },
    47.        { 0.25, -60.145809, 60.145809, 0.89999998 },
    48.        { 85.453789, -85.453789, -64.939346, 64.939346 },
    49.        { 19.73921, -19.73921, -1, 1 },
    50.        { -9, 0.75, 1.45, 2.2 },
    51.        { 0.2 } };
    52. TEMP R0;
    53. TEMP R1;
    54. TEMP R2;
    55. TEMP R3;
    56. TEMP R4;
    57. ADD R0.y, vertex.position.x, vertex.position;
    58. MOV R0.x, c[6];
    59. MUL R0.x, R0, c[5];
    60. ADD R2.w, R0.y, vertex.position.z;
    61. SLT R0.z, R0.x, c[0].w;
    62. ADD R0.y, -R0.x, -R0.x;
    63. MAD R1.w, R0.y, R0.z, R0.x;
    64. MAD R0.x, R1.w, c[11].w, R2.w;
    65. MUL R0.x, R0, c[0].z;
    66. ADD R0.x, R0, -c[8];
    67. FRC R0.w, R0.x;
    68. ADD R0.xyz, -R0.w, c[7];
    69. MUL R0.xyz, R0, R0;
    70. MUL R1.xyz, R0, c[0].xyxw;
    71. ADD R1.xyz, R1, c[8].yzyw;
    72. MAD R1.xyz, R1, R0, c[9].xyxw;
    73. MAD R1.xyz, R1, R0, c[9].zwzw;
    74. MAD R1.xyz, R1, R0, c[10].xyxw;
    75. MAD R0.xyz, R1, R0, c[10].zwzw;
    76. SLT R2.x, R0.w, c[8];
    77. SGE R2.yz, R0.w, c[11].xxyw;
    78. MOV R1.xz, R2;
    79. DP3 R1.y, R2, c[10].zwzw;
    80. DP3 R0.x, R0, -R1;
    81. MAD R0.y, R1.w, c[11].z, R2.w;
    82. MUL R0.x, R0, vertex.texcoord[0];
    83. MAD R0.w, -R0.x, c[12].x, vertex.position.z;
    84. MAD R0.x, R1.w, c[7].w, R2.w;
    85. MUL R0.y, R0, c[0].z;
    86. ADD R0.y, R0, -c[8].x;
    87. FRC R2.w, R0.y;
    88. MUL R0.x, R0, c[0].z;
    89. ADD R0.x, R0, -c[8];
    90. FRC R1.w, R0.x;
    91. ADD R0.xyz, -R2.w, c[7];
    92. MUL R0.xyz, R0, R0;
    93. MUL R3.xyz, R0, c[0].xyxw;
    94. ADD R1.xyz, -R1.w, c[7];
    95. MUL R1.xyz, R1, R1;
    96. MUL R2.xyz, R1, c[0].xyxw;
    97. ADD R3.xyz, R3, c[8].yzyw;
    98. MAD R3.xyz, R3, R0, c[9].xyxw;
    99. MAD R3.xyz, R3, R0, c[9].zwzw;
    100. MAD R3.xyz, R3, R0, c[10].xyxw;
    101. ADD R2.xyz, R2, c[8].yzyw;
    102. MAD R2.xyz, R2, R1, c[9].xyxw;
    103. MAD R2.xyz, R2, R1, c[9].zwzw;
    104. MAD R2.xyz, R2, R1, c[10].xyxw;
    105. MAD R3.xyz, R3, R0, c[10].zwzw;
    106. SLT R4.x, R2.w, c[8];
    107. SGE R4.yz, R2.w, c[11].xxyw;
    108. MOV R0.xz, R4;
    109. DP3 R0.y, R4, c[10].zwzw;
    110. DP3 R2.w, R3, -R0;
    111. SGE R0.yz, R1.w, c[11].xxyw;
    112. SLT R0.x, R1.w, c[8];
    113. DP3 R0.y, R0, c[10].zwzw;
    114. MAD R1.xyz, R2, R1, c[10].zwzw;
    115. DP3 R0.x, R1, -R0;
    116. MUL R1.w, vertex.texcoord[0].x, vertex.texcoord[0].y;
    117. MOV R0.z, vertex.position.w;
    118. MUL R0.x, vertex.texcoord[0], R0;
    119. MUL R0.y, -R1.w, c[8].w;
    120. MAD R0.y, R0.x, c[7], R0;
    121. MUL R0.x, vertex.texcoord[0], R2.w;
    122. MAD R0.x, R0, c[7].y, vertex.position;
    123. DP4 result.position.w, R0.xywz, c[4];
    124. DP4 result.position.z, R0.xywz, c[3];
    125. DP4 result.position.y, R0.xywz, c[2];
    126. DP4 result.position.x, R0.xywz, c[1];
    127. MOV result.texcoord[0].xy, vertex.texcoord[0];
    128. END
    129. # 71 instructions, 5 R-regs
    130. "
    131. }
    132.  
    133. SubProgram "d3d9 " {
    134. Keywords { }
    135. Bind "vertex" Vertex
    136. Bind "texcoord" TexCoord0
    137. Matrix 0 [glstate_matrix_mvp]
    138. Vector 4 [_Time]
    139. Float 5 [_WaveSpeed]
    140. "vs_2_0
    141. ; 66 ALU
    142. dcl_position0 v0
    143. dcl_texcoord0 v1
    144. def c6, -0.02083333, -0.12500000, 1.00000000, 0.50000000
    145. def c7, -0.00000155, -0.00002170, 0.00260417, 0.00026042
    146. def c8, 0.00000000, 3.11999989, 0.15915491, 0.50000000
    147. def c9, 6.28318501, -3.14159298, 0.89999998, 1.45000005
    148. def c10, 2.20000005, 0.20000000, 0, 0
    149. add r0.w, v0.x, v0.y
    150. mov r0.x, c4
    151. mul r0.x, c5, r0
    152. slt r0.y, r0.x, c8.x
    153. max r0.y, -r0, r0
    154. slt r0.y, c8.x, r0
    155. add r0.z, -r0.y, c6
    156. mul r0.z, r0.x, r0
    157. mad r1.y, r0, -r0.x, r0.z
    158. add r1.x, r0.w, v0.z
    159. mad r0.x, r1.y, c10, r1
    160. mad r0.x, r0, c8.z, c8.w
    161. frc r0.x, r0
    162. mad r1.z, r0.x, c9.x, c9.y
    163. sincos r0.xy, r1.z, c7.xyzw, c6.xyzw
    164. mul r0.x, r0.y, v1
    165. mad r2.z, -r0.x, c10.y, v0
    166. mad r0.y, r1, c9.w, r1.x
    167. mad r0.x, r1.y, c8.y, r1
    168. mad r0.x, r0, c8.z, c8.w
    169. mad r0.y, r0, c8.z, c8.w
    170. frc r0.y, r0
    171. mov r2.w, v0
    172. mad r1.y, r0, c9.x, c9
    173. frc r1.x, r0
    174. sincos r0.xy, r1.y, c7.xyzw, c6.xyzw
    175. mad r0.x, r1, c9, c9.y
    176. sincos r1.xy, r0.x, c7.xyzw, c6.xyzw
    177. mul r0.x, v1, v1.y
    178. mul r0.z, -r0.x, c9
    179. mul r0.x, v1, r1.y
    180. mad r2.y, r0.x, c6.w, r0.z
    181. mul r0.x, v1, r0.y
    182. mad r2.x, r0, c6.w, v0
    183. dp4 oPos.w, r2, c3
    184. dp4 oPos.z, r2, c2
    185. dp4 oPos.y, r2, c1
    186. dp4 oPos.x, r2, c0
    187. mov oT0.xy, v1
    188. "
    189. }
    190.  
    191. SubProgram "gles " {
    192. Keywords { }
    193. "!!GLES
    194. #define SHADER_API_GLES 1
    195. #define tex2D texture2D
    196.  
    197.  
    198. #ifdef VERTEX
    199. #define gl_ModelViewProjectionMatrix glstate_matrix_mvp
    200. uniform mat4 glstate_matrix_mvp;
    201.  
    202. varying highp vec2 xlv_TEXCOORD0;
    203.  
    204. uniform highp float _WaveSpeed;
    205. uniform highp vec4 _Time;
    206. attribute vec4 _glesMultiTexCoord0;
    207. attribute vec4 _glesVertex;
    208. void main ()
    209. {
    210.  highp vec4 tmpvar_1;
    211.  tmpvar_1 = _glesVertex;
    212.  highp float t;
    213.  highp float tmpvar_2;
    214.  tmpvar_2 = ((_glesVertex.x + _glesVertex.y) + _glesVertex.z);
    215.  highp float tmpvar_3;
    216.  tmpvar_3 = (_Time * _WaveSpeed).x;
    217.  t = tmpvar_3;
    218.  if ((tmpvar_3 < 0.0)) {
    219.    t = (tmpvar_3 * -1.0);
    220.  };
    221.  highp float tmpvar_4;
    222.  tmpvar_4 = _glesMultiTexCoord0.x;
    223.  tmpvar_1.x = (_glesVertex.x + ((sin (((t * 1.45) + tmpvar_2)) * tmpvar_4) * 0.5));
    224.  tmpvar_1.y = (((sin (((t * 3.12) + tmpvar_2)) * tmpvar_4) * 0.5) - ((_glesMultiTexCoord0.x * _glesMultiTexCoord0.y) * 0.9));
    225.  tmpvar_1.z = (tmpvar_1.z - ((sin (((t * 2.2) + tmpvar_2)) * tmpvar_4) * 0.2));
    226.  gl_Position = (gl_ModelViewProjectionMatrix * tmpvar_1);
    227.  xlv_TEXCOORD0 = _glesMultiTexCoord0.xy;
    228. }
    229.  
    230.  
    231.  
    232. #endif
    233. #ifdef FRAGMENT
    234.  
    235. varying highp vec2 xlv_TEXCOORD0;
    236. uniform sampler2D _MainTex;
    237. void main ()
    238. {
    239.  highp vec4 tmpvar_1;
    240.  mediump vec4 color;
    241.  lowp vec4 tmpvar_2;
    242.  tmpvar_2 = texture2D (_MainTex, xlv_TEXCOORD0);
    243.  color = tmpvar_2;
    244.  tmpvar_1 = color;
    245.  gl_FragData[0] = tmpvar_1;
    246. }
    247.  
    248.  
    249.  
    250. #endif"
    251. }
    252.  
    253. }
    254. Program "fp" {
    255. // Fragment combos: 1
    256. //   opengl - ALU: 1 to 1, TEX: 1 to 1
    257. //   d3d9 - ALU: 1 to 1, TEX: 1 to 1
    258. SubProgram "opengl " {
    259. Keywords { }
    260. SetTexture 0 [_MainTex] 2D
    261. "!!ARBfp1.0
    262. # 1 ALU, 1 TEX
    263. TEX result.color, fragment.texcoord[0], texture[0], 2D;
    264. END
    265. # 1 instructions, 0 R-regs
    266. "
    267. }
    268.  
    269. SubProgram "d3d9 " {
    270. Keywords { }
    271. SetTexture 0 [_MainTex] 2D
    272. "ps_2_0
    273. ; 1 ALU, 1 TEX
    274. dcl_2d s0
    275. dcl t0.xy
    276. texld r0, t0, s0
    277. mov oC0, r0
    278. "
    279. }
    280.  
    281. SubProgram "gles " {
    282. Keywords { }
    283. "!!GLES"
    284. }
    285.  
    286. }
    287.  
    288. #LINE 76
    289.  
    290.  
    291.       SetTexture [_MainTex] {combine texture}
    292.     }
    293. }
    294.    Fallback "VertexLit"
    295. }
    296.  
    Which results in a flag that uses alpha values, but when the flag waves it leaves rendering artifacts at the end of the flag (it looks like a copy of the end of the flag is left hanging in space as the flag moves on). Does anyone have any ideas how to fix this?
     
    Last edited: Apr 5, 2011
  30. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Ok guys,

    Thanks a lot for this very usefull Thread.
    Starting from this, I went a little bit further in the study.

    Here is my version of the shader :

    The "FlagWaveCG.cginc" file :
    Code (csharp):
    1. // Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
    2.  
    3. // Original shader by cboe - Mar, 23, 2009
    4. // Enhanced to 3 axis movement by Seon - Jan, 21, 2010
    5. // Added _WaveSpeed by Eric5h5 - Jan, 26, 2010
    6. // CHANGE LOG - Gauthier BOAGLIO (golgauth) / Klakos - May, 07, 2011 :
    7. //      - Added Transparency support
    8. //      - Added Spec and Normal mapping support
    9. //      - Added Shadow casting support (+ Shadow Alpha and Shadow Alpha cutoff support)
    10. //              [Done in the "ShadowCaster" additional Pass]
    11. //      - Added advanced double-sided rendering support
    12. //      - Added _WaveStrength param
    13. //
    14. // Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
    15. // Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.  
    16. //
    17. // [url]http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/[/url] ] for
    18. // visuals and more informations
    19.  
    20.  
    21. #include "UnityCG.cginc"
    22.  
    23. float4 _Color;
    24. sampler2D _MainTex;
    25. fixed _Cutoff;
    26. float _WaveSpeed;
    27. float _WaveStrength;
    28.  
    29.  
    30. struct v2f {
    31.     V2F_SHADOW_CASTER;
    32.     float2 uv : TEXCOORD1;
    33. };
    34.  
    35.  
    36. void computeWave (inout appdata_full v, inout v2f o)
    37. {
    38.     float sinOff=(v.vertex.x+v.vertex.y+v.vertex.z) * _WaveStrength;
    39.     float t=-_Time*_WaveSpeed;
    40.     float fx=v.texcoord.x;
    41.     float fy=v.texcoord.x*v.texcoord.y;
    42.  
    43.     v.vertex.x+=sin(t*1.45+sinOff)*fx*0.5;
    44.     v.vertex.y=(sin(t*3.12+sinOff)*fx*0.5-fy*0.9);
    45.     v.vertex.z-=(sin(t*2.2+sinOff)*fx*0.2);
    46.     o.pos = mul( UNITY_MATRIX_MVP, v.vertex );
    47.     o.uv = v.texcoord;
    48. }

    The "FlagWave-Advanced.shader" file :
    Code (csharp):
    1. // Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
    2.  
    3. // Original shader by cboe - Mar, 23, 2009
    4. // Enhanced to 3 axis movement by Seon - Jan, 21, 2010
    5. // Added _WaveSpeed by Eric5h5 - Jan, 26, 2010
    6. // CHANGE LOG - Gauthier BOAGLIO (golgauth) / Klakos - May, 07, 2011 :
    7. //      - Added Transparency support
    8. //      - Added Spec and Normal mapping support
    9. //      - Added Shadow casting support (+ Shadow Alpha and Shadow Alpha cutoff support)
    10. //              [Done in the "ShadowCaster" additional Pass]
    11. //      - Added advanced double-sided rendering support
    12. //      - Added _WaveStrength param
    13. //
    14. // Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
    15. // Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.  
    16. //
    17. // See [ http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/ ] for
    18. // visuals and more informations
    19.  
    20.  
    21. Shader "Selfmade/for-2sided/FlagWave Advanced Regular"
    22. {
    23.  
    24. Properties
    25. {
    26.     // Ususal stuffs
    27.     _Color ("Main Color", Color) = (1,1,1,1)
    28.     _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
    29.     _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
    30.     _MainTex ("Base (RGB) TransGloss (A)", 2D) = "white" {}
    31.  
    32.     // Bump stuffs
    33.     //_Parallax ("Height", Range (0.005, 0.08)) = 0.02
    34.     _BumpMap ("Normalmap", 2D) = "bump" {}
    35.     //_ParallaxMap ("Heightmap (A)", 2D) = "black" {}
    36.    
    37.     // Shadow Stuff
    38.     _Cutoff ("Shadow Alpha cutoff", Range(0.25,0.9)) = 1.0
    39.  
    40.     // Flag Stuffs
    41.     _WaveSpeed ("Wave Speed", Range(0.0, 300.0)) = 50.0
    42.     _WaveStrength ("Wave Strength", Range(0.0, 5.0)) = 1.0
    43. }
    44.  
    45.  
    46. SubShader
    47. {
    48.     Tags {
    49.     "Queue"="Geometry"
    50.     "IgnoreProjector"="True"
    51.     "RenderType"="Transparent"}
    52.  
    53.     LOD 300
    54.  
    55.  
    56.  
    57.     Pass
    58.     {
    59.             Name "ShadowCaster"
    60.             Tags { "LightMode" = "ShadowCaster" }
    61.            
    62.             Fog {Mode Off}
    63.             ZWrite On ZTest Less Cull Off
    64.             Offset 1, 1
    65.  
    66.             CGPROGRAM
    67. // Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it does not contain a surface program or both vertex and fragment programs.
    68. #pragma exclude_renderers gles
    69.             #pragma vertex vert
    70.             #pragma fragment frag
    71.             #pragma fragmentoption ARB_precision_hint_fastest
    72.             #pragma multi_compile_shadowcaster
    73.             #include "FlagWaveCG.cginc"
    74.            
    75.            
    76.             v2f vert( appdata_full v )
    77.             {
    78.                 v2f o;
    79.                 computeWave(v, o);
    80.                 TRANSFER_SHADOW_CASTER(o)
    81.    
    82.               return o;
    83.             }
    84.            
    85.             //sampler2D _MainTex;
    86.                    
    87.             float4 frag( v2f i ) : COLOR
    88.             {
    89.                 fixed4 texcol = tex2D( _MainTex, i.uv );
    90.                 clip( texcol.a - _Cutoff );
    91.                 SHADOW_CASTER_FRAGMENT(i)
    92.             }
    93.             ENDCG
    94.  
    95.  
    96.       //SetTexture [_MainTex] {combine texture}
    97.     }
    98.  
    99. //CULL Front
    100.  
    101. CGPROGRAM
    102.         #pragma surface surf BlinnPhong alpha vertex:vert fullforwardshadows approxview
    103.         #include "FlagWaveCG.cginc"
    104.  
    105.  
    106.         half _Shininess;
    107.  
    108.         sampler2D _BumpMap;
    109.         //sampler2D _ParallaxMap;
    110.         float _Parallax;
    111.  
    112.         struct Input {
    113.             float2 uv_MainTex;
    114.             float2 uv_BumpMap;
    115.             //float3 viewDir;
    116.         };
    117.  
    118.         v2f vert (inout appdata_full v) {
    119.             v2f o;
    120.             computeWave(v, o);
    121.             return o;
    122.         }
    123.  
    124.         void surf (Input IN, inout SurfaceOutput o) {
    125.             // Comment the next 4 following lines to get a standard bumped rendering
    126.             // [Without Parallax usage, which can cause strange result on the back side of the plane]
    127.             /*half h = tex2D (_ParallaxMap, IN.uv_BumpMap).w;
    128.             float2 offset = ParallaxOffset (h, _Parallax, IN.viewDir);
    129.             IN.uv_MainTex += offset;
    130.             IN.uv_BumpMap += offset;*/
    131.  
    132.             fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    133.             o.Albedo = tex.rgb * _Color.rgb;
    134.             o.Gloss = tex.a;
    135.             o.Alpha = tex.a * _Color.a;
    136.             //clip(o.Alpha - _Cutoff);
    137.             o.Specular = _Shininess;
    138.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    139.         }
    140. ENDCG
    141. }
    142.    
    143. Fallback "Transparent/VertexLit"
    144. }

    I also made a full case study here :
    http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/

    It covers the following points :

    * * Flag vertices animation via a shader (trigo. way)
    * * Advanced ShaderLab surface shading for transparency management
    * * Adding a shadow Pass (with alpha support)
    * * Double-sided surfaces methods (methods 1, 2 and 3)
    * * Provided Double-sided Materials Configuration Wizard (for 3rd method)


    >>> Downloads [from the address bellow]

    * - PDF version of the article : WavingFlag.pdf
    * - Configuration Wizard : BackwardMaterialBuilder.cs
    * - Unity 3.3 Package : WavingFlagDemo.unitypackage | WavingFlagDemo.rar


    Hope this will help...
     
    Last edited: May 14, 2011
  31. ognjenm

    ognjenm

    Joined:
    May 3, 2011
    Posts:
    97
  32. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Log : Changed render Queue to "AlphaTest" (Because it works better like this).
     
  33. Clock

    Clock

    Joined:
    Nov 22, 2011
    Posts:
    6
    Hello cboe~~~ it's very useful for me.

    But there are still some parts of this shader ,that i do not understand.

    Such as:

    TRANSFER_SHADOW_CASTER(o)

    SHADOW_CASTER_FRAGMENT(i)

    Are they the Built-in funtion of Unity?

    Where i can found the details about them?
     
  34. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Yes they are (from UnityCG.cginc). Have a look at the Vertexlit built-in shader : it includes passes for both shadow casting SHADOW_CASTER_FRAGMENT and shadow receiving SHADOW_COLLECTOR_FRAGMENT.
    The goal, here is to force both shadow casting and receiving even if the material is transparent (and should not be able to).

    http://unity3d.com/support/documentation/Components/SL-PassTags.html
     
    Last edited: Nov 24, 2011
  35. Karmarama

    Karmarama

    Joined:
    Jul 11, 2011
    Posts:
    261
    I'm trying to use this (and even downloaded the unitypackage example scene) and in doing so ran across the following issue (attached) where a polyPlane from maya - exported without any edits - causes a weird issue. It's more pinched at one side, and isn't exactly animating or flowing correctly to the Sin. I assume this is a problem with what's documented in the shader:

    Although this seems fine to me, I'm honestly not understanding where the issue lays and where I should be fixing this in maya.

    I'm not quite sure if anything was done to the blender imported plane to make it work however.

    Much appreciated!
     

    Attached Files:

    Last edited: Jan 10, 2013
  36. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Yes it does. Unfortunately I don't know anything about Maya vertices and axises management. So, all I can say, is that under Blender, you have to enter the "Vertex Mode" (aka : Edit the Mesh). Then select all vertices and rotate of 90 degrees along the appropriate axis. Then apply (I think it is Ctrl+A+Enter), to reset the relative coordinates of the selected vertices. Then save and reimport in Unity : the flag should be in the same plane than the Unity plane now. If you can't do such an operation in Maya, all I can suggest is to use Blender... Sorry. If we have a Maya specialist around there, please help !
     
  37. thilina098

    thilina098

    Joined:
    Oct 31, 2012
    Posts:
    18
    Hi Guys,

    I've been using this shader and want to have the flag some gravity applied to it. Like this $Flag.PNG

    I'm very new to CGProgramming. But I think I have to change the code in here

    to apply gravity to it. I'm not completely sure how to do this. Any help would be appreciated.

    thanks for your help in advance.