Unity Community


Results 1 to 13 of 13

  1. Posts
    16

    Animate water using Flow Maps

    Hey guys,

    I wrote a shader that should animate water using a flow map and a noise map, everything is based on the shader developed by Valve for LF4 and Graphics Runner DirectX Sample

    The shader itself is really simple, but for some reason a cannot animate the water. I would really appreciate any help, in fact would be cool having a water animated using a flow map in unity free version.

    this is the shader:

    Code:  
    1. Shader "WaterTestShader1"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Main Color", Color) = (1,1,1,0.5)
    6.         _MainTex ("Base (RGB)", 2D) = "white" {}
    7.         _MainTex2 ("Base (RGB)", 2D) = "white" {}
    8.         _FlowMap   ("FlowMap  (RGB)", 2D) = "white" {}
    9.         _NoiseMap  ("NoiseMap (RGB)", 2D) = "white" {}
    10.        
    11.         _WaveScale ("Wave scale", Range (0.02,0.15)) = .07
    12.         _WaveSpeed ("Wave speed (map1 x,y; map2 x,y)", Vector) = (19,9,-16,-7)
    13.     }
    14.     SubShader
    15.     {
    16.    
    17.     Pass
    18.     {
    19.  
    20.     CGPROGRAM
    21.     #pragma vertex vert
    22.     #pragma fragment frag
    23.     #include "UnityCG.cginc"
    24.  
    25.     float4 _Color;
    26.     sampler2D _MainTex, _MainTex2, _FlowMap, _NoiseMap;
    27.     float4 _MainTex_ST;
    28.     float4 _MainTex2_ST;
    29.    
    30.     float3 _WaveSpeed;
    31.     float  _WaveScale;
    32.    
    33.     //Flow map offsets used to scroll the wave maps
    34.     float   flowMapOffset0;
    35.     float   flowMapOffset1;
    36.  
    37.     //scale used on the wave maps
    38.     float waveScale = 1.0f;
    39.     float halfCycle;
    40.  
    41. struct v2f
    42. {
    43.     float4  pos  : SV_POSITION;
    44.     float2  uv0  : TEXCOORD0;
    45.     float2  uv1  : TEXCOORD1;
    46.     float3  col  : COLOR0;
    47. };
    48.  
    49. v2f vert (appdata_base v)
    50. {
    51.     v2f o;
    52.     o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    53.     o.uv0 = TRANSFORM_TEX (v.texcoord, _MainTex);
    54.     o.uv1 = TRANSFORM_TEX (v.texcoord, _MainTex2);
    55.     o.col = v.normal * 0.5 + 0.5; //shift the colour in the range [0, 1]
    56.     return o;
    57. }
    58.  
    59. half4 frag (v2f i) : COLOR
    60. {
    61.     //get and uncompress the flow vector for this pixel
    62.     float2 flowmap = tex2D( _FlowMap, i.uv0 ).rg * 2.0f - 1.0f;
    63.     float cycleOffset = tex2D( _NoiseMap, i.uv0 ).r;
    64.    
    65.     float phase0 = cycleOffset * .5f + flowMapOffset0;
    66.     float phase1 = cycleOffset * .5f + flowMapOffset1;
    67.    
    68.     // Sample normal map.
    69.     float3 normalT0 = tex2D(_MainTex, ( i.uv0 * waveScale ) + flowmap * phase0 ).rgb;
    70.     float3 normalT1 = tex2D(_MainTex2, ( i.uv0 * waveScale ) + flowmap * phase1 ).rgb;
    71.    
    72.     float f = ( abs( halfCycle - flowMapOffset0 ) / halfCycle );
    73.    
    74.     float3 normalT = lerp( normalT0, normalT1, f );
    75.     return float4( normalT, 1.0f );
    76.  
    77. }
    78. ENDCG
    79.  
    80.     }
    81. }
    82. Fallback "VertexLit"
    83. }

    and this is the script I use to update overtime the scrolling textures:

    Code:  
    1. using UnityEngine;
    2.  
    3. [ExecuteInEditMode]
    4.  
    5.  
    6. public class UVScroller : MonoBehaviour
    7. {
    8.    
    9.    float m_fFlowMapOffset0 = 0.0f;
    10.    float m_fFlowMapOffset1 = 0.0f;
    11.    float m_fFlowSpeed = 0.05f;
    12.    float m_fCycle = 0.15f;
    13.    float m_fWaveMapScale = 2.0f;
    14.    
    15.    public void Update ()
    16.    {
    17.        //update the flow map offsets for both layers
    18.        m_fFlowMapOffset0 += m_fFlowSpeed * Time.deltaTime;
    19.        m_fFlowMapOffset1 += m_fFlowSpeed * Time.deltaTime;
    20.      
    21.        if ( m_fFlowMapOffset0 >= m_fCycle )
    22.             m_fFlowMapOffset0 = 0.0f;
    23.  
    24.        if ( m_fFlowMapOffset1 >= m_fCycle )
    25.             m_fFlowMapOffset1 = 0.0f;
    26.          
    27.        float _fHalfCycle = m_fCycle*0.5f;
    28.      
    29.        Shader.SetGlobalFloat("fFlowMapOffset0", m_fFlowMapOffset0);
    30.        Shader.SetGlobalFloat("fFlowMapOffset1", m_fFlowMapOffset1);
    31.        Shader.SetGlobalFloat("halfCycle", _fHalfCycle);
    32.        Shader.SetGlobalFloat("fWaveSpeed", m_fFlowSpeed);
    33.        Shader.SetGlobalFloat("fWaveScale", m_fWaveMapScale);
    34.   }
    35. }

    At the moment I am not considering the light I just want to make the flow working.

    The flow is scrolling,but there is a problem with normals, apparently I do not unpack normals properly and when the texture reached the endCycle is resetting itself

    What I want to do is scrolling normal maps and not the actual texture, this means unpack normals and?

    Thank you very much in advance

    Finally a pic as reference:
    Attached Images  
    Last edited by Alhaziel; 07-25-2011 at 03:00 PM.


  2. Location
    Leeds, UK
    Posts
    2,059
    For normal maps you want to use the function UnpackNormals() with your normal map texture sampler as an argument.
    e.g.
    Code:  
    1. float3 normalT0 = UnpackNormals(tex2D(_MainTex, ( i.uv0 * waveScale ) + flowmap * phase0 ));


  3. Posts
    16
    Quote Originally Posted by Farfarer View Post
    For normal maps you want to use the function UnpackNormals() with your normal map texture sampler as an argument.
    e.g.
    Code:  
    1. float3 normalT0 = UnpackNormals(tex2D(_MainTex, ( i.uv0 * waveScale ) + flowmap * phase0 ));
    yeah I know I fixed that, but I think I have still some problems, the water looks redish because of the colours of the textures, but usually normals look purple or green-ish... I do not know if this is due to the fact i do not have lighting calculations...

    Finally, the main problem is that once the scrolling texture reached the end of his cycle, it jumps back to the start and the visual effect is really ugly to watch.


  4. Location
    Leeds, UK
    Posts
    2,059
    I kinda think it'd be worthwhile using the _Time variable in the shader itself to control the animation. Rather than scripting it all then passing variables in.

    But in...
    Code:  
    1. if ( m_fFlowMapOffset1 >= m_fCycle )
    2.             m_fFlowMapOffset1 = 0.0f;
    m_fCycle is 0.15

    So the offset is hitting 15% of texture offset then jumping back to 0. That's not going to look graceful - it's going to keep snapping back.

    Perhaps use
    Code:  
    1. m_fFlowMapOffset1 = Mathf.Repeat(m_fFlowMapOffset1 + m_fFlowSpeed * Time.deltaTime, 1);
    which will keep it going and wrap it back round to 0 once it's passed 1. And if you've put it, say 0.1 over 1.0, it'll wrap back round to 0.1. Keeps it running smoothly.


  5. Posts
    16
    Quote Originally Posted by Farfarer View Post
    I kinda think it'd be worthwhile using the _Time variable in the shader itself to control the animation. Rather than scripting it all then passing variables in.

    But in...
    Code:  
    1. if ( m_fFlowMapOffset1 >= m_fCycle )
    2.             m_fFlowMapOffset1 = 0.0f;
    m_fCycle is 0.15

    So the offset is hitting 15% of texture offset then jumping back to 0. That's not going to look graceful - it's going to keep snapping back.

    Perhaps use
    Code:  
    1. m_fFlowMapOffset1 = Mathf.Repeat(m_fFlowMapOffset1 + m_fFlowSpeed * Time.deltaTime, 1);
    which will keep it going and wrap it back round to 0 once it's passed 1. And if you've put it, say 0.1 over 1.0, it'll wrap back round to 0.1. Keeps it running smoothly.
    First of all thanks very much for your help man.

    I have put that line of code, and yes it is working much better without jumping back to the start, but still there is something i do not understand completely.

    The flow seems working fine, it is cool, but first of all is redish, and after it started flowing it changes coloulors, but when the texture is scrolled completely the flow stops for a second a starts again... the effect is not bas as was before, but still not perfect.

    Finally I really would like to know why the normal maps look red ish, here is a screenshot:
    Attached Images  


  6. Location
    Leeds, UK
    Posts
    2,059
    For a start, you've got two returns going on in your shader, which isn't right.

    You want to remove the last one - the i.col one - just to be sure it's not screwing things up.

    Secondly... are your normal maps tagged as normal maps in the inspector? If they're not, the UnpackNormals() function's going to screw up the colouring as it relies on them being DXT5nm compressed (which is what tagging them as normal maps in the inspector does).


  7. Posts
    16
    Quote Originally Posted by Farfarer View Post
    For a start, you've got two returns going on in your shader, which isn't right.

    You want to remove the last one - the i.col one - just to be sure it's not screwing things up.

    Secondly... are your normal maps tagged as normal maps in the inspector? If they're not, the UnpackNormals() function's going to screw up the colouring as it relies on them being DXT5nm compressed (which is what tagging them as normal maps in the inspector does).
    yea i have fixed the two returns, before opening the thread, i just didnt notice i posted the old code, but the second return should not be called anyway, sry.

    I just changed the two normal maps, they are set as normal maps this is the inspector window for them:

    The flow now looks much better (the textures are not even squared..btw but i do not think it s a problem right now), but still it is blue-ish now. It like is getting the ambient colour from this textures..now I have seen normal map rendered and I know how they should look like, imho there is something wrong.
    Attached Images   
    Last edited by Alhaziel; 07-22-2011 at 04:16 AM.


  8. Location
    Leeds, UK
    Posts
    2,059
    Untick generate from height. You're passing in proper normal maps, not height maps that need converting.


  9. Posts
    16
    ok man thx very much again!

    I think I have pretty much done the shader with your help, but just one problem left.
    I think I commit some mistakes when I try to animate the flow, because the areas that should be around objects in the final scene, are not moving at all. But they should move as you can see in the GraphicsRunner web site!

    here is the final polished shader code:

    Code:  
    1. Shader "WaterTestShader1"
    2. {
    3.     Properties
    4.     {
    5.         //color
    6.         _Color ("Main Color", Color) = (1,1,1,0.5)
    7.        
    8.         //main water texture
    9.         _AmbientTex ("Water Base Texture", 2D) = "white" {}
    10.        
    11.         //first main normal map to scroll
    12.         _NrmTex1 ("First scrolling normal map (RGB)", 2D) = "bump" {}
    13.        
    14.         //second main normal map to scroll
    15.         _NrmTex2 ("Second scrolling normal map", 2D) = "bump" {}
    16.        
    17.         //flowmap
    18.         _FlowMap   ("FlowMap  (RGB)", 2D) = "white" {}
    19.        
    20.         //noise map
    21.          _NoiseMap  ("NoiseMap (RGB)", 2D) = "white" {}
    22.        
    23.         //colour textures overlay
    24.         _ColorTextureOverlay ("_ColorTextureOverlay", Range (0.0, 1.0)) = 0.75
    25.        
    26.         //fresnel power for reflections
    27.         _FresnelPower ("_FresnelPower", Range (0.1, 10.0)) = 2.0
    28.        
    29.         //ambient power light
    30.         _Ambient ("_Ambient", Range (0.0, 1.0)) = 0.8
    31.        
    32.         //world light direction
    33.         _WorldLightDir("_WorldLightDir", Vector) = (0,0,0,1)
    34.        
    35.         //specular shiness
    36.         _Shininess ("_Shininess", Range (0.1, 60.0)) = 1.0
    37.        
    38.         //spec colours
    39.         _SpecColor ("Spec Color", Color) = (0.5,0.5,0.5,0.5)
    40.        
    41.         _WaveScale ("Wave scale", Range (0.02,0.15)) = .07
    42.        
    43.        // _WaveSpeed ("Wave speed (map1 x,y; map2 x,y)", Vector) = (19,9,-16,-7)
    44.     }
    45.    
    46.     Category
    47.     {
    48.         Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    49.         Blend SrcAlpha OneMinusSrcAlpha
    50.         Cull Off
    51.         //ColorMask RGB
    52.         //Lighting off ZWrite Off
    53.        
    54.     SubShader
    55.     {
    56.    
    57.     Pass
    58.     {
    59.  
    60.     CGPROGRAM
    61.     #pragma target 3.0
    62.     #pragma vertex vert
    63.     #pragma fragment frag
    64.     #include "UnityCG.cginc"
    65.  
    66.     //main colour
    67.     float4 _Color;
    68.    
    69.     //texsampler
    70.     sampler2D _NrmTex1, _NrmTex2, _FlowMap, _NoiseMap, _AmbientTex;
    71.    
    72.     //texture's st
    73.     float4 _NrmTex1_ST;
    74.     float4 _NrmTex2_ST;
    75.     float4 _AmbientTex_ST;
    76.     float4 _FlowMap_ST;
    77.    
    78.     //wave speed
    79.     float3 fWaveSpeed;
    80.    
    81.     //wave scale
    82.     float  _WaveScale;
    83.    
    84.     //Flow map offsets used to scroll the wave maps
    85.     float   flowMapOffset0;
    86.     float   flowMapOffset1;
    87.  
    88.     //scale used on the wave maps
    89.     float fWaveScale = 1.0f;
    90.    
    91.     //the half cycle needed to blend the 2 normal maps when one reaches the top the other's contribuition should be 0
    92.     float halfCycle;
    93.    
    94.     //color texture overlay
    95.     float _ColorTextureOverlay;
    96.    
    97.     //reflection power
    98.     float _FresnelPower;
    99.    
    100.     //ambient cols
    101.     float _Ambient;
    102.    
    103.     //spec shiness
    104.     float _Shininess;
    105.    
    106.     //spec colour
    107.     float4 _SpecColor;
    108.    
    109.     //world light direction used to calculate the fresnel law
    110.     float4 _WorldLightDir;
    111.  
    112. //vertex structure from vertex shader to pixel
    113. struct v2f
    114. {
    115.     float4  pos         : SV_POSITION;
    116.     float2  uv0         : TEXCOORD0;
    117.     float2  uv1         : TEXCOORD1;
    118.     float3 viewDirWorld : TEXCOORD2;
    119.     float3 TtoW0        : TEXCOORD3;
    120.     float3 TtoW1        : TEXCOORD4;
    121.     float3 TtoW2        : TEXCOORD5;
    122.     float3  col         : COLOR0;
    123.     float2 uv2          : TEXCOORD6;
    124. };
    125.  
    126. v2f vert (appdata_full v)
    127. {
    128.     //declaration of the evrtex structure
    129.     v2f o;
    130.    
    131.     //determine the position in world space applying the model view projection transform
    132.     o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    133.    
    134.     //unpack texture coords for the scrolling normal maps (they are the same so there is no need to waste memory for another float2 texcoord variable)
    135.     o.uv0 = TRANSFORM_TEX (v.texcoord, _NrmTex1);
    136.    
    137.     //unpack texture coord for the flow map
    138.     o.uv1 = TRANSFORM_TEX (v.texcoord, _FlowMap);
    139.    
    140.     //unpack tex coords for ambient water base texture
    141.     o.uv2 = TRANSFORM_TEX (v.texcoord, _AmbientTex);
    142.    
    143.     //reverse view dir                                     
    144.     o.viewDirWorld = -WorldSpaceViewDir(v.vertex);
    145.        
    146.     //calculates the tangent normals for the fresnel law                                                   
    147.     TANGENT_SPACE_ROTATION;
    148.     o.TtoW0 = mul(rotation, _Object2World[0].xyz * unity_Scale.w);
    149.     o.TtoW1 = mul(rotation, _Object2World[1].xyz * unity_Scale.w);
    150.     o.TtoW2 = mul(rotation, _Object2World[2].xyz * unity_Scale.w);     
    151.      
    152.     //returns the output structure
    153.     return o;
    154. }
    155.  
    156. half4 frag (v2f i) : COLOR
    157. {
    158.     //get and uncompress the flow vector for this pixel
    159.     float2 flowmap = tex2D( _FlowMap, i.uv1 ).rg * 2.0f - 1.0f;
    160.    
    161.     //determines the noise clycle offset from the noise mask
    162.     float cycleOffset = tex2D( _NoiseMap, i.uv1 ).r;
    163.    
    164.     //determines the phase0
    165.     float phase0 = cycleOffset * .5f + flowMapOffset0;
    166.    
    167.     //determines the phase1
    168.     float phase1 = cycleOffset * .5f + flowMapOffset1;
    169.    
    170.     // Sample normal map1
    171.     float3 normalT0 = UnpackNormal(tex2D(_NrmTex1, ( i.uv0 * fWaveScale ) + flowmap * phase0 ));
    172.    
    173.     //Sample normal map2
    174.     float3 normalT1 = UnpackNormal(tex2D(_NrmTex2, ( i.uv0 * fWaveScale ) + flowmap * phase1 ));
    175.    
    176.     //determines the flow function
    177.     float f = ( abs( halfCycle - flowMapOffset0 ) / halfCycle );
    178.    
    179.     //unroll the normals retrieved from the normalmaps
    180.     normalT0.yz = normalT0.zy
    181.     normalT1.yz = normalT1.zy;
    182.    
    183.     normalT0 = 2.0f * normalT0 - 1.0f;
    184.     normalT1 = 2.0f * normalT1 - 1.0f;
    185.    
    186.     //determins the resulting normal
    187.     float3 normalT = lerp( normalT0, normalT1, f );
    188.    
    189.     // declare world normal
    190.     half3 worldNormal;
    191.  
    192.     //calculate the world normals
    193.     worldNormal.x = dot(i.TtoW0, normalT.xyz);
    194.     worldNormal.y = dot(i.TtoW1, normalT.xyz);
    195.     worldNormal.z = dot(i.TtoW2, normalT.xyz);     
    196.                    
    197.     // normalize
    198.     worldNormal = normalize(worldNormal);
    199.     i.viewDirWorld = normalize(i.viewDirWorld);
    200.    
    201.     // color
    202.     float4 color = tex2D(_AmbientTex, i.uv2);
    203.     color = lerp(half4(0.6, 0.6, 0.6, 0.6), color, _ColorTextureOverlay);   
    204.    
    205.     // REFLECTION
    206.     float3 reflectVector = normalize(reflect(i.viewDirWorld, worldNormal));
    207.     half4 reflColor = 0.75;
    208.    
    209.     // FRESNEL CALCS
    210.     float fcbias = 0.20373;
    211.     float facing = saturate(1.0 - max(dot(-i.viewDirWorld, worldNormal), 0.0));
    212.     float refl2Refr = max(fcbias + (1.0 - fcbias) * pow(facing, _FresnelPower), 0)
    213.    
    214.     color.rgba *= (lerp(half4(0.6,0.6,0.6, 0.6), half4(reflColor.rgb,1.0), refl2Refr));
    215.                      
    216.     // light
    217.     color.rgb = color.rgb * max(_Ambient, saturate(dot(_WorldLightDir.xyz, worldNormal)));
    218.    
    219.     // a little more spec in low quality to have at least something going on
    220.     color.rgb += _SpecColor.rgb * 2.0 *  pow(saturate(dot(_WorldLightDir.xyz, reflectVector)), _Shininess);
    221.    
    222.     //returns the light color computer modulated by the diffuse color      
    223.     return _Color * color;
    224.            
    225. }
    226. ENDCG
    227.  
    228. }
    229.  
    230.  
    231.     }
    232. }
    233. Fallback ""//"VertexLit"
    234. }

    and here is a pic as reference:
    Attached Images  
    Last edited by Alhaziel; 07-22-2011 at 06:32 AM.


  10. Posts
    16
    edit double post sry
    Last edited by Alhaziel; 07-22-2011 at 06:18 AM.


  11. Posts
    2
    I think you might be interested, I've created a flow editor - http://algoholic.eu/flow-shader-fix-flow-editor/

    Cheers.


  12. Posts
    26
    Quote Originally Posted by sadaszewski View Post
    I think you might be interested, I've created a flow editor - http://algoholic.eu/flow-shader-fix-flow-editor/

    Cheers.
    Hey I have just checked your page. Look really cool. Many thanks for the flow map editor, really handy.


  13. Posts
    2
    Iíve introduced some useful changes:
    1) Fast preview/export using triangulated irregular network linear interpolation. This looks a bit worse than Natural Neighbor method but itís a lot faster.
    2) Thanks to using OpenMP for Natural Neighbor high quality export, it should be approximately N times faster (where N is the number of CPU cores you have)
    3) When loading image, flowed automatically looks for corresponding .ff file and tries to load it
    4) Antialiasing of the drawing scene
    5) Added Repeat Last Export button
    6) Fixed bug in Natural Neighbor which used to cause artifacts near right border of the flow map

    http://algoholic.eu/flow-field-editor-update/
    Last edited by sadaszewski; 03-26-2012 at 08:04 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •