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

Wanted: Ocean shader

Discussion in 'Works In Progress - Archive' started by bigkahuna, Jan 8, 2009.

  1. Nsomnia

    Nsomnia

    Joined:
    Sep 26, 2014
    Posts:
    27
    I've looked into your project quickly and while the underwater/above water function looks decent and the frames per second is better than you think (I was getting between 60-120 at water level on a nvidia gtx 760) I cant seem to figure out why the corners of the ocean grid look all messed up with black polys and the surface color looking like a "short wall" around the ocean at any height above sealevel, especially when looking around. Whats really odd is increasing the tileing amount and removing the skybox and disabling shadows has no effect on this.

    The problem with the surface color (the green color) surrounding the ocean is a problem in the Ocean_C# prefab so the issues start very very early on, add in the underwater effects and I think stuff just gets compounded.

    It seems our issues start here
    Lines 301-308. If you remove it, you dont get the problems listed above (havn't tried with the underwater addons)

    Code (csharp):
    1.  
    2.     //build walls along the edge that will keep the user from seeing a gap in the ocean tiles
    3.      float wH = Mathf.Sqrt (Mathf.Pow (20,2) / 2) / 2;
    4.      float wX = tiles / 2f * size.x;
    5.      float wZ = tiles / 2f * size.z;
    6.      BuildStaticTile (new Vector3 (0,-wH + 0.001f, wZ - wH), new Vector3 (_sizeX, 0, 20),Quaternion.AngleAxis(130, Vector3.right), emptyMesh, _staticTiles, material);
    7.      BuildStaticTile (new Vector3 (0,-wH + 0.001f, -wZ + wH), new Vector3 (_sizeX, 0, 20),Quaternion.AngleAxis(-130, Vector3.right), emptyMesh, _staticTiles, material);
    8.      BuildStaticTile (new Vector3 (wX - wH,-wH + 0.001f, 0), new Vector3 (20, 0, _sizeZ),Quaternion.AngleAxis(-130, Vector3.forward), emptyMesh, _staticTiles, material);
    9.      BuildStaticTile (new Vector3 (-wX + wH,-wH + 0.001f, 0), new Vector3 (20, 0, _sizeZ),Quaternion.AngleAxis(130, Vector3.forward), emptyMesh, _staticTiles, material);
    Changinge the Quanternion.AngleAxis values from +-130 to +- 180 has the same effect as removing the code completely, but alas then we see the tile gap then.

    I'll have to do some playing around.

    I played around with it for a few hours. That code is a mess too many cooks in the kitchen with not enough commenting and organization. I can't do anything with it, not at this point anyway.

    Its funny for anyone that wants a under & above water based game in Unity even throwing down 400$ for Triton gets you hardly anywhere for a team of less than 10 people. Water is truly one of the hardest things to master in video games IMO. Fluid dynamics in general I guess (flight sims etc)
     
    Last edited: Feb 16, 2015
  2. HeadHunter2009

    HeadHunter2009

    Joined:
    Jul 3, 2012
    Posts:
    50
    We made nice minimap with lens effect for radar.
    Minimap.png
     
    idurvesh and odival like this.
  3. odival

    odival

    Joined:
    Jun 11, 2014
    Posts:
    57
    @Nsomnia I'm not sure what you mean with black polys, could you post a pic?
    This ocean has those walls and some static tiles that extends towards visible distance. I've got them from the Hearts of Oak version. They don't work so good in my version, but I didn't see any black polys.
    If you want to remove them completely delete the
    208 to 223:
    Code (CSharp):
    1. //Captain's code for static tiles
    2.         GameObject BuildStaticTile (Vector3 pos, Vector3 scale, Quaternion rotation, Mesh mesh, GameObject parentTiles, Material material) {
    3.         GameObject tile = new GameObject ("StaticTile_" + pos.x + "_" + pos.z);
    4.         tile.transform.position=pos;
    5.         MeshFilter mf = tile.AddComponent <MeshFilter>();
    6.         mf.sharedMesh = mesh;
    7.         tile.AddComponent ("MeshRenderer");
    8.         tile.renderer.material = material;
    9.         tile.transform.parent = parentTiles.transform;
    10.         tile.transform.localScale = scale;
    11.         tile.transform.rotation = rotation;
    12.         tile.isStatic = true;
    13.  
    14.         return tile;
    15.     }
    16.     //End of Captain's code
    270 to 312:
    Code (CSharp):
    1. //Captain's code for static tiles
    2.         //GameObject parentTile=new GameObject("ParentTile");
    3.         GameObject tile;
    4.  
    5.         //make empty tiles that use a simplified mesh
    6.         Mesh emptyMesh = new Mesh ();
    7.         emptyMesh = CreateMesh(0.5f);
    8.  
    9.         //build static tiles only
    10.         //take the current position, move to halfway between the end of the active tiles and the farclip
    11.         //float _maxWidth = Camera.main.farClipPlane * 2;
    12.         float _distanceToOffsetX = size.x * tiles;
    13.         float _distanceToOffsetZ = size.z * tiles;
    14.         float _sizeX = size.x * tiles;
    15.         float _sizeZ = size.z * tiles;
    16.  
    17.         //build the tiles a certain number of spaces away
    18.         // take the main camera's farClipPlane from it, and then creates a count for x and y tiles by
    19.         //dividing the current tile size by the x/y of the active tiles
    20.         int _staticTilesX = (int)((Camera.main.farClipPlane + (tiles * size.x)) / (tiles * size.x));
    21.         int _staticTilesZ = (int)((Camera.main.farClipPlane + (tiles * size.z)) / (tiles * size.z));
    22.         GameObject _staticTiles = new GameObject ("StaticTiles");
    23.         _staticTiles.transform.parent = transform; //Parent the static tiles to the Ocean GO
    24.         for (int sZ = -_staticTilesZ; sZ < _staticTilesZ; sZ++) {
    25.             for (int sX = -_staticTilesX; sX < _staticTilesX; sX++) {
    26.                 if (!(sX == 0 && sZ == 0)) {
    27.                     BuildStaticTile (new Vector3 (_distanceToOffsetX * sX, 0, _distanceToOffsetZ * sZ), new Vector3 (_sizeX, 0, _sizeZ),Quaternion.Euler(-180,0,0), emptyMesh, _staticTiles, material);
    28.                 }
    29.             }
    30.         }
    31.        
    32.         //build walls along the edge that will keep the user from seeing a gap in the ocean tiles
    33.         float wH = Mathf.Sqrt (Mathf.Pow (20,2) / 2) / 2;
    34.         float wX = tiles / 2f * size.x;
    35.         float wZ = tiles / 2f * size.z;
    36.         BuildStaticTile (new Vector3 (0,-wH + 0.001f, wZ - wH), new Vector3 (_sizeX, 0, 20),Quaternion.AngleAxis(130, Vector3.right), emptyMesh, _staticTiles, material);
    37.         BuildStaticTile (new Vector3 (0,-wH + 0.001f, -wZ + wH), new Vector3 (_sizeX, 0, 20),Quaternion.AngleAxis(-130, Vector3.right), emptyMesh, _staticTiles, material);
    38.         BuildStaticTile (new Vector3 (wX - wH,-wH + 0.001f, 0), new Vector3 (20, 0, _sizeZ),Quaternion.AngleAxis(-130, Vector3.forward), emptyMesh, _staticTiles, material);
    39.         BuildStaticTile (new Vector3 (-wX + wH,-wH + 0.001f, 0), new Vector3 (20, 0, _sizeZ),Quaternion.AngleAxis(130, Vector3.forward), emptyMesh, _staticTiles, material);
    40.  
    41.         //wall.transform.Rotate (Vector3.right, -45);
    42.        
    43.         //End of Captain's code
    1182 to 1208:
    Code (CSharp):
    1. //Captain's code for static tiles
    2.     Mesh CreateMesh(float width)
    3.     {
    4.         Mesh m = new Mesh();
    5.         m.name = "ScriptedMesh";
    6.         m.vertices = new Vector3[] {
    7.             new Vector3(-width, 0.01f, -width),
    8.             new Vector3(width, 0.01f, -width),
    9.             new Vector3(width, 0.01f, width),
    10.             new Vector3(-width, 0.01f, width)
    11.         };
    12.         m.uv = new Vector2[] {
    13.             new Vector2 (0, 0),
    14.             new Vector2 (0, 1),
    15.             new Vector2(1, 1),
    16.             new Vector2 (1, 0)
    17.         };
    18.         m.triangles = new int[] { 0, 1, 2, 0, 2, 3};
    19.         m.RecalculateNormals();
    20.         m.tangents = new Vector4[] {
    21.             new Vector4(0,0,0,0),
    22.             new Vector4(0,0,0,0),
    23.             new Vector4(0,0,0,0),
    24.             new Vector4(0,0,0,0)};
    25.         return m;
    26.     }
    27.     //End of Captain's code

    And remember to uncomment the line 314. The ocean will seem smaller, but without the static tiles.
     
  4. firestorm713q

    firestorm713q

    Joined:
    Jan 6, 2013
    Posts:
    16
    Figured it out! :D I'm so happy with what I've gotten done so far.

    Still working out tiling and some other stuff, but the base simulation is now working!

    https://dl.dropboxusercontent.com/u/116281983/OceanStuff/OceanStuff.html

    Turns out I didn't quite understand what the simulation was doing. I kept regenerating the height field every frame. Once I stopped doing that, I found out that I wasn't understanding how the FFT bits interacted with the initial complex field(I was animating the initial field, which made it explode). Soo glad I found this thread, I wouldn't have been able to figure it out without the community shader.
     
    odival likes this.
  5. odival

    odival

    Joined:
    Jun 11, 2014
    Posts:
    57
    Does these mobile versions - like joaquim's and head@hunter's - use real time FFT calculation or does it use a pre-calculated FFT table?

    Hello @CaptainMurphy , can you tell me what the edgeBlend is suposed to do, and how?
     
    Last edited: Feb 26, 2015
  6. ZJP

    ZJP

    Joined:
    Jan 22, 2010
    Posts:
    2,649
    Last edited: Mar 15, 2015
    Hormic and KingLlama like this.
  7. Chronster

    Chronster

    Joined:
    Mar 7, 2015
    Posts:
    1
    This is amazing stuff the community did there. Has someone ever tried to do the fft on the gpu, for example in a compute shader? I tried to read up on that topic for a week or so, but I guess I would need a working example because I don't quite understand the algorithms used for calculating inverse fft with multiple threads.
     
  8. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
    Wow, , you guys doing amazing contribution.......brilliant job, kudos....!!

    I just have one question, @Head@Hunter how to create prefab out of ocean? I can see it creates water at run time,....I tried to create plane > added material >shader, though it do not gives that stormy ,mist effect...
     
  9. HeadHunter2009

    HeadHunter2009

    Joined:
    Jul 3, 2012
    Posts:
    50
    Just open scene in Ocean project, and you will see how it works.
     
  10. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
    @Head@Hunter yeah I get it how it works, though not sure can I make racing tracks with it? Actually I'm making mobile racing game on water, so need to create racing tracks of water, could this be possible with it? As I need to store prefabs of diffrent length n turns
     
  11. HeadHunter2009

    HeadHunter2009

    Joined:
    Jul 3, 2012
    Posts:
    50
    Yes, just create new prefabs with Boyancy script, you can do anything you want with this Ocean.
     
  12. odival

    odival

    Joined:
    Jun 11, 2014
    Posts:
    57
    Anyone tested any ocean version with Unity5 yet? If so, how well it went?
     
  13. Dheen Doha

    Dheen Doha

    Joined:
    Jan 1, 2015
    Posts:
    10
    Unity 5 have free pro waters with it, and its a little bit soar tastted news for those who were working with water shaders - including me.
    The only relief is in thinking that, pro waters will not work on mobile devices, it requires extra licence even for pro users.

    so, its time to turn your water packs name to "mobile compatible", if u were trying to make a few bugs selling any of those watery things...
     
  14. Breyer

    Breyer

    Joined:
    Nov 10, 2012
    Posts:
    412
    @Dheen Doha personal mobile isnt limited in featureset (only splash screen is pro and 100k cap in revenue apply) as well so dont worry only limitation is hardware.

    Btw do you know that wind component have exposed properties in unity5? They are no longer internal so you could use them to simulate wind on water

    Ah and i saw somewhere splash water effect free project they was pro only in the past but this is no longer problem you could integrate them if you want. I will post link later, now im on phone

    EDIT

    http://forum.unity3d.com/threads/gp...desktop-and-ios-source-code-available.182296/ there is
     
    Last edited: Mar 21, 2015
    idurvesh and odival like this.
  15. odival

    odival

    Joined:
    Jun 11, 2014
    Posts:
    57
    Does anyone have any idea how we could set some pre-calculated FFT tables, so the Ocean script has only to lerp between them (without calculating anything in real-time)?
    That would surely increase fps, and make it easy to sync the ocean in multiplayer sessions...
     
  16. Dheen Doha

    Dheen Doha

    Joined:
    Jan 1, 2015
    Posts:
    10
    it may make it robtic
     
  17. DizzyTornado

    DizzyTornado

    Joined:
    Nov 17, 2013
    Posts:
    134
    Any updates?
     
    idurvesh likes this.
  18. leiwww

    leiwww

    Joined:
    Jun 11, 2015
    Posts:
    4
    Is there anybody help me?
    Gerstner wave is like this:
    upload_2015-6-11_12-22-45.png
    In Unity, There is a water called WaterPro , the main function of its shader is GerstnerOffset4.
    how to explain it?
    half3 GerstnerOffset4 (half2 xzVtx, half4 steepness, half4 amp, half4 freq, half4 speed, half4 dirAB, half4 dirCD)
    {
    half3 offsets;

    half4 AB = steepness.xxyy * amp.xxyy * dirAB.xyzw;
    half4 CD = steepness.zzww * amp.zzww * dirCD.xyzw;

    half4 dotABCD = freq.xyzw * half4(dot(dirAB.xy, xzVtx), dot(dirAB.zw, xzVtx), dot(dirCD.xy, xzVtx), dot(dirCD.zw, xzVtx)); //this equals to K*x?
    half4 TIME = _Time.yyyy * speed;

    half4 COS = cos (dotABCD + TIME);
    half4 SIN = sin (dotABCD + TIME);

    offsets.x = dot(COS, half4(AB.xz, CD.xz));
    offsets.z = dot(COS, half4(AB.yw, CD.yw));
    offsets.y = dot(SIN, amp);

    return offsets;
    }
     
    Last edited: Jun 11, 2015
  19. leiwww

    leiwww

    Joined:
    Jun 11, 2015
    Posts:
    4
    well, I add the notes myself.
    half3 GerstnerOffset4 (half2 xzVtx, half4 steepness, half4 amp, half4 freq, half4 speed, half4 dirAB, half4 dirCD)
    {
    half3 offsets;

    half4 dotABCD = freq.xyzw * half4(dot(dirAB.xy, xzVtx), dot(dirAB.zw, xzVtx), dot(dirCD.xy, xzVtx), dot(dirCD.zw, xzVtx));
    /*
    (dirAB.x * xzVtx.x + dirAB.y * xzVtx.z)*freq.x,
    (dirAB.z * xzVtx.x + dirAB.w * xzVtx.z))*freq.y,
    (dirCD.x * xzVtx.x + dirCD.y * xzVtx.z))*freq.z,
    (dirCD.z * xzVtx.x + dirCD.w * xzVtx.z))*freq.w,
    */
    half4 TIME = _Time.yyyy * speed;

    half4 COS = cos (dotABCD + TIME);
    half4 SIN = sin (dotABCD + TIME);

    half4 AB = steepness.xxyy * amp.xxyy * dirAB.xyzw;
    half4 CD = steepness.zzww * amp.zzww * dirCD.xyzw;
    /* AB =
    steepness.x * amp.x * dirAB.x,
    steepness.x * amp.x * dirAB.y,
    steepness.y * amp.y * dirAB.z,
    steepness.y * amp.y * dirAB.w
    CD =
    steepness.z * amp.z * dirCD.x,
    steepness.z * amp.z * dirCD.y,
    steepness.w * amp.w * dirCD.z,
    steepness.w * amp.w * dirCD.w
    */

    /* half4(AB.xz, CD.xz):
    steepness.x * amp.x * dirAB.x,
    steepness.y * amp.y * dirAB.z,
    steepness.z * amp.z * dirCD.x,
    steepness.w * amp.w * dirCD.z,
    half4(AB.yw, CD.yw):
    steepness.x * amp.x * dirAB.y,
    steepness.y * amp.y * dirAB.w,
    steepness.z * amp.z * dirCD.y,
    steepness.w * amp.w * dirCD.w
    */
    offsets.x = dot(COS, half4(AB.xz, CD.xz));
    offsets.z = dot(COS, half4(AB.yw, CD.yw));
    offsets.y = dot(SIN, amp);

    /* offsets.x:
    Math.cos(dirAB.x * xzVtx.x + dirAB.y * xzVtx.z + TIME)*freq.x* steepness.x * amp.x * dirAB.x +
    Math.cos(dirAB.z * xzVtx.x + dirAB.w * xzVtx.z + TIME)*freq.y* steepness.y * amp.y * dirAB.z +
    Math.cos(dirCD.x * xzVtx.x + dirCD.y * xzVtx.z + TIME)*freq.z* steepness.z * amp.z * dirCD.x +
    Math.cos(dirCD.z * xzVtx.x + dirCD.w * xzVtx.z+ TIME)*freq.w* steepness.w * amp.w * dirCD.z

    offsets.z:
    Math.cos(dirAB.x * xzVtx.x + dirAB.y * xzVtx.z + TIME)*freq.x* steepness.x * amp.x * dirAB.y+
    Math.cos(dirAB.z * xzVtx.x + dirAB.w * xzVtx.z + TIME)*freq.y* steepness.y * amp.y * dirAB.w +
    Math.cos(dirCD.x * xzVtx.x + dirCD.y * xzVtx.z + TIME)*freq.z* steepness.z * amp.z * dirCD.y +
    Math.cos(dirCD.z * xzVtx.x + dirCD.w * xzVtx.z+ TIME)*freq.w* steepness.w * amp.w * dirCD.w

    offsets.y:
    Math.sin(dirAB.x * xzVtx.x + dirAB.y * xzVtx.z + TIME)*freq.x*amp.x +
    Math.sin(dirAB.z * xzVtx.x + dirAB.w * xzVtx.z + TIME)*freq.y*amp.y +
    Math.sin(dirCD.x * xzVtx.x + dirCD.y * xzVtx.z + TIME)*freq.z*amp.z +
    Math.sin(dirCD.z * xzVtx.x + dirCD.w * xzVtx.z+ TIME)*freq.w*amp.w
    */
    return offsets;
    }
     
    Last edited: Jun 11, 2015
  20. CaptainMurphy

    CaptainMurphy

    Joined:
    Jul 15, 2014
    Posts:
    746
    It might help if we knew what exactly you needed help with. Are you trying to apply this to the tops of the waves?
     
  21. leiwww

    leiwww

    Joined:
    Jun 11, 2015
    Posts:
    4
    Thanks for your replay. At first i can't understand the relationship between the GerstnerOffset4 function and Gerstner formula.
    At that time i down't know what does the parameter mean and how to make Gerstenr wave. And now i know a litter. The GerstnerOffset4 function create four waves at once. A single wave only have a direction with two parameters represent x direction, z direction in the horizontal plane. Am i right?
     
  22. leiwww

    leiwww

    Joined:
    Jun 11, 2015
    Posts:
    4
    I create the wave based on the example of unity water. It's so regular. how to improve it? Can i change the amplitude of each vetex by such function as perlin noise or any other?
    upload_2015-6-12_9-49-39.png
     
  23. fleet15

    fleet15

    Joined:
    Jul 1, 2015
    Posts:
    2
    I'm trying to use the ocean surface height to produce simplified ship dynamics. The current problem I am having is that GetWaterHeightAtLocation is not returning the correct value for the ocean height. Has anyone else encountered this problem with the ocean script to find wave height?
     
  24. HeadHunter2009

    HeadHunter2009

    Joined:
    Jul 3, 2012
    Posts:
    50
    It should return correct value, becouse Bayancy script using it and work just great, why you dont want just to use allredy working solution? To get correct value from GetWaterHeightAtLocation you should provide valid object position.
     
  25. hugo-tguerra

    hugo-tguerra

    Joined:
    Jul 7, 2013
    Posts:
    13
    I'm trying to get an ocean shader with coastal waves that works well with a bird's eye view but the only decent solution I found for unity was the (very expensive) Triton asset.

    But I also found this article dissecting such a shader. How hard would it be to do that in unity?
     
  26. John-G

    John-G

    Joined:
    Mar 21, 2013
    Posts:
    1,122
    Ceto will be running open beta soon, best ocean I've seen and used in Unity. Check out the thread in wip.
     
  27. ludos

    ludos

    Joined:
    Nov 14, 2011
    Posts:
    55
    hi, the mobile ocean water code is great. but as fleet15 mentioned, the GetWaterHeightAtLocation is not returning correct values. It may return the correct values for a vertex, but the vertex x/z position is moving, which causes the position to be incorrect most of the time. A small script such as the following will make it obvious:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class ApplyOceanHeight : MonoBehaviour {
    5.  
    6.     Ocean ocean;
    7.  
    8.     // Use this for initialization
    9.     void Start () {
    10.         ocean = FindObjectOfType<Ocean> ();
    11.     }
    12.    
    13.     // Update is called once per frame
    14.     void Update () {
    15.         Vector3 pos = transform.position;
    16.         pos.y = ocean.GetWaterHeightAtLocation(pos.x, pos.z);
    17.         transform.position = pos
    18.     }
    19. }
    20.  
     
  28. NullSignal

    NullSignal

    Joined:
    Sep 18, 2013
    Posts:
    45
    Is 1.1 the latest version? I'm having issues with the ocean being rendered at some location other than where the game object is. I can move the gameobject around and the ocean moves, but the ocean itself is never where my gameobject is. I can only move it in the editor (while the game isn't running) and guessing where to put it is proving futile. Anyone know what I've done?

    EDIT: I got it where it needs to be through trial and error.
     
    Last edited: Oct 1, 2015
  29. NullSignal

    NullSignal

    Joined:
    Sep 18, 2013
    Posts:
    45
    Is there any way to make this Ocean work with deferred lighting?
     
  30. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    For the current ocean if you really want to using it. It would run better if you strip the code only get the Ocean Height and normal generator then use a custom standard shader with tesellation
     
  31. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    The Boyancy on android no working :(
     
  32. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    I fixed the ocean and Boyancy script for working on android :

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class Ocean : MonoBehaviour
    6. {
    7.     public bool fixedTiles;
    8.     public int fTilesDistance = 2;
    9.     public int fTilesLod = 5;
    10.     public int width = 32;
    11.     public int height = 32;
    12.     public int renderTexWidth = 128;
    13.     public int renderTexHeight = 128;
    14.     public float scale = 0.1f;
    15.     private float waveScale = 1f;
    16.     public float speed = 0.7f;
    17.     public float wakeDistance = 5f;
    18.     public Vector3 size = new Vector3 (150.0f, 1.0f, 150.0f);
    19.     public int tiles = 2;
    20.  
    21.     public static Ocean Singleton { get; private set; }
    22.  
    23.     public float pWindx=10.0f;
    24.     public float windx {
    25.         get {
    26.             return pWindx;
    27.         }
    28.         set {
    29.             if (value!=pWindx) {
    30.                 this.pWindx=value;
    31.                 this.InitWaveGenerator();
    32.             }
    33.         }
    34.     }
    35.  
    36.     public float pWindy=10.0f;
    37.     public float windy {
    38.         get {
    39.             return pWindy;
    40.         }
    41.         set {
    42.             if (value!=pWindy) {
    43.                 this.pWindy=value;
    44.                 this.InitWaveGenerator();
    45.             }
    46.         }
    47.     }
    48.  
    49.     private int pNormal_scale=8;
    50.     public int normal_scale {
    51.         get {
    52.             return pNormal_scale;
    53.         }
    54.         set {
    55.             if (value!=pNormal_scale) {
    56.                 pNormal_scale=value;
    57.                 this.InitWaveGenerator();
    58.             }
    59.         }
    60.     }
    61.     private float pNormalStrength=2f;
    62.     public float normalStrength {
    63.         get {
    64.             return pNormalStrength;
    65.         }
    66.         set {
    67.             if (value!=pNormalStrength) {
    68.                 pNormalStrength=value;
    69.             }
    70.         }
    71.     }
    72.     public float choppy_scale = 2.0f;
    73.  
    74.     public Material material;
    75.     public bool followMainCamera = true;
    76.     private int max_LOD = 6;
    77.     private ComplexF[] h0;
    78.     private ComplexF[] t_x;
    79.     private ComplexF[] n0;
    80.     private ComplexF[] n_x;
    81.     private ComplexF[] n_y;
    82.     private ComplexF[] data;
    83.     private Color[] pixelData;
    84.     private Vector3[] baseHeight;
    85.  
    86.     private Mesh baseMesh;
    87.     private GameObject child;
    88.     private List<List<Mesh>> tiles_LOD;
    89.     private List<List<Mesh>> fTiles_LOD;
    90.     private int g_height;
    91.     private int g_width;
    92.     private int n_width;
    93.     private int n_height;
    94.     private Vector2 sizeInv;
    95.    
    96.     private bool normalDone = false;
    97.     private bool reflectionRefractionEnabled = false;
    98.     public float m_ClipPlaneOffset = 0.07f;
    99.     private RenderTexture m_ReflectionTexture = null;
    100.     private RenderTexture m_RefractionTexture = null;
    101.     private Dictionary<Camera, Camera> m_ReflectionCameras = new Dictionary<Camera, Camera>(); // Camera -> Camera table
    102.     private Dictionary<Camera, Camera> m_RefractionCameras = new Dictionary<Camera, Camera>(); // Camera -> Camera table
    103.     private int m_OldReflectionTextureSize = 0;
    104.     private int m_OldRefractionTextureSize = 0;
    105.     public LayerMask renderLayers = -1;
    106.  
    107.     private Vector3[] vertices;
    108.     private Vector3[] normals;
    109.     private Vector4[] tangents;
    110.     public Transform player;
    111.     public Transform sun;
    112.     public Vector4 SunDir;
    113.  
    114.     public Color surfaceColor = new Color (0.3f, 0.5f, 0.3f, 1.0f);
    115.     public Color waterColor = new Color (0.3f, 0.4f, 0.3f);
    116.  
    117.     public Shader oceanShader;
    118.     public bool renderReflection = true;
    119.     public bool renderRefraction = true;
    120.  
    121.     //Shader wave offset animation speed
    122.     public float waveSpeed = 10f;
    123.     private float prevOffsetValue = 0;
    124.     private float nextOffsetValue = 0;
    125.     private float prevOffsetTime = -100000;
    126.     private const float offsetTimeFreq = 1f/ 60f;
    127.     private int swich;
    128.  
    129.     //Humidity values
    130.     public bool dinamicWaves;
    131.     public static float wind;
    132.     public float humidity;
    133.     private float prevValue = 0.1f;
    134.     private float nextValue = 0.4f;
    135.     private float prevTime = 1;
    136.     private const float timeFreq = 1f/ 280f;
    137.  
    138.     public GameObject mist;
    139.     public GameObject mistLow;
    140.     public GameObject mistClouds;
    141.     public bool mistEnabled;
    142.     public bool waterInteractionEffects;
    143.  
    144.     private float GetHumidity() {
    145.         float time = Time.time;
    146.        
    147.         int intTime = (int)(time * timeFreq);
    148.         int intPrevTime = (int)(prevTime * timeFreq);
    149.        
    150.         if (intTime != intPrevTime){
    151.             prevValue = nextValue;
    152.             nextValue = Random.value;
    153.         }
    154.         prevTime = time;
    155.         float frac = time * timeFreq - intTime;
    156.        
    157.         return Mathf.SmoothStep(prevValue, nextValue, frac);
    158.     }
    159.  
    160.     private float GetFloat() {
    161.         float time = Time.time * waveSpeed;
    162.        
    163.         int intTime = (int)(time * offsetTimeFreq);
    164.         int intPrevTime = (int)(prevOffsetTime * offsetTimeFreq);
    165.        
    166.         if (prevOffsetTime < 0){
    167.             nextOffsetValue = -100;
    168.         }
    169.        
    170.         if (intTime != intPrevTime){
    171.             prevOffsetValue = nextOffsetValue;
    172.             if(swich == 0){
    173.                 nextOffsetValue = 100;
    174.                 swich = 1;  
    175.             }else if(swich == 1){
    176.                 nextOffsetValue = -100;
    177.                 swich = 0;
    178.             }
    179.         }
    180.         prevOffsetTime = time;
    181.         float frac = time * offsetTimeFreq - intTime;
    182.        
    183.         return Mathf.Lerp(prevOffsetValue, nextOffsetValue, frac);
    184.     }
    185.  
    186.     IEnumerator AddMist () {
    187.         while(true){
    188.             if(player != null && mistEnabled){
    189.                 Vector3 pos = new Vector3(player.transform.position.x + Random.Range(-30, 30), player.transform.position.y + 5, player.transform.position.z + Random.Range(-30, 30));
    190.                 if(wind >= 0.7f){
    191.                     if (mistClouds != null && mist != null)
    192.                     {
    193.                         GameObject mistParticles = Instantiate(mist, pos, new Quaternion(0, 0, 0, 0)) as GameObject;
    194.                         mistParticles.transform.parent = transform;
    195.                         GameObject clouds = Instantiate(mistClouds, pos, new Quaternion(0, 0, 0, 0)) as GameObject;
    196.                         clouds.transform.parent = transform;
    197.                     }
    198.                 }else if(wind > 0.4f){
    199.                     if(mist != null)
    200.                     {
    201.                         GameObject mistParticles = Instantiate(mist, pos, new Quaternion(0,0,0,0)) as GameObject;
    202.                         mistParticles.transform.parent = transform;
    203.                         yield return new WaitForSeconds(0.5f);
    204.                     }
    205.                 }
    206.                 else if(mistLow != null){
    207.                     GameObject mistParticles = Instantiate(mistLow, pos, new Quaternion(0,0,0,0)) as GameObject;
    208.                     mistParticles.transform.parent = transform;
    209.                     yield return new WaitForSeconds(1f);
    210.                 }
    211.             }
    212.             yield return new WaitForSeconds(0.5f);
    213.            
    214.         }
    215.     }
    216.    
    217.     public void SetWaves (float wind) {
    218.         waveScale = Mathf.Lerp(0, scale, wind);
    219.     }
    220.    
    221.     public float GetWaterHeightAtLocation(float x, float y)
    222.     {
    223.  
    224.         x = x / size.x;
    225.         x = (x-Mathf.FloorToInt(x)) * width;
    226.         y = y / size.z;
    227.         y = (y-Mathf.FloorToInt(y)) * height;
    228.  
    229.         int index = (int)width * Mathf.FloorToInt(y) + Mathf.FloorToInt(x);
    230.  
    231.         return data[index].Re * waveScale / (width * height);
    232.     }
    233.  
    234.     float GaussianRnd ()
    235.     {
    236.         float x1 = Random.value;
    237.         float x2 = Random.value;
    238.    
    239.         if (x1 == 0.0f)
    240.             x1 = 0.01f;
    241.    
    242.         return (float)(System.Math.Sqrt (-2.0 * System.Math.Log (x1)) * System.Math.Cos (2.0 * Mathf.PI * x2));
    243.     }
    244.  
    245.     // Phillips spectrum
    246.     float P_spectrum (Vector2 vec_k, Vector2 wind)
    247.     {
    248.         float A = vec_k.x > 0.0f ? 1.0f : 0.05f; // Set wind to blow only in one direction - otherwise we get turmoiling water
    249.    
    250.         float L = wind.sqrMagnitude / 9.81f;
    251.         float k2 = vec_k.sqrMagnitude;
    252.         // Avoid division by zero
    253.         if (vec_k.sqrMagnitude == 0.0f) {
    254.             return 0.0f;
    255.         }
    256.         float vcsq=vec_k.magnitude;  
    257.         return (float)(A * System.Math.Exp (-1.0f / (k2 * L * L) - System.Math.Pow (vcsq * 0.1, 2.0)) / (k2 * k2) * System.Math.Pow (Vector2.Dot (vec_k / vcsq, wind / wind.magnitude), 2.0));// * wind_x * wind_y;
    258.     }
    259.  
    260.     void Awake()
    261.     {
    262.         Singleton = this;
    263.     }
    264.  
    265.     void Start ()
    266.     {
    267.  
    268.         // normal map size
    269.         n_width = 128;
    270.         n_height = 128;
    271.        
    272.         //Avoid division every frame, so do it only once on start up
    273.         sizeInv = new Vector2(1f / size.x,  1f / size.z);
    274.        
    275.         SetupOffscreenRendering ();
    276.  
    277.    
    278.         pixelData = new Color[n_width * n_height];
    279.  
    280.         // Init the water height matrix
    281.         data = new ComplexF[width * height];
    282.  
    283.         // tangent
    284.         t_x = new ComplexF[width * height];
    285.  
    286.         n_x = new ComplexF[n_width * n_height];
    287.         n_y = new ComplexF[n_width * n_height];
    288.  
    289.         // Geometry size
    290.         g_height = height + 1;  
    291.         g_width = width + 1;
    292.  
    293.         tiles_LOD = new List<List<Mesh>>();
    294.         fTiles_LOD = new List<List<Mesh>>();
    295.  
    296.         for (int L0D=0; L0D<max_LOD; L0D++) {
    297.             tiles_LOD.Add (new List<Mesh>());
    298.         }
    299.  
    300.         for (int L0D=0; L0D<max_LOD; L0D++) {
    301.             fTiles_LOD.Add (new List<Mesh>());
    302.         }
    303.  
    304.         GameObject tile;
    305.  
    306.         int chDist; // Chebychev distance  
    307.         for (int y=0; y<tiles; y++) {
    308.             for (int x=0; x<tiles; x++) {
    309.                 chDist = System.Math.Max (System.Math.Abs (tiles / 2 - y), System.Math.Abs (tiles / 2 - x));
    310.                 chDist = chDist > 0 ? chDist - 1 : 0;
    311.                 float cy = y - Mathf.Floor(tiles * 0.5f);
    312.                 float cx = x - Mathf.Floor(tiles * 0.5f);
    313.                 tile = new GameObject ("WaterTile");
    314.                
    315.                 Vector3 pos=tile.transform.position;
    316.                 pos.x = cx * size.x;
    317.                 pos.y = transform.position.y;
    318.                 pos.z = cy * size.z;
    319.                 tile.transform.position=pos;
    320.                 tile.AddComponent (typeof(MeshFilter));
    321.                 tile.AddComponent <MeshRenderer>();
    322.                 material.renderQueue = 3000;
    323.                 tile.GetComponent<Renderer>().material = material;
    324.                 //Make child of this object, so we don't clutter up the
    325.                 //scene hierarchy more than necessary.
    326.                 tile.transform.parent = transform;
    327.            
    328.                 //Also we don't want these to be drawn while doing refraction/reflection passes,
    329.                 //so we'll add the to the water layer for easy filtering.
    330.                 tile.layer = LayerMask.NameToLayer ("Water");
    331.            
    332.                 // Determine which L0D the tile belongs
    333.                 if(fixedTiles){
    334.                     if(chDist < fTilesDistance)
    335.                         tiles_LOD[chDist].Add((tile.GetComponent<MeshFilter>()).mesh);
    336.                     else
    337.                         fTiles_LOD[fTilesLod].Add((tile.GetComponent<MeshFilter>()).mesh);
    338.                 }else{
    339.                     tiles_LOD[chDist].Add((tile.GetComponent<MeshFilter>()).mesh);
    340.                 }
    341.             }
    342.         }
    343.  
    344.    
    345.         // Init wave spectra. One for vertex offset and another for normal map
    346.         h0 = new ComplexF[width * height];
    347.         n0 = new ComplexF[n_width * n_height];
    348.        
    349.         InitWaveGenerator();
    350.         UpdateWaterColor ();
    351.         GenerateHeightmap ();
    352.         StartCoroutine(AddMist());
    353.     }
    354.    
    355.     void InitWaveGenerator() {
    356.         // Wind restricted to one direction, reduces calculations
    357.         Vector2 windDirection = new Vector2 (windx, windy);
    358.  
    359.         // Initialize wave generator  
    360.         for (int y=0; y<height; y++) {
    361.             for (int x=0; x<width; x++) {
    362.                 float yc = y < height / 2f ? y : -height + y;
    363.                 float xc = x < width / 2f ? x : -width + x;
    364.                 Vector2 vec_k = new Vector2 (2.0f * Mathf.PI * xc / size.x, 2.0f * Mathf.PI * yc / size.z);
    365.                 h0 [width * y + x] = new ComplexF (GaussianRnd (), GaussianRnd ()) * 0.707f * (float)System.Math.Sqrt (P_spectrum (vec_k, windDirection));
    366.             }
    367.         }
    368.  
    369.         for (int y=0; y<n_height; y++) {
    370.             for (int x=0; x<n_width; x++) {  
    371.                 float yc = y < n_height / 2f ? y : -n_height + y;
    372.                 float xc = x < n_width / 2f ? x : -n_width + x;
    373.                 Vector2 vec_k = new Vector2 (2.0f * Mathf.PI * xc / (size.x / normal_scale), 2.0f * Mathf.PI * yc / (size.z / normal_scale));
    374.                 n0 [n_width * y + x] = new ComplexF (GaussianRnd (), GaussianRnd ()) * 0.707f * (float)System.Math.Sqrt (P_spectrum (vec_k, windDirection));
    375.             }
    376.         }      
    377.     }
    378.  
    379.     void GenerateHeightmap ()
    380.     {
    381.  
    382.         Mesh mesh = new Mesh ();
    383.  
    384.         int y = 0;
    385.         int x = 0;
    386.  
    387.         // Build vertices and UVs
    388.         Vector3 []vertices = new Vector3[g_height * g_width];
    389.         Vector4 []tangents = new Vector4[g_height * g_width];
    390.         Vector2 []uv = new Vector2[g_height * g_width];
    391.  
    392.         Vector2 uvScale = new Vector2 (1.0f / (g_width - 1f), 1.0f / (g_height - 1f));
    393.         Vector3 sizeScale = new Vector3 (size.x / (g_width - 1f), size.y, size.z / (g_height - 1f));
    394.  
    395.         for (y=0; y<g_height; y++) {
    396.             for (x=0; x<g_width; x++) {
    397.                 Vector3 vertex = new Vector3 (x, 0.0f, y);
    398.                 vertices [y * g_width + x] = Vector3.Scale (sizeScale, vertex);
    399.                 uv [y * g_width + x] = Vector2.Scale (new Vector2 (x, y), uvScale);
    400.             }
    401.         }
    402.    
    403.         mesh.vertices = vertices;
    404.         mesh.uv = uv;
    405.  
    406.         for (y=0; y<g_height; y++) {
    407.             for (x=0; x<g_width; x++) {
    408.                 tangents [y * g_width + x] = new Vector4 (1.0f, 0.0f, 0.0f, -1.0f);
    409.             }
    410.         }
    411.         mesh.tangents = tangents;  
    412.    
    413.         for (int L0D=0; L0D<max_LOD; L0D++) {
    414.             Vector3[] verticesLOD = new Vector3[(int)(height / System.Math.Pow (2, L0D) + 1) * (int)(width / System.Math.Pow (2, L0D) + 1)];
    415.             Vector2[] uvLOD = new Vector2[(int)(height / System.Math.Pow (2, L0D) + 1) * (int)(width / System.Math.Pow (2, L0D) + 1)];
    416.             int idx = 0;
    417.             for (y=0; y<g_height; y+=(int)System.Math.Pow(2,L0D)) {
    418.                 for (x=0; x<g_width; x+=(int)System.Math.Pow(2,L0D)) {
    419.                     verticesLOD [idx] = vertices [g_width * y + x];
    420.                     uvLOD [idx++] = uv [g_width * y + x];
    421.                 }          
    422.             }
    423.             for (int k=0; k<tiles_LOD[L0D].Count; k++) {
    424.                 Mesh meshLOD = tiles_LOD [L0D][k];
    425.                 meshLOD.vertices = verticesLOD;
    426.                 meshLOD.uv = uvLOD;
    427.             }
    428.             for (int k=0; k<fTiles_LOD[L0D].Count; k++) {
    429.                 Mesh meshLOD = fTiles_LOD [L0D][k];
    430.                 meshLOD.vertices = verticesLOD;
    431.                 meshLOD.uv = uvLOD;
    432.             }
    433.         }
    434.  
    435.         // Build triangle indices: 3 indices into vertex array for each triangle
    436.         for (int L0D=0; L0D<max_LOD; L0D++) {
    437.             int index = 0;
    438.             int width_LOD = (int)(width / System.Math.Pow (2, L0D) + 1);
    439.             int[] triangles = new int[(int)(height / System.Math.Pow (2, L0D) * width / System.Math.Pow (2, L0D)) * 6];
    440.             for (y=0; y<(int)(height/System.Math.Pow(2,L0D)); y++) {
    441.                 for (x=0; x<(int)(width/System.Math.Pow(2,L0D)); x++) {
    442.                     // For each grid cell output two triangles
    443.                     triangles [index++] = (y * width_LOD) + x;
    444.                     triangles [index++] = ((y + 1) * width_LOD) + x;
    445.                     triangles [index++] = (y * width_LOD) + x + 1;
    446.  
    447.                     triangles [index++] = ((y + 1) * width_LOD) + x;
    448.                     triangles [index++] = ((y + 1) * width_LOD) + x + 1;
    449.                     triangles [index++] = (y * width_LOD) + x + 1;
    450.                 }
    451.             }
    452.             for (int k=0; k<tiles_LOD[L0D].Count; k++) {
    453.                 Mesh meshLOD = tiles_LOD [L0D][k];
    454.                 meshLOD.triangles = triangles;
    455.             }
    456.             for (int k=0; k<fTiles_LOD[L0D].Count; k++) {
    457.                 Mesh meshLOD = fTiles_LOD [L0D][k];
    458.                 meshLOD.triangles = triangles;
    459.             }
    460.         }
    461.    
    462.         baseMesh = mesh;
    463.  
    464.         //Generate data for fixed tiles
    465.         for (int k=0; k< fTiles_LOD[fTilesLod].Count; k++) {
    466.             Mesh meshLOD = fTiles_LOD [fTilesLod][k];
    467.             meshLOD.RecalculateNormals();
    468.             meshLOD.tangents = new Vector4[] {
    469.                 new Vector4(0.01f,0.01f,0.01f,0.01f),
    470.                 new Vector4(0.01f,0.01f,0.01f,0.01f),
    471.                 new Vector4(0.01f,0.01f,0.01f,0.01f),
    472.                 new Vector4(0.01f,0.01f,0.01f,0.01f)
    473.             };
    474.         }  
    475.     }
    476.  
    477.     public void AssignFolowTarget(Transform tr) {
    478.         player = tr;
    479.     }
    480.  
    481.     void Update ()
    482.     {
    483.         if(material != null){
    484.             if(sun != null){
    485.                 SunDir = sun.transform.forward;
    486.                 material.SetVector ("_SunDir", SunDir);
    487.             }
    488.             material.SetVector("_WaveOffset", new Vector4 (GetFloat(), GetFloat(), GetFloat(), GetFloat()));
    489.         }
    490.  
    491.         if(dinamicWaves)
    492.             humidity = GetHumidity();
    493.  
    494.         wind = humidity;
    495.  
    496.         SetWaves(wind);
    497.  
    498.         if (followMainCamera && player != null) {
    499.            
    500.             Vector3 centerOffset;
    501.             centerOffset.x = Mathf.Floor(player.position.x * sizeInv.x) *  size.x;
    502.             centerOffset.z = Mathf.Floor(player.position.z * sizeInv.y) *  size.z;
    503.             centerOffset.y = transform.position.y;
    504.            
    505.             if(transform.position != centerOffset)
    506.                 transform.position = centerOffset;
    507.            
    508.         }
    509.        
    510.  
    511.         float hhalf=height/2f;
    512.         float whalf=width/2f;
    513.         float time=Time.time;
    514.         for (int y = 0; y<height; y++) {
    515.             for (int x = 0; x<width; x++) {
    516.                 int idx = width * y + x;
    517.                 float yc = y < hhalf ? y : -height + y;
    518.                 float xc = x < whalf ? x : -width + x;
    519.                 Vector2 vec_k = new Vector2 (2.0f * Mathf.PI * xc / size.x, 2.0f * Mathf.PI * yc / size.z);
    520.  
    521.                 float sqrtMagnitude=(float)System.Math.Sqrt((vec_k.x * vec_k.x) + (vec_k.y * vec_k.y));
    522.                 float iwkt = (float)System.Math.Sqrt(9.81f * sqrtMagnitude) * time * speed;
    523.                 ComplexF coeffA = new ComplexF ((float)System.Math.Cos(iwkt), (float)System.Math.Sin(iwkt));
    524.                 ComplexF coeffB;
    525.                 coeffB.Re = coeffA.Re;
    526.                 coeffB.Im = -coeffA.Im;
    527.  
    528.                 int ny = y > 0 ? height - y : 0;
    529.                 int nx = x > 0 ? width - x : 0;
    530.  
    531.                 data [idx] = h0 [idx] * coeffA + h0[width * ny + nx].GetConjugate() * coeffB;              
    532.                 t_x [idx] = data [idx] * new ComplexF (0.0f, vec_k.x) - data [idx] * vec_k.y;
    533.  
    534.                 // Choppy wave calculations
    535.                 if (x + y > 0)
    536.                     data [idx] += data [idx] * vec_k.x / sqrtMagnitude;
    537.             }
    538.         }
    539.  
    540.         Fourier.FFT2 (data, width, height, FourierDirection.Backward);
    541.         Fourier.FFT2 (t_x, width, height, FourierDirection.Backward);
    542.  
    543.         // Get base values for vertices and uv coordinates.
    544.         if (baseHeight == null) {
    545.             baseHeight = baseMesh.vertices;
    546.             vertices = new Vector3[baseHeight.Length];
    547.             normals = new Vector3[baseHeight.Length];
    548.             tangents = new Vector4[baseHeight.Length];
    549.         }
    550.        
    551.         int wh=width*height;
    552.         float scaleA = choppy_scale / wh;
    553.         float scaleB = waveScale / wh;
    554.         float scaleBinv = 1.0f / scaleB;
    555.    
    556.         for (int i=0; i<wh; i++) {
    557.             int iw = i + i / width;
    558.             vertices [iw] = baseHeight [iw];
    559.             vertices [iw].x += data [i].Im * scaleA;
    560.             vertices [iw].y = data [i].Re * scaleB;
    561.  
    562.             normals [iw] = Vector3.Normalize(new Vector3 (t_x [i].Re, scaleBinv, t_x [i].Im));
    563.    
    564.             if (((i + 1) % width)==0) {
    565.                 int iwi=iw+1;
    566.                 int iwidth=i+1-width;
    567.                 vertices [iwi] = baseHeight [iwi];
    568.                 vertices [iwi].x += data [iwidth].Im * scaleA;
    569.                 vertices [iwi].y = data [iwidth].Re * scaleB;
    570.  
    571.                 normals [iwi] = Vector3.Normalize(new Vector3 (t_x [iwidth].Re, scaleBinv, t_x [iwidth].Im));
    572.  
    573.             }
    574.         }
    575.  
    576.         int offset = g_width * (g_height - 1);
    577.  
    578.         for (int i=0; i<g_width; i++) {
    579.             int io=i+offset;
    580.             int mod=i % width;
    581.             vertices [io] = baseHeight [io];
    582.             vertices [io].x += data [mod].Im * scaleA;
    583.             vertices [io].y = data [mod].Re * scaleB;
    584.            
    585.             normals [io] = Vector3.Normalize(new Vector3 (t_x [mod].Re, scaleBinv, t_x [mod].Im));
    586.         }
    587.        
    588.         int gwgh=g_width*g_height-1;
    589.         for (int i=0; i<gwgh; i++) {
    590.            
    591.             //Need to preserve w in refraction/reflection mode
    592.             if (!reflectionRefractionEnabled) {
    593.                 if (((i + 1) % g_width) == 0) {
    594.                     tangents [i] = Vector3.Normalize((vertices [i - width + 1] + new Vector3 (size.x, 0.0f, 0.0f) - vertices [i]));
    595.                 } else {
    596.                     tangents [i] = Vector3.Normalize((vertices [i + 1] - vertices [i]));
    597.                 }
    598.            
    599.                 tangents [i].w = 1.0f;
    600.             } else {
    601.                 Vector3 tmp;// = Vector3.zero;
    602.            
    603.                 if (((i + 1) % g_width) == 0) {
    604.                     tmp = Vector3.Normalize(vertices[i - width + 1] + new Vector3 (size.x, 0.0f, 0.0f) - vertices [i]);
    605.                 } else {
    606.                     tmp = Vector3.Normalize(vertices [i + 1] - vertices [i]);
    607.                 }
    608.                
    609.                 tangents [i] = new Vector4 (tmp.x, tmp.y, tmp.z, tangents [i].w);
    610.             }
    611.         }
    612.        
    613.        
    614.        
    615.         //Vector3 playerRelPos =  player.position - transform.position;
    616.        
    617.         //In reflection mode, use tangent w for foam strength
    618.         if (reflectionRefractionEnabled) {
    619.             for (int y = 0; y < g_height; y++) {
    620.                 for (int x = 0; x < g_width; x++) {
    621.                     int item=x + g_width * y;
    622.                     if (x + 1 >= g_width) {
    623.                         tangents [item].w = tangents [g_width * y].w;
    624.                    
    625.                         continue;
    626.                     }
    627.                    
    628.                     if (y + 1 >= g_height) {
    629.                         tangents [item].w = tangents [x].w;
    630.                        
    631.                         continue;
    632.                     }
    633.                
    634.                     float right = vertices[(x + 1) + g_width * y].x - vertices[item].x;
    635.                    
    636.                     float foam = right/(size.x / g_width);
    637.                    
    638.                    
    639.                     if (foam < 0.0f)
    640.                         tangents [item].w = 1f;
    641.                     else if (foam < 0.5f)
    642.                         tangents [item].w += 3.0f * Time.deltaTime;
    643.                     else
    644.                         tangents [item].w -= 0.4f * Time.deltaTime;
    645.                    
    646.                     if (player != null )
    647.                     {
    648.                         Vector3 player2Vertex = (player.position - vertices[item] - transform.position);
    649.                         // foam around boat
    650.                         if (player2Vertex.x >= size.x)
    651.                             player2Vertex.x -= size.x;
    652.                        
    653.                         if (player2Vertex.x<= -size.x)
    654.                             player2Vertex.x += size.x;
    655.                        
    656.                         if (player2Vertex.z >= size.z)
    657.                             player2Vertex.z -= size.z;
    658.                        
    659.                         if (player2Vertex.z<= -size.z)
    660.                             player2Vertex.z += size.z;
    661.                         player2Vertex.y = 0;
    662.                        
    663.                         if (player2Vertex.sqrMagnitude < wakeDistance * wakeDistance)
    664.                             tangents[item].w += 3.0f * Time.deltaTime;
    665.  
    666.                     }
    667.                    
    668.                    
    669.                     tangents [item].w = Mathf.Clamp (tangents[item].w, 0.0f, 2.0f);
    670.                 }
    671.             }
    672.         }
    673.    
    674.         tangents [gwgh] = Vector4.Normalize(vertices [gwgh] + new Vector3 (size.x, 0.0f, 0.0f) - vertices [1]);
    675.  
    676.         for (int L0D=0; L0D<max_LOD; L0D++) {
    677.             int den = (int)System.Math.Pow (2f, L0D);
    678.             int itemcount = (int)((height / den + 1) * (width / den + 1));
    679.        
    680.             Vector4[] tangentsLOD = new Vector4[itemcount];
    681.             Vector3[] verticesLOD = new Vector3[itemcount];
    682.             Vector3[] normalsLOD = new Vector3[itemcount];
    683.    
    684.             int idx = 0;
    685.  
    686.             for (int y=0; y<g_height; y+=den) {
    687.                 for (int x=0; x<g_width; x+=den) {
    688.                     int idx2 = g_width * y + x;
    689.                     verticesLOD [idx] = vertices [idx2];
    690.                     tangentsLOD [idx] = tangents [idx2];
    691.                     normalsLOD [idx++] = normals [idx2];
    692.                 }          
    693.             }
    694.             for (int k=0; k< tiles_LOD[L0D].Count; k++) {
    695.                 Mesh meshLOD = tiles_LOD [L0D][k];
    696.                 meshLOD.vertices = verticesLOD;
    697.                 meshLOD.normals = normalsLOD;
    698.                 meshLOD.tangents = tangentsLOD;
    699.             }  
    700.         }
    701.     }
    702.  
    703.     /*
    704.     Prepares the scene for offscreen rendering; spawns a camera we'll use for for
    705.     temporary renderbuffers as well as the offscreen renderbuffers (one for
    706.     reflection and one for refraction).
    707.     */
    708.    
    709.     void SetupOffscreenRendering ()
    710.     {
    711.         material.SetVector ("_Size", new Vector4 (size.x, size.y, size.z, 0.0f));
    712.        
    713.         //Hack to make this object considered by the renderer - first make a plane
    714.         //covering the watertiles so we get a decent bounding box, then
    715.         //scale all the vertices to 0 to make it invisible.
    716.         gameObject.AddComponent (typeof(MeshRenderer));
    717.         GetComponent<Renderer>().material.renderQueue = 1001;
    718.         GetComponent<Renderer>().receiveShadows = false;
    719.         GetComponent<Renderer>().castShadows = false;
    720.        
    721.         Mesh m = new Mesh ();
    722.        
    723.         Vector3[] verts = new Vector3[4];
    724.         Vector2[] uv = new Vector2[4];
    725.         Vector3[] n = new Vector3[4];
    726.         int[] tris = new int[6];
    727.        
    728.         float minSizeX = -1024;
    729.         float maxSizeX = 1024;
    730.        
    731.         float minSizeY = -1024;
    732.         float maxSizeY = 1024;
    733.        
    734.         verts [0] = new Vector3 (minSizeX, 0.0f, maxSizeY);
    735.         verts [1] = new Vector3 (maxSizeX, 0.0f, maxSizeY);
    736.         verts [2] = new Vector3 (maxSizeX, 0.0f, minSizeY);
    737.         verts [3] = new Vector3 (minSizeX, 0.0f, minSizeY);
    738.        
    739.         tris [0] = 0;
    740.         tris [1] = 1;
    741.         tris [2] = 2;
    742.        
    743.         tris [3] = 2;
    744.         tris [4] = 3;
    745.         tris [5] = 0;
    746.        
    747.         m.vertices = verts;
    748.         m.uv = uv;
    749.         m.normals = n;
    750.         m.triangles = tris;
    751.  
    752.         MeshFilter mfilter = gameObject.GetComponent<MeshFilter>();
    753.        
    754.         if (mfilter == null)
    755.             mfilter = gameObject.AddComponent<MeshFilter>();
    756.        
    757.         mfilter.mesh = m;
    758.         m.RecalculateBounds ();
    759.        
    760.         //Hopefully the bounds will not be recalculated automatically
    761.         verts [0] = Vector3.zero;
    762.         verts [1] = Vector3.zero;
    763.         verts [2] = Vector3.zero;
    764.         verts [3] = Vector3.zero;
    765.        
    766.         m.vertices = verts;
    767.        
    768.         reflectionRefractionEnabled = true;
    769.     }
    770.    
    771.     /*
    772.     Called when the object is about to be rendered. We render the refraction/reflection
    773.     passes from here, since we only need to do it once per frame, not once per tile.
    774.     */
    775.     void OnWillRenderObject ()
    776.     {
    777.         if (this.renderReflection || this.renderRefraction)
    778.             RenderReflectionAndRefraction ();
    779.     }
    780.    
    781.     public void RenderReflectionAndRefraction()
    782.     {
    783.         int cullingMask = ~(1 << 4) & renderLayers.value;
    784.         Camera cam = Camera.current;
    785.         if( !cam )
    786.             return;
    787.  
    788.         Camera reflectionCamera, refractionCamera;
    789.         CreateWaterObjects( cam, out reflectionCamera, out refractionCamera );
    790.        
    791.         // find out the reflection plane: position and normal in world space
    792.         Vector3 pos = transform.position;
    793.         Vector3 normal = transform.up;
    794.        
    795.         // Optionally disable pixel lights for reflection/refraction
    796.         int oldPixelLightCount = QualitySettings.pixelLightCount;
    797.        
    798.         UpdateCameraModes( cam, reflectionCamera );
    799.         UpdateCameraModes( cam, refractionCamera );
    800.        
    801.         // Render reflection if needed
    802.         if(this.renderReflection)
    803.         {
    804.             // Reflect camera around reflection plane
    805.             float d = -Vector3.Dot (normal, pos) - m_ClipPlaneOffset;
    806.             Vector4 reflectionPlane = new Vector4 (normal.x, normal.y, normal.z, d);
    807.            
    808.             Matrix4x4 reflection = Matrix4x4.zero;
    809.             CalculateReflectionMatrix (ref reflection, reflectionPlane);
    810.             Vector3 oldpos = cam.transform.position;
    811.             Vector3 newpos = reflection.MultiplyPoint( oldpos );
    812.             reflectionCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflection;
    813.            
    814.             // Setup oblique projection matrix so that near plane is our reflection
    815.             // plane. This way we clip everything below/above it for free.
    816.             Vector4 clipPlane = CameraSpacePlane( reflectionCamera, pos, normal, 1.0f );
    817.             reflectionCamera.projectionMatrix = cam.CalculateObliqueMatrix(clipPlane);
    818.            
    819.             reflectionCamera.cullingMask = cullingMask; // never render water layer
    820.             reflectionCamera.targetTexture = m_ReflectionTexture;
    821.             //reflectionCamera.gameObject.AddComponent<FogLayer>().fog = true;
    822.             GL.SetRevertBackfacing (true);
    823.             reflectionCamera.transform.position = newpos;
    824.             Vector3 euler = cam.transform.eulerAngles;
    825.             reflectionCamera.transform.eulerAngles = new Vector3(-euler.x, euler.y, euler.z);
    826.             reflectionCamera.Render();
    827.             reflectionCamera.transform.position = oldpos;
    828.             GL.SetRevertBackfacing (false);
    829.             material.SetTexture( "_Reflection", m_ReflectionTexture );
    830.         }
    831.        
    832.         // Render refraction
    833.         if(this.renderRefraction)
    834.         {
    835.             refractionCamera.worldToCameraMatrix = cam.worldToCameraMatrix;
    836.            
    837.             // Setup oblique projection matrix so that near plane is our reflection
    838.             // plane. This way we clip everything below/above it for free.
    839.             Vector4 clipPlane = CameraSpacePlane( refractionCamera, pos, normal, -1.0f );
    840.             refractionCamera.projectionMatrix = cam.CalculateObliqueMatrix(clipPlane);
    841.            
    842.             refractionCamera.cullingMask = cullingMask; // never render water layer
    843.             refractionCamera.targetTexture = m_RefractionTexture;
    844.             //reflectionCamera.gameObject.AddComponent<FogLayer>().fog = true;
    845.             refractionCamera.transform.position = cam.transform.position;
    846.             refractionCamera.transform.rotation = cam.transform.rotation;
    847.             refractionCamera.Render();
    848.             material.SetTexture( "_Refraction", m_RefractionTexture );
    849.         }
    850.     }
    851.  
    852.     // Cleanup all the objects we possibly have created
    853.     void OnDisable()
    854.     {
    855.         if( m_ReflectionTexture ) {
    856.             DestroyImmediate( m_ReflectionTexture );
    857.             m_ReflectionTexture = null;
    858.         }
    859.         if( m_RefractionTexture ) {
    860.             DestroyImmediate( m_RefractionTexture );
    861.             m_RefractionTexture = null;
    862.         }
    863.         foreach (KeyValuePair<Camera, Camera> kvp in m_ReflectionCameras)
    864.             DestroyImmediate( (kvp.Value).gameObject );
    865.         m_ReflectionCameras.Clear();
    866.         foreach (KeyValuePair<Camera, Camera> kvp in m_RefractionCameras)
    867.             DestroyImmediate( (kvp.Value).gameObject );
    868.         m_RefractionCameras.Clear();
    869.     }
    870.  
    871.     private void UpdateCameraModes( Camera src, Camera dest )
    872.     {
    873.         if( dest == null )
    874.             return;
    875.         // set water camera to clear the same way as current camera
    876.         dest.clearFlags = src.clearFlags;
    877.         dest.backgroundColor = src.backgroundColor;      
    878.         if( src.clearFlags == CameraClearFlags.Skybox )
    879.         {
    880.             Skybox sky = src.GetComponent(typeof(Skybox)) as Skybox;
    881.             Skybox mysky = dest.GetComponent(typeof(Skybox)) as Skybox;
    882.             if( !sky || !sky.material )
    883.             {
    884.                 mysky.enabled = false;
    885.             }
    886.             else
    887.             {
    888.                 mysky.enabled = true;
    889.                 mysky.material = sky.material;
    890.             }
    891.         }
    892.         // update other values to match current camera.
    893.         // even if we are supplying custom camera&projection matrices,
    894.         // some of values are used elsewhere (e.g. skybox uses far plane)
    895.         dest.farClipPlane = src.farClipPlane;
    896.         dest.nearClipPlane = src.nearClipPlane;
    897.         dest.orthographic = src.orthographic;
    898.         dest.fieldOfView = src.fieldOfView;
    899.         dest.aspect = src.aspect;
    900.         dest.orthographicSize = src.orthographicSize;
    901.     }
    902.    
    903.     // On-demand create any objects we need for water
    904.     private void CreateWaterObjects( Camera currentCamera, out Camera reflectionCamera, out Camera refractionCamera )
    905.     {  
    906.         reflectionCamera = null;
    907.         refractionCamera = null;
    908.        
    909.         if(this.renderReflection)
    910.         {
    911.             // Reflection render texture
    912.             if( !m_ReflectionTexture || m_OldReflectionTextureSize != renderTexWidth )
    913.             {
    914.                 if( m_ReflectionTexture )
    915.                     DestroyImmediate( m_ReflectionTexture );
    916.                 m_ReflectionTexture = new RenderTexture( renderTexWidth, renderTexHeight, 16 );
    917.                 m_ReflectionTexture.name = "__WaterReflection" + GetInstanceID();
    918.                 m_ReflectionTexture.isPowerOfTwo = true;
    919.                 m_ReflectionTexture.hideFlags = HideFlags.DontSave;
    920.                 m_OldReflectionTextureSize = renderTexWidth;
    921.             }
    922.            
    923.             // Camera for reflection
    924.             m_ReflectionCameras.TryGetValue(currentCamera, out reflectionCamera);
    925.             if (!reflectionCamera) // catch both not-in-dictionary and in-dictionary-but-deleted-GO
    926.             {
    927.                 GameObject go = new GameObject( "Water Refl Camera id" + GetInstanceID() + " for " + currentCamera.GetInstanceID(), typeof(Camera), typeof(Skybox) );
    928.                 reflectionCamera = go.GetComponent<Camera>();
    929.                 reflectionCamera.enabled = false;
    930.                 reflectionCamera.transform.position = transform.position;
    931.                 reflectionCamera.transform.rotation = transform.rotation;
    932.                 reflectionCamera.gameObject.AddComponent<FlareLayer>();
    933.                 go.hideFlags = HideFlags.HideAndDontSave;
    934.                 m_ReflectionCameras[currentCamera] = reflectionCamera;
    935.             }
    936.         }
    937.        
    938.         if(this.renderRefraction)
    939.         {
    940.             // Refraction render texture
    941.             if( !m_RefractionTexture || m_OldRefractionTextureSize != renderTexWidth )
    942.             {
    943.                 if( m_RefractionTexture )
    944.                     DestroyImmediate( m_RefractionTexture );
    945.                 m_RefractionTexture = new RenderTexture( renderTexWidth, renderTexHeight, 16 );
    946.                 m_RefractionTexture.name = "__WaterRefraction" + GetInstanceID();
    947.                 m_RefractionTexture.isPowerOfTwo = true;
    948.                 m_RefractionTexture.hideFlags = HideFlags.DontSave;
    949.                 m_OldRefractionTextureSize = renderTexWidth;
    950.             }
    951.            
    952.             // Camera for refraction
    953.             m_RefractionCameras.TryGetValue(currentCamera, out refractionCamera);
    954.             if (!refractionCamera) // catch both not-in-dictionary and in-dictionary-but-deleted-GO
    955.             {
    956.                 GameObject go = new GameObject( "Water Refr Camera id" + GetInstanceID() + " for " + currentCamera.GetInstanceID(), typeof(Camera), typeof(Skybox) );
    957.                 refractionCamera = go.GetComponent<Camera>();
    958.                 refractionCamera.enabled = false;
    959.                 refractionCamera.transform.position = transform.position;
    960.                 refractionCamera.transform.rotation = transform.rotation;
    961.                 refractionCamera.gameObject.AddComponent<FlareLayer>();
    962.                 go.hideFlags = HideFlags.HideAndDontSave;
    963.                 m_RefractionCameras[currentCamera] = refractionCamera;
    964.             }
    965.         }
    966.     }
    967.  
    968.     // Given position/normal of the plane, calculates plane in camera space.
    969.     private Vector4 CameraSpacePlane (Camera cam, Vector3 pos, Vector3 normal, float sideSign)
    970.     {
    971.         Vector3 offsetPos = pos + normal * m_ClipPlaneOffset;
    972.         Matrix4x4 m = cam.worldToCameraMatrix;
    973.         Vector3 cpos = m.MultiplyPoint( offsetPos );
    974.         Vector3 cnormal = m.MultiplyVector( normal ).normalized * sideSign;
    975.         return new Vector4( cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos,cnormal) );
    976.     }
    977.    
    978.     // Calculates reflection matrix around the given plane
    979.     private static void CalculateReflectionMatrix (ref Matrix4x4 reflectionMat, Vector4 plane)
    980.     {
    981.         reflectionMat.m00 = (1F - 2F*plane[0]*plane[0]);
    982.         reflectionMat.m01 = (   - 2F*plane[0]*plane[1]);
    983.         reflectionMat.m02 = (   - 2F*plane[0]*plane[2]);
    984.         reflectionMat.m03 = (   - 2F*plane[3]*plane[0]);
    985.        
    986.         reflectionMat.m10 = (   - 2F*plane[1]*plane[0]);
    987.         reflectionMat.m11 = (1F - 2F*plane[1]*plane[1]);
    988.         reflectionMat.m12 = (   - 2F*plane[1]*plane[2]);
    989.         reflectionMat.m13 = (   - 2F*plane[3]*plane[1]);
    990.        
    991.         reflectionMat.m20 = (   - 2F*plane[2]*plane[0]);
    992.         reflectionMat.m21 = (   - 2F*plane[2]*plane[1]);
    993.         reflectionMat.m22 = (1F - 2F*plane[2]*plane[2]);
    994.         reflectionMat.m23 = (   - 2F*plane[3]*plane[2]);
    995.        
    996.         reflectionMat.m30 = 0F;
    997.         reflectionMat.m31 = 0F;
    998.         reflectionMat.m32 = 0F;
    999.         reflectionMat.m33 = 1F;
    1000.     }
    1001.    
    1002.     void ReflectionQuality (string quality) {
    1003.         OnDisable();
    1004.         if(quality == "Low"){
    1005.             renderTexWidth = 128;
    1006.             renderTexHeight = 128;
    1007.         }else{
    1008.             renderTexWidth = 512;
    1009.             renderTexHeight = 512;
    1010.         }
    1011.     }
    1012.    
    1013.     void EnableReflection(bool isActive) {
    1014.         renderReflection = isActive;
    1015.         renderRefraction = isActive;
    1016.         if(!isActive){
    1017.             material.SetTexture ("_Reflection", null);
    1018.             material.SetTexture ("_Refraction", null);
    1019.             oceanShader.maximumLOD = 1;
    1020.         }else{
    1021.             OnDisable();
    1022.             oceanShader.maximumLOD = 2;
    1023.         }
    1024.     }
    1025.  
    1026.     public void UpdateWaterColor () {
    1027.         material.SetColor ("_WaterColor", waterColor);
    1028.         material.SetColor ("_SurfaceColor", surfaceColor);
    1029.     }
    1030.  
    1031.     void Mist (bool isActive) {
    1032.         mistEnabled = isActive;  
    1033.     }
    1034.  
    1035.     void InteractiveWater (bool isActive) {
    1036.         waterInteractionEffects = isActive;  
    1037.     }
    1038.  
    1039. }
    1040.  
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3.  
    4. public class BoyancyCS : MonoBehaviour
    5. {
    6.  
    7.     private Ocean ocean;
    8. // Water plane at y = 0
    9.     private float mag = 1f;
    10.     public float ypos = 0.0f;
    11.     private List<Vector3> blobs;
    12.     private float ax = 2.0f;
    13.     private float ay = 2.0f;
    14.     private float dampCoeff = .2f;
    15.     private bool engine = false;
    16.     public bool sink = false;
    17.     public float sinkForce = 3;
    18.     private List<float> sinkForces;
    19.    
    20.     void Start ()
    21.     {
    22.         ocean = Ocean.Singleton;
    23.        
    24.         GetComponent<Rigidbody>().centerOfMass = new Vector3 (0.0f, -1f, 0.0f);
    25.    
    26.         Vector3 bounds = GetComponent<BoxCollider> ().size;
    27.         float length = bounds.z;
    28.         float width = bounds.x;
    29.  
    30.         blobs = new List<Vector3> ();
    31.  
    32.         int i = 0;
    33.         float xstep = 1.0f / (ax - 1f);
    34.         float ystep = 1.0f / (ay - 1f);
    35.    
    36.         sinkForces = new List<float>();
    37.        
    38.         float totalSink = 0;
    39.  
    40.         for (int x=0; x<ax; x++) {
    41.             for (int y=0; y<ay; y++) {      
    42.                 blobs.Add (new Vector3 ((-0.5f + x * xstep) * width, 0.0f, (-0.5f + y * ystep) * length) + Vector3.up * ypos);
    43.                
    44.                 float force =  Random.Range(0f,1f);
    45.                
    46.                 force = force * force;
    47.                
    48.                 totalSink += force;
    49.                
    50.                 sinkForces.Add(force);
    51.                 i++;
    52.             }      
    53.         }
    54.        
    55.         // normalize the sink forces
    56.         for (int j=0; j< sinkForces.Count; j++)
    57.         {
    58.             sinkForces[j] = sinkForces[j] / totalSink * sinkForce;
    59.         }
    60.        
    61.     }
    62.  
    63.  
    64.     void FixedUpdate ()
    65.     {
    66.         if (ocean != null)
    67.         {
    68.             int index = 0;
    69.             foreach (Vector3 blob in blobs) {
    70.  
    71.                 Vector3 wpos = transform.TransformPoint (blob);
    72.  
    73.                 float damp = GetComponent<Rigidbody>().GetPointVelocity (wpos).y;
    74.  
    75.                 Vector3 sinkForce = new Vector3(0,0,0);
    76.                 float buyancy = mag * (wpos.y);
    77.  
    78.                 if (ocean.enabled)
    79.                     buyancy = mag * (wpos.y - ocean.GetWaterHeightAtLocation (wpos.x, wpos.z));
    80.            
    81.                 if (sink)
    82.                 {
    83.                     buyancy = Mathf.Max(buyancy, -3) + sinkForces[index++] ;
    84.                 }
    85.  
    86.                 GetComponent<Rigidbody>().AddForceAtPosition (-Vector3.up * (buyancy + dampCoeff * damp), wpos);
    87.                 //rigidbody.velocity = rigidbody.velocity * Time.deltaTime *10f;
    88.             }
    89.         }
    90.     }
    91.    
    92.     public void Sink(bool isActive)
    93.     {
    94.         sink = isActive;  
    95.     }
    96.  
    97.  
    98. }
    99.  
     
  33. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    What the best way for simulate motor propulsion on my boat (boat using BoyancyCS) ?
    Use Rigidbody and AddForce() ?



    Thank :)
     
  34. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    I would start with force and drag. Where you'll have trouble simulating the behaviour will be on how the water affects the boat. Perhaps you'd also need forces acting on other parts of the boat?
     
  35. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    Hi Adam ;)

    I think adding a force that simulates the boat motors and add boyancy script to boat
     
  36. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    First version of my script. Working with buyancy ;)
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class Boat : MonoBehaviour {
    6.  
    7.     [SerializeField] private List<GameObject> m_motors;
    8.     [SerializeField] private float m_horizontalFactor = 1F;
    9.     [SerializeField] private float m_verticalFactor = 1F;
    10.    
    11.     void FixedUpdate () {
    12.    
    13.         float yRotation = Input.GetAxisRaw ("Horizontal") * m_horizontalFactor;
    14.  
    15.         foreach (GameObject motor in m_motors)
    16.         {
    17.             motor.transform.Rotate(0F, 0F, -yRotation * 2f);
    18.         }
    19.  
    20.  
    21.         Vector3 motorForce = Vector3.zero;
    22.         float motorPower = Input.GetAxisRaw ("Vertical") * m_verticalFactor;
    23.  
    24.         motorForce = new Vector3(0,0,motorPower);
    25.  
    26.  
    27.         Rigidbody rigidbody =  GetComponent<Rigidbody>();
    28.         rigidbody.AddRelativeForce (motorForce, ForceMode.Impulse);
    29.         rigidbody.AddRelativeTorque(new Vector3(0F,yRotation,0F));
    30.        
    31.     }
    32. }
    33.  
     
  37. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    Hi everyone !

    I create a github repo with unity version of mobile ocean and boat with physic controller (no completed !).


    If some want to improve boat controller ....
     
    odival, ZenMicro and John-G like this.
  38. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    One of the things that makes a boat move the way you'd expect is the amount of drag produced by the water. Finding out how much of the boat is submerged will help that, even if it's just an estimate. Boats start to "rise" on the water under speed, reducing resistance. Fast boats that can launch off waves will have a moment with only air resistance. This may be easiest to fake completely, but it will help that feel.
     
  39. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    Hi Adam ;)

    I updated the repo

    - Physic working ;)
    - Fix bugs and errors
    - Add sounds
    - New water and effect textures
    - Unity 5 skybox

     
  40. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
  41. dradb

    dradb

    Joined:
    Jan 10, 2015
    Posts:
    86
     
  42. dustinhughson

    dustinhughson

    Joined:
    Nov 25, 2015
    Posts:
    5
    This project is fantastic!

    However I am trying to figure out why the boat is not rendering in the when I use the included scene... Thoughts? I would think it is because my system is semi lower end but when I look at the Stats I am pulling 70-80fps

    thoughts?

    edit - I can drop a barrel in and that is ok
     
  43. elias_t

    elias_t

    Joined:
    Sep 17, 2010
    Posts:
    1,367
    https://github.com/eliasts/Ocean_Community_Next_Gen
     
  44. dustinhughson

    dustinhughson

    Joined:
    Nov 25, 2015
    Posts:
    5
  45. sniperisa

    sniperisa

    Joined:
    Sep 20, 2015
    Posts:
    18
    Really nice water :)

    i tried to use it in a multiplayer game but the waves are different on every client. I tried to fix that by setting the Random.seed to the same value on every client but it doesn't work (i checked the values, they are the same, but the waves still look different).

    What did i miss?
     
    DizzyTornado and Martin_H like this.
  46. FiveFingers

    FiveFingers

    Joined:
    Oct 15, 2009
    Posts:
    541
    Tremendous job there Elias. Congrats.

    I have been playing with this community project for a while and your addition are just great!
    Looking forward to have a look and use that in my current project!

    Thank you!!!
     
  47. knotFF

    knotFF

    Joined:
    Apr 13, 2013
    Posts:
    66
    Is it possible to make this Shader work on Planes, instead of using the camera position to generate the ocean?
    Also, can it output multiple oceans on the same scene?
     
  48. firestorm713q

    firestorm713q

    Joined:
    Jan 6, 2013
    Posts:
    16
    Well, the script (the one I had at least) technically does work on planes, and simply uses the camera to determine the location of them, so as-implemented, no. It can't do either of those things, as it's kind of out of scope for what it's supposed to do.

    To create the effect you want, you can use the same system already presented, using Tessendorf's equations and all that, and use a displacement map and some matrix maths to have it displace along the object's normal, tangent, and bitangent.

    https://github.com/firestorm713/ShaderExperiments/blob/master/Assets/Scripts/Ocean.cs here's my rudimentary version of the ocean script, with lots of comments and whatnot as to how I got it working.

    You could probably adapt that, with some grit and dedication.
     
  49. Foxxis

    Foxxis

    Joined:
    Jun 27, 2006
    Posts:
    1,108
    Late reply, but the built in random functions in Unity are not platform independent. So even if the seed is the same, the result of calling random.value can still differ. Try rolling your own random function (or use a library which is platform independent) and you should get identical results. In theory. ;)
     
  50. knotFF

    knotFF

    Joined:
    Apr 13, 2013
    Posts:
    66
    Thanks for the reply.