Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Ceto (Scrawks Ocean)

Discussion in 'Assets and Asset Store' started by scrawk, May 4, 2015.

  1. Don-Gray

    Don-Gray

    Joined:
    Mar 18, 2009
    Posts:
    2,278
    Actually, I mean the surface of the ship.
    If I put a mesh collider on the model it does nothing to keep the player on it,
    if I put a mesh collider on the two parts of the mesh I get an error saying,
    "Non-convex MeshCollider with non-kinematic Rigidbody is no longer supported in Unity 5.
    If you want to use a non-convex mesh either make the Rigidbody kinematic or remove the Rigidbody component. Scene hierarchy path "Tanker/-Tanker-_MeshPart0", Mesh asset path "Assets/_Max Files/Tanker/Tanker.FBX" Mesh name "-Tanker-_MeshPart0"
     
  2. CaptainMurphy

    CaptainMurphy

    Joined:
    Jul 15, 2014
    Posts:
    746
    That part is somewhat self explanatory. Set the mesh collider to be convex (if the mesh really is or the shape goes can go bonkers) or remove the rigidbody part of it and just have it as a collider without mass that uses a script to sync to the rigidbody object.

    First thing to check is your physics layers are set to interact. If the ship mesh is the same that is being pushed around by your buoyancy then a player controller will REALLY cause it to go nuts. It is best to have a buoyancy object that is the rigidbody and has a collision mesh that is syncing its position to a kinematic object that is totally separate. Also, make it so the buoyancy object layer is not interactible physically with the player layer or you get some fun physics.
     
  3. Don-Gray

    Don-Gray

    Joined:
    Mar 18, 2009
    Posts:
    2,278
    I get error above if I put the mesh collider on one or both of the parts, as non-convex.
    Non-convex makes the ship turn over. I hadn't tried making the model non-convex but it doesn't allow the player stay on the object, still goes through. Pretty sure I have no idea how to implement the instructions you mention.
     
  4. shuao23

    shuao23

    Joined:
    Dec 19, 2013
    Posts:
    33
    Is it possible to clip the water out of the mesh? Something like this:
     
  5. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    Kind of. You can clip away parts of the ocean but I'm not sure if you will have enough control for a small object like that boat.

    Add gameobject to the scene and then add cetos AddWaveOverlay script.

    Then add a grey scale texture ( make sure alpha from greyscale is ticked on the texture) to the clip mask slot. Where the texture is white the ocean will be clipped.
     
  6. kideternal

    kideternal

    Joined:
    Nov 20, 2014
    Posts:
    82
    You can create a new mesh that just covers the area inside the boat and then use a material with a shader like this one:

    Shader "Ceto/Mask" {

    SubShader {
    // Render the mask after regular geometry, but before masked geometry and
    // transparent things.

    Tags {"Queue" = "Geometry+10" }

    // Don't draw in the RGBA channels; just the depth buffer

    ColorMask 0
    ZWrite On

    // Do nothing specific in the pass:

    Pass {}
    }
    }
     
    twobob, shuao23 and John-G like this.
  7. Danirey

    Danirey

    Joined:
    Apr 3, 2013
    Posts:
    548
    Hi there!

    Another happy customer of Ceto here.

    I'm just starting to use it, but i have a quick question about collision with the ocean....

    How can i detect a collision to intantiate a Splash particle effect? I see some splash scripts, but i don't know how to use them.

    Thanks, and very good job!
     
  8. Tony-Lovell

    Tony-Lovell

    Joined:
    Jul 14, 2014
    Posts:
    127
    I don't know how to use splash scripts either, but you can query the water height.

    Code (CSharp):
    1.  
    2. private float GetWaterLevel(float x, float z)
    3. {
    4. float height = Ceto.Ocean.Instance.QueryWaves(x, z);
    5. return height;
    6. }
     
    Danirey likes this.
  9. Danirey

    Danirey

    Joined:
    Apr 3, 2013
    Posts:
    548
    Thanks @Tony Lovell , i suppose with the y value of that spot in the ocean, i'll have to check every frame if the object's y value is lower than the wave height, to confirm a collision?
     
  10. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    you could enclose that in a trigger zone to minimise impact on the Update thread when patently never gonna match
     
    Danirey likes this.
  11. CaptainMurphy

    CaptainMurphy

    Joined:
    Jul 15, 2014
    Posts:
    746
    Our cannonballs do a height check on X frames relating to X height distance. Because we know about how high the water was when it was fired we know to increase the check the closer it gets to that water height. So at say 4m above it will do it every 5 frames, and at 2m every over and at 1m every frame. Here is our splash pooling manager that handles then splash and the ceto foam/water height. It is singleton pattern so you call it with a single line once it is in the scene on a gameobject.

    Code (CSharp):
    1. WPG.WaterSplashParticlePool.Instance.PlayParticleEffect(pos,rot,scale)
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using DarkTonic.MasterAudio;
    5.  
    6. namespace WPG
    7. {
    8.     public class WaterSplashParticlePool : MonoBehaviour
    9.     {
    10.         public enum LOD
    11.         {
    12.             LOD0,
    13.             LOD1,
    14.             LOD2
    15.         }
    16.  
    17.         float maxScale = 15f;
    18.  
    19.         public static WaterSplashParticlePool Instance = null;
    20.         [SerializeField]
    21.         GameObject splash;
    22.  
    23.         [Header("Particles")]
    24.         [SerializeField]
    25.         GameObject[] LOD0Particles;
    26.         [SerializeField]
    27.         GameObject[] LOD1Particles;
    28.         [SerializeField]
    29.         GameObject[] LOD2Particles;
    30.  
    31.         [SerializeField]
    32.         int LOD0Count = 10;
    33.         [SerializeField]
    34.         int LOD1Count = 10;
    35.         [SerializeField]
    36.         int LOD2Count = 10;
    37.  
    38.         [Header("Distance to Switch")]
    39.         [SerializeField]
    40.         float LOD0Distance = 100f;
    41.         [SerializeField]
    42.         float LOD1Distance = 250f;
    43.         [SerializeField]
    44.         float LOD2Distance = 1000f;
    45.  
    46.         List<GameObject> LOD0ParticlePool = new List<GameObject>();
    47.         List<GameObject> LOD1ParticlePool = new List<GameObject>();
    48.         List<GameObject> LOD2ParticlePool = new List<GameObject>();
    49.  
    50.         //public Vector2 ParticleSizeRange = new Vector2(1f, 1f);
    51.  
    52.         GameObject pool;
    53.         public float ParticleAge = 3f;
    54.         float timePassed = 0f;
    55.         public float UpdateSpeed = 30f;
    56.         void Awake()
    57.         {
    58.             pool = new GameObject("ParticlePool-WaterSplash");
    59.             pool.transform.parent = this.gameObject.transform;
    60.             Instance = this;
    61.         }
    62.  
    63.         // Use this for initialization
    64.         void Start()
    65.         {
    66.             //build the initial pool
    67.             for (int i = 0; i < LOD0Count; i++)
    68.             {
    69.                 AddParticle(LOD.LOD0, LOD0ParticlePool);
    70.             }
    71.  
    72.             //build the initial pool
    73.             for (int i = 0; i < LOD1Count; i++)
    74.             {
    75.                 AddParticle(LOD.LOD1, LOD1ParticlePool);
    76.             }
    77.  
    78.             //build the initial pool
    79.             for (int i = 0; i < LOD2Count; i++)
    80.             {
    81.                 AddParticle(LOD.LOD2, LOD2ParticlePool);
    82.             }
    83.         }
    84.  
    85.         IEnumerator particleUpdate()
    86.         {
    87.             while (timePassed < ParticleAge)
    88.             {
    89.                 for (int i = 0; i < LOD0ParticlePool.Count; i++)
    90.                 {
    91.                     if (!LOD0ParticlePool[i].activeInHierarchy) { continue; }
    92.                     LOD0ParticlePool[i].transform.position = new Vector3(LOD0ParticlePool[i].transform.position.x,
    93.                                              Ceto.Ocean.Instance.QueryWaves(LOD0ParticlePool[i].transform.position.x, LOD0ParticlePool[i].transform.position.z),
    94.                                              LOD0ParticlePool[i].transform.position.z);
    95.                 }
    96.                 timePassed += Time.deltaTime;
    97.                 yield return new WaitForFixedUpdate();
    98.             }
    99.         }
    100.  
    101.         public void PlayParticleEffect(Vector3 t, Quaternion q, float scale)
    102.         {
    103.             LOD currentLOD = LOD.LOD0;
    104.             float distance = Vector3.Distance(t, Camera.main.transform.position);
    105.             float _scale = scale * Mathf.Clamp(distance / 30f, 3f, maxScale);
    106.             if (distance < LOD2Distance)
    107.             {
    108.                 List<GameObject> ParticlePool = new List<GameObject>();
    109.                 if (distance <= LOD0Distance)
    110.                 {
    111.                     ParticlePool = LOD0ParticlePool;
    112.                     currentLOD = LOD.LOD0;
    113.                     //we also want these particles to track the surface of the water when they move
    114.                     if (timePassed >= ParticleAge)
    115.                     {
    116.                         timePassed = 0f;
    117.                         StartCoroutine(particleUpdate());
    118.                     } else
    119.                     {
    120.                         timePassed = 0f;
    121.                     }      
    122.                 }
    123.                 else if (distance > LOD0Distance && distance <= LOD1Distance)
    124.                 {
    125.                     ParticlePool = LOD1ParticlePool;
    126.                     currentLOD = LOD.LOD1;
    127.                 }
    128.                 else if (distance > LOD1Distance && distance < LOD2Distance)
    129.                 {
    130.                     ParticlePool = LOD2ParticlePool;
    131.                     currentLOD = LOD.LOD2;
    132.                 }
    133.  
    134.                 for (int i = 0; i < ParticlePool.Count; i++)
    135.                 {
    136.                     //check the pool for the next inactive parent object
    137.                     if (!ParticlePool[i].GetComponentInChildren<ParticleSystem>().isPlaying)
    138.                     {
    139.                         ParticlePool[i].transform.position = t;
    140.                         ParticlePool[i].transform.rotation = q;
    141.                         PlayParticle(ParticlePool[i], _scale);
    142.                         //we are done, break out of method
    143.                         return;
    144.                     }
    145.                 }
    146.  
    147.                 //if it made it here then it did not find an open pool object, now make a new one and use it
    148.                 GameObject go = AddParticle(currentLOD, ParticlePool);
    149.                 go.transform.position = t;
    150.                 go.transform.rotation = q;
    151.                 PlayParticle(go, _scale);
    152.             }
    153.         }
    154.  
    155.         GameObject AddParticle(LOD lod, List<GameObject> ParticlePool)
    156.         {
    157.             GameObject g1 = new GameObject("PoolObject" + lod.ToString());
    158.             GameObject[] LODParticles = LOD0Particles;
    159.             if (lod == LOD.LOD1) { LODParticles = LOD1Particles; }
    160.             if (lod == LOD.LOD2) { LODParticles = LOD2Particles; }
    161.             for (int i = 0; i < LODParticles.Length; i++)
    162.             {
    163.                 GameObject go = (GameObject)Instantiate((Object)LODParticles[i]);
    164.                 go.transform.parent = g1.transform;
    165.             }
    166.  
    167.             GameObject g = (GameObject)Instantiate(splash);
    168.             g.transform.localPosition = Vector3.zero;
    169.             g.transform.SetParent(g1.transform);
    170.             g1.transform.parent = pool.transform;
    171.             ParticlePool.Add(g1);
    172.  
    173.             //just in case this is an addon GameObject that was created because the rest of the items were full
    174.             return g1;
    175.         }
    176.  
    177.  
    178.  
    179.         void PlayParticle(GameObject go, float scale)
    180.         {
    181.             ParticleSystem[] ps = go.GetComponentsInChildren<ParticleSystem>();
    182.             for (int i = 0; i < ps.Length; i++)
    183.             {
    184.                 ps[i].startSize = scale;
    185.                 ps[i].Play();
    186.             }
    187.             MasterAudio.PlaySound3DAndForget("cannonballSplash", go.transform);
    188.          }
    189.  
    190.         IEnumerator DisableGameObject(GameObject go, float delayTime)
    191.         {
    192.             yield return new WaitForSeconds(delayTime);
    193.             go.SetActive(false);
    194.         }
    195.     }
    196.  
    197. }
     
    Last edited: Jan 3, 2016
    Danirey, ernov, hopeful and 3 others like this.
  12. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    That is an excellent example. I would only curtail the foreachs for a production system; simply because it is so easy to do so; it may happen so often; and I am anal like that ;) Thanks for the cut and paste ready example. Kudos
     
    Danirey likes this.
  13. CaptainMurphy

    CaptainMurphy

    Joined:
    Jul 15, 2014
    Posts:
    746
    Good catch, I don't think we have really messed with this code in about a year now other than to add in Ceto for the height rather than our old water. So it is a bit dated, lol. I updated the code example to a 'for' instead.
     
    twobob likes this.
  14. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    nice one ;)

    NOTE: I am not entirely sure if this is still current but in the old days it was actually faster to decrement loops than increment them, so when optimising I do this by default on non-order critical tasks. I should find out is this is still the case I suppose :).

    EDIT: It still depends on your target: possibly WebGL and computationally sensitive operations may still benefit from this level of pre-optimisation, in general the difference should be nominal (and in your example the list is only 3 long ;) ) Aged Musing ends.
     
    Last edited: Jan 3, 2016
  15. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    Hi Danirey,

    There are some splash script but they don't do anything. I started on a splash system a while ago but never got to finish it as there was other features and bugs that needed to be done first.

    I left the basic scripts in as I will still use them when I finish it off.

    As people have suggested you will need to set up system were you check if the object hits the ocean surface then spawn a splash particle effect.
     
    Danirey likes this.
  16. CaptainMurphy

    CaptainMurphy

    Joined:
    Jul 15, 2014
    Posts:
    746
    Here is the relevant code from my projectile code that references the splash pool I listed above. This is done in the LateUpdate, though I don't remember why we put it there instead of FixedUpdate.
    Code (CSharp):
    1.  
    2.         if (transform.position.y < Ceto.Ocean.Instance.QueryWaves(transform.position.x, transform.position.z) && !underwater){
    3.             underwater = true;
    4.             WPG.WaterSplashParticlePool.Instance.PlayParticleEffect(transform.position, Quaternion.identity, 3);
    5.             gameObject.GetComponent<Rigidbody>().drag *= 40f;
    6.         } else if (transform.position.y > Ceto.Ocean.Instance.QueryWaves(transform.position.x, transform.position.z) && underwater)
    7.         {
    8.             underwater = false;
    9.             WPG.WaterSplashParticlePool.Instance.PlayParticleEffect(transform.position, Quaternion.identity, 3);
    10.             //splash
    11.             gameObject.GetComponent<Rigidbody>().drag = .1f;
    12.         }
    I don't immediately destroy the cannonball, so it can continue through waves several times before getting slowed enough to get destroyed. The 'underwater' bool is just to make sure that it only does the splash when it is entering or exiting the water.
     
    John-G, Danirey, scrawk and 2 others like this.
  17. Danirey

    Danirey

    Joined:
    Apr 3, 2013
    Posts:
    548
    Thanks guys!

    Great help. @CaptainMurphy , thanks a lot for the scripts. I'll put myself into this right now to test all that....

    Cheers!
     
  18. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    Hi Sepult,

    Thanks :)

    Didnt really understand the question about the FPSController sorry.

    With the collision issue with the water its because the ocean does not use a collidor so there will never be a OnCollisionEnter event triggered.

    The reason the ocean does not use a mesh collidor is because they are expensive to update and must be a finite size where the ocean waves moves every frame (there fore the collidor would have to be updated) and is infinite in size. This makes collidors a poor choice when it comes to the ocean.

    Instead you need to ask Ceto what the wave height is at a location.

    You can do that like so...

    Code (CSharp):
    1.  
    2.  
    3. float x = transform.position.x;
    4. float z = transform.position.z;
    5.  
    6. float height = Ceto.Ocean.Instance.QueryWaves(x, z);
    7.  
    Please see the manual section on wave queries for more info.

    Once you have the wave height from there you can just check if your object is below it and then spawn a splash.
     
    ernov and twobob like this.
  19. Tony-Lovell

    Tony-Lovell

    Joined:
    Jul 14, 2014
    Posts:
    127
    Captain Murphy, what is a suitable GameObject to assign to your script's "splash" variable?

    edit: I guess I see that it has to have a particle system

    tone
     
    Last edited: Jan 3, 2016
  20. Tony-Lovell

    Tony-Lovell

    Joined:
    Jul 14, 2014
    Posts:
    127
    As written, your code would test the waterheight once and once only.

    This is more like what you want, which you would add to the cube GameObject :

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class BowSplash : MonoBehaviour {
    6.        bool submerged = false;
    7.        bool firstUpdate = true;
    8.  
    9.        void Update() {
    10.            float height = Ceto.Ocean.Instance.QueryWaves(transform.position.x, transform.position.z);
    11.            bool sub = height > transform.position.y;
    12.            if (sub && !submerged && !firstUpdate) {
    13.                // add code here to create a splash
    14.            }
    15.            firstUpdate = false;
    16.            submerged = sub;
    17.        }
    18.     }
    19. }
    20.  
     
    scrawk and ernov like this.
  21. CaptainMurphy

    CaptainMurphy

    Joined:
    Jul 15, 2014
    Posts:
    746
    Here is a standard scene setup for us and how I use that script above.

    All you do is place the component on a gameobject, assign the particle system prefabs you want at each LOD and when you run it, it handles the rest. In this example I am using the same LOD particle for all levels, so it isn't a real good example of utilizing the LOD part of it. When the script runs, it makes a set of particle gameobjects as a pool to use and if it runs out of instances it will make more, so it is self managing. The LOD Count fields are the starting number of each particle pool to make. The particle age is used to determine how long it should track the LOD0 splash particle movement and keep it in sync with the waves so that the splash stays on top of the water. Be sure to make your particle system local space for it to work, otherwise world space particles will just render and go underwater if a wave goes past, or end up hovering over the water if a trough is moving by.

    What, exactly, are you trying to accomplish here? I am completely lost as to what you are doing with the cube at all.
     
    scrawk and ernov like this.
  22. Andrzej-Skibinski

    Andrzej-Skibinski

    Joined:
    Apr 16, 2014
    Posts:
    13
    Hey. We just love how your water system looks. We set it up to look exactly how we wanted in just a moment. Great thanks for such nice asset.

    I have however a question about the ship from demoscene. Is it possible to add some collision with static scene elements? So far this ship can pass though objects, even tho they have colliders.
     
  23. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804

    Hi Andrzej,

    The ship and its controller are just for the demo scene. There are pretty basic and theres nothing special about there setup. I dont recommend you use them for a game unless you just want something to play around with.

    The objects in the scene may have a collidor but the ship doesnt. You need to add a mesh collidor to the ships hull mesh ( is the Mesh09 one in the ShipsMesh game object) and make sure convex is ticked.
     
    Andrzej-Skibinski and ernov like this.
  24. CaptainMurphy

    CaptainMurphy

    Joined:
    Jul 15, 2014
    Posts:
    746
    The script I am showing is just to create a splash when you want. So if you want a splash to occur on the bow a particle point goes underwater then you would call that line when you want the splash to occur. These splashes, however, are world space so they would be created at that point in the water and if your ship is moving it would move right past it (or through it) which looks wrong. That script is better used for things like cannonballs, guns, bombs, etc.

    For my bow splashes I use a different technique and I would recommend NOT using a series of single points with the height check on them because it is rather inefficient, even if you are batching the calls. Instead I have a single tracking point that follows a vector attached near the bow about 1m ahead of it and using a technique that @InfiniteDice showed me where you generate an invisible particle aimed at the ship, on the collision event of the invisible particle you will spawn a subparticle that will show the splash(es). Render the subparticle in local space and it will stick to the collision area and follow the water height since it would be a child of the tracking point. This technique gets me down to a single height check that is being done at the origin point and extrapolates the distance to be along the vector for the tracking point to be at.

     
    twobob, ernov and scrawk like this.
  25. Saevax

    Saevax

    Joined:
    Nov 3, 2012
    Posts:
    58
    You may have answered these questions before but I'm not seeing them in this thread.

    You mentioned underwater was causing a lot of issues and editing OCEAN_BOTTOM_DEPTH. I need large depths so is there any pitfalls you can think of to increases the bottom depth to around 10k?

    How can I decrease the strength of the underwater effect so that the camera can see further?

    The default GlobalFog script appears to show sub-sea terrains up to the far clip plane, how can I fix this?

    upload_2016-1-4_16-4-42.png

    How can I offset the grid of CETO to match scene/camera shifts? I shift the entire scene occasionally to keep the camera close to the origin and it is noticeable when the CETO ocean doesn't match up.
     
  26. ernov

    ernov

    Joined:
    Sep 17, 2014
    Posts:
    21
    Thank you very much CaptainMurphy, I now understood ;)
     
  27. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    You can set the OCEAN_BOTTOM_DEPTH to 10k if you want. It should work fine but I have not tested it to the level so not 100% sure. There maybe some precision issues that cause white specs on the horizon when under water.

    To decrease the underwater effect go to the UnderWater script on the ocean (not the post effect one on camera) and adjust the below inscatter and absorbance scale. The inscatter is the fog and the absorbance is how the color changes with distance.

    Set the scale to 0 for both. The underwater effect should now be clear. Then increase the absorbance scale until the color of near objects look how you want. The far objects should go black as the light gets absorbed before it reaches the camera. Then increase the inscatter scale until the fog covers the far objects that are black. You might want to change the inscatter mode as well.

    Not sure whats going on with the global fog there. It doesn't look right but its a bit hard to tell whats going on in that image.
    If you just want the global fog to show on the ocean you need to either use the opaque ocean prefab or you can use the transparent prefab and shift when the global fog gets applied to after the transparent queue (comment out the [ImageEffectOpaque] tag in the global fog script, This can cause other issues and will not work in dx11/deferred )

    Ceto does not match up when shifting the scene as the projected grid does not have a world space. It works in camera space so when you shift the transform it has no effect. There is a offset you can apply to the ocean from a script to make it match your scene offset.

    Code (CSharp):
    1. Ceto.Ocean.Instance.PositionOffset = yourSceneOffset;
    This needs to be the total amount you have offset the scene by during game play. Cant remember if its meant to be negated (-yourSceneOffset) so try that if it does not work.
     
  28. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    2,058
    Awesome. 6 out of 5 from us.
     
  29. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    So one of the things I am working on for next update is a option to select what spectrum type to use. The current one used is the Unified spectrum and I am adding in the Phillips spectrum at the moment.

    The Unified spectrum (actually called the JONSWAP spectrum) is better at representing long rolling wind driven waves but is expensive to calculate. It can also calculate waves from a range of wave lengths so its uses 4 grids each with different waves lengths from the large rolling one to the small ones that give the ocean the extra detail.

    Each grid requires a fourier transform however meaning that for just the displacements Ceto does 3 transforms per update. The slopes require 2 and the Jacobian method used for the foam also requires 3.

    This all means that Ceto does 8 transforms per update. All this is rather expensive which is why the fourier sizes are kept low (recommended is 64 or 128) so a option is being added to only use 4 or 2 grids for the spectrum.

    The Phillips spectrum is a lot cheaper to compute but cant represent larger wind driven waves. Its represents small choppy waves that slosh back and forth. It does not normally use more than one grid but you can if you want.

    I also thought it maybe possible to use a combination of the two. Using the Unified spectrum to represent the larger wind driven waves in the 2 larger grids and using the Phillips for the small detail in the 2 smaller grids.

    So its still a WIP but the new spectrum type options will probably be something like UNIFIED_4_GRID, UNIFIED_2_GRID, PHILLIPS_2_GRID, PHILLIPS_1_GRID, UNIFIED_PHILLIPS_4_GRID with UNIFIED_4_GRID being the current one used.

    While updating the spectrum code there has also been some performance improvements. The CPU fourier and spectrum initialization is now 30% faster and 1ms of post data processing has been moved of the main thread.

    Anyway way while I was adding in the Phillips spectrum code for the slopes today I made a bit a mistake in the code. I thought the results looked kinda cool and would post a screen shot out of interest.

    @lazygunn : maybe something you could use for that faceted look?

    CetoOpps.jpg
     
  30. spraycanmansam

    spraycanmansam

    Joined:
    Nov 22, 2012
    Posts:
    254
    If there could be an option to blend between the unified spectrum for large open areas and the phillips spectrum for the smaller shore waves (maybe even based on the user-generated shore maps?) that would absolutely amazing! If the phillips spectrum was essentially being used as detail for the shores it could even be a very small fourier size, or even completely GPU based as buoyancy would probably not be needed... I'm waffling now. Pretty please? :p

    Also, I've noticed with the latest version 1.0.9 the projected grid gets a little wobbly when moving the camera?
    Thanks again for the hard work.
     
    CaptainMurphy likes this.
  31. Saevax

    Saevax

    Joined:
    Nov 3, 2012
    Posts:
    58
    Basically there is a sub-sea terrain far below the ocean and global fog is being applied to it because it is so far away (after?) the ocean renders.

    I'm in DX11 with forward rendering. The [ImageEffectOpaque] was already commented but when I uncommented it everything seems to work fine. Thanks for your help!
     
    scrawk likes this.
  32. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    I have not noticed that with the grid. I will check it out.

    The double precision projection math was rewritten in the last version to get ride of 2kb of memory allocations. Maybe something got broke. On the ocean script if you untick the 'double precision projection' option it will use the single precision math which has not changed. Can you tell me if that makes the issue go away. If not then the problem must be with something else.

    The idea of using the Phillips spectrum near the shores is a good one and easy to do. :)

    I can just add a extra channel to the height overlay buffer and have the large waves and small waves masked by different channels. I can then just add a option to the overlay to select what channel to mask. This will also work well with the current Unified spectrum. Only issue is it will make the buffer go from RGHalf to ARGBHalf so will be double the memory.
    Dont think that matters too much as that buffer can be half or quarter the screen size and still works good.

    If I add a mixture of the two spectrums they would both have to have the same Fourier size at the moment as they share a common buffer setup that has to all be the same size.
     
    twobob and ernov like this.
  33. Tony-Lovell

    Tony-Lovell

    Joined:
    Jul 14, 2014
    Posts:
    127
    I am tackling the issue of keeping my camera near the scene origin to avoid jitter issues associated with positions far from the origin where floating point precision defies small increments in position -- imagine trying to animate a small hand-held compass at world position (1e6f, 0f, 1e6f).

    The solution involves bumping all root game objects (well, most) back by -camera.transform.position when the camera has strayed too far from the scene's origin. I can figure out how to do this with the root GameObjects and with the active world-based particles but I do not see how to do this with Ceto's textures for foam trails and foam thrusters.

    I imagine I need to reach into WaveOverlayManager or something, but could Ceto be altered such that if the Ocean's position is changed that the WaveOverlays all move accordingly? It should, I suppose, merely be a case of adding their "world position" to that of the Ocean.

    Also -- I am puzzled why Ceto has support for double precision in creating its projected grid, but things such as the ocean's x/z position and the water height query are all based on floats. Is there something I am missing about how I should support a very large world here?
     
    Last edited: Jan 5, 2016
  34. Tony-Lovell

    Tony-Lovell

    Joined:
    Jul 14, 2014
    Posts:
    127
    Another question: a commercial asset developer's first-person controller (Ootii's ActorController) is not working at all well with my sim and he has asked if I can send him a scene that highlights the issues of how the guy falls through the deck of the ship on the sea. The surest way to do so would include Ceto's ocean.

    I could perhaps gut the scene of scripts that actually show the ocean, etc. What would you permit me to do in this regard? I really value your asset and your IP and don't want to compromise your interests.

    tone
     
  35. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    The foam trail and thruster scripts create a overlay in world space so if you translate the scene you need to manually move all those overlays as well as the are not attached to the game objects transform.

    The best way to do this is not in the overlay manager script but in the trail/thrusters base class the AddWaveOverlayBase script. It keeps a list of all the overlays it created so you can just iterate the list and translate them. You can use this function, it will be added in the next update also (im at work so have not checked it to set if it has errors).

    Code (CSharp):
    1.        
    2. //Add me to AddWaveOverlayBase script
    3. public virtual void Translate(Vector3 pos)
    4.         {
    5.             if (m_overlays != null)
    6.             {
    7.                 //unhide all the overlays on enable.
    8.                 var e = m_overlays.GetEnumerator();
    9.                 while (e.MoveNext())
    10.                 {
    11.                     e.Current.Position = e.Current.Position + pos;
    12.                 }
    13.             }
    14.         }
    You will have to grab all the AddFoamTrail/Thruster scripts at start at then call this function when ever you offset the scene.

    The double precision stuff is for the calculation of the projection matrices. They contain a lot of matrix multiplications and inverses so are sensitive to precision issues. This is just a small isolated part of the code though so was a easy option to add.

    Yes you can send Ceto to another asset developer if they need a example scene to fix a issue. That's not a issue.
     
  36. Tony-Lovell

    Tony-Lovell

    Joined:
    Jul 14, 2014
    Posts:
    127
    Many thanks on both counts!

    tone
     
  37. ernov

    ernov

    Joined:
    Sep 17, 2014
    Posts:
    21
  38. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    There is currently no smoothing used by the buoyancy scripts (amount other issues) which makes the boat jitter.

    This should be fixed sometime soon.
     
    ernov and Shodan0101 like this.
  39. cgarossi

    cgarossi

    Joined:
    Jun 23, 2013
    Posts:
    70
    Hi. I love this sytem, but please could you complete the documentation on how to create a shoreline effect? Thanks
     
  40. ernov

    ernov

    Joined:
    Sep 17, 2014
    Posts:
    21
    scrawk
    Thank you for the quick response, so for now no solution, there there another solution for flotation ?
     
  41. John-G

    John-G

    Joined:
    Mar 21, 2013
    Posts:
    1,114
    I'm using this one, https://www.assetstore.unity3d.com/en/#!/content/31646
    Just needs a few alterations to the scripts to get it working with Ceto.
    Also if you look back in the thread I posted a Ceto version of the community buoyancy by Alexzzz.
     
    ernov likes this.
  42. CaptainMurphy

    CaptainMurphy

    Joined:
    Jul 15, 2014
    Posts:
    746
    o_O:confused::rolleyes:
     
  43. rageingnonsense

    rageingnonsense

    Joined:
    Dec 3, 2014
    Posts:
    99
    I just purchased this, and I am having an issue where this is flat out not working at all. I have dragged the Ocean_TransparentQueue prefab to my scene, hit play, and I see no ocean. In the console, I see this:

    Code (csharp):
    1.  
    2. Ceto (1.0.9) Warning: Underwater depth mode must be USE_OCEAN_DEPTH_PASS if using opaque material. Underwater effect will not look correct.
    3.  
    Not sure why it is doing that out of the box. I tried to set the depth mode as the warning suggests, and restart the game. The warning went away, but still, there is nothing. No mesh, no water effect.

    I tried this again in a clean project with nothing but Ceto, and it worked with no problem.

    What could possibly cause this to happen?


    EDIT: When I tried the opaque version it DOES render at least, but it looks awful. It is basically a blue mirror that moves with little choppiness, no foam, no bubbles, anything resembling an ocean.


    EDIT 2: I think this has something to do with my terrain? I am using a custom terrain of my own design. when I disable it, the opaque ocean works fine (transparent still refuses to work at all in the project). This is what it looks like with my terrain not disabled:



    I don't understand what the difference is though; they should not be interacting at all right? Other than for the reflection?

    What gives? Did I download a messed up version? I am using 1.0.9.


    EDIT 3: I just don't know what to make of this. Sometimes, if my terrain generates fast enough, the opaque version works. But if I go to another window, then come back to unity, all of the water effects are missing (like in the above image). Is there a bug tracker for this thing?
     
    Last edited: Jan 7, 2016
  44. rageingnonsense

    rageingnonsense

    Joined:
    Dec 3, 2014
    Posts:
    99
    Ok, so I think I at least know how to reproduce this; I just don't know how to fix it. It appears that if I leave the focus of the unity editor at any point after hitting play, and then come back, the water effects do not render. I think this is best explained with this giphy link:

    http://giphy.com/gifs/l3nWci8a4z3Yd1EfS/html5

    You'll notice everything looks fine (incredible actually, the water is just so nice). However, when I leave focus on the unity editor (shown as my cursor going off screen to bring focus to my gif recording software), and then come bacl, you'll see all the scatter effects just disappear! The editor flickers for a split second when this happens.

    Any suggestions for things I should try? I have a feeling there is something being done in this plugin in Awake() that should not be done in Awake() (as Awake() would be invoked in the scenario I described); grasping at straws here though.
     
  45. CaptainMurphy

    CaptainMurphy

    Joined:
    Jul 15, 2014
    Posts:
    746
    @rageingnonsense That is a known bug. It has been reported on about every page going back to the beta, lol. The actual project when built doesn't exhibit the issue, just when running in editor when it does the hiccup on focus of the IDE. I tend to see it more often when I am showing both scene and game windows at the same time and it happens more when I am doing something computationally intensive or visually intensive. @scrawk has been chasing a fix for it, and it helps to know more about exactly what causes it on each person's machine.
     
    twobob likes this.
  46. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    Hi rageingnonsense,

    Yes there is a current issue where the ocean goes flat in the editor when Unity loses focus. This does not happen for everyone. Its not happening on any of my computesr which is why I have not been able to fix it yet. Its only happens in the editor not the build.

    I just bought a new iMac for testing and I am hoping this issue happens on it. It would be helpful for me to know your OS and GPU version.

    The problem with the transparent prefab was strange. Its it working for you now?

    That warning message about the depth mode is because there is a mode on the underwater script that does not work with the opaque prefab. It should not come up when using the transparent one. It works by checking what render queue the material uses but I have just learnt that if there is a error and the shader does not compile the render queue for the material does not get set and the warning comes up when its not meant to.

    Can you just go into Cetos shader folder and click on the shaders to see if any have errors?

    Im hoping to fix some of the issues with the buoyancy scripts in next update.
     
    ernov likes this.
  47. ernov

    ernov

    Joined:
    Sep 17, 2014
    Posts:
    21
    Thank you for the answer scrawk, hoping for an update soon.
     
  48. _alphaBeta_

    _alphaBeta_

    Joined:
    Aug 8, 2014
    Posts:
    38
    Thanks so much for sharing the technique, but I have a couple quick questions to ensure I fully understand. Probably best if I paraphrase in my own words what I think you're doing. Once per frame you measure the wave height at an "origin point." Can I assume this point is the blue circle gizmo in your GIF? From there you apply the world Y distance from the origin point to the water surface to a vector that matches the bow shape of the ship. Do you do this with trig? This puts your tracking point at water height a certain distance in front of the bow. Can I assume this tracking point is the green circular gizmo? From there, you release a particle so that it drifts back and collides with the ship shortly thereafter, correct? I assume this is in world space with no parent so it drifts back and hits the ship as opposed to moving with the ship. At that point you create a sub-particle as a child of the tracking point so that it moves with the wave height. Do you periodically drop another particle, or does the sub-particle stay around indefinitely? Or does it create its spray for a certain time, long enough for another particle to drift back and hit the ship collider again?

    I haven't gotten into particle systems too deeply yet. When you say particles and sub-particles, are you talking about particle system objects, or one particle from a system? I guess I'm a little lost on the "release a particle" and "create the sub-particle."

    Thanks for any help you can offer. I was planning to just query heights along a similar vector in front of the ship playing a high-low game at a certain resolution. I've been worried about this though with many ships in the scene. Then again, it didn't seem like the height query was very expensive. Along those lines, what would stop you from just calculating the proper location of the tracking point and just having a particle system as a child? I feel like I'm missing something. I imagine if this is equivalent, I'd move the vector the tracking point slides along closer to the ship.
     
    CaptainMurphy, John-G and ernov like this.
  49. CaptainMurphy

    CaptainMurphy

    Joined:
    Jul 15, 2014
    Posts:
    746
    You have the idea on it pretty close to what I am doing. When I am saying 'release a particle' what I am doing is setting the emission rate based on the current ship z velocity so that the faster it goes, the more particles it generates. My particle system is actually about 3 units ahead of the ship and creates the particles in world space along a line that is perpendicular to ship centerline. this gets you more particles along the side during turns (which is correct) and each subparticle emitter is making one of two differing particles when it generates so that it looks different all the time. Those subparticles have a short lifespan and clear themselves constantly. They are all children of the main gameobject that is tracking the bow motion, so once in a while they will move up/down while the bow is in motion too, but it is hard to notice unless you are in rough seas or you are just staring at the particles. The blue gizmo is the gameobject that determines the vector of the angle. For our ships we don't need to make it perfect since the particles are going to float back in world space anyhow and collide with our low poly mesh that is wrapped around the bow.

    Here is an older version. It appears it is just making an array of the points along the line (I did that for complicated bow shapes in a previous iteration, not needed now) and doing a batched wavequery. You will just replace the ShipNetworked object with your own method for getting the forward velocity. In a later version I cut out the process past certain distances and do some basic particle LOD, but is probably pretty close to this. I am at work so I can't check my other repo.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. namespace WPG {
    4.     public class BowSplash : MonoBehaviour {
    5.  
    6.         public float Height = 1f;
    7.         public float fineResolution = 0.1f;
    8.         private int count = 1;
    9.         public float offsetY = 0f;
    10.  
    11.         public ParticleSystem[] SmallParticle;
    12.         public ParticleSystem LargeParticle;
    13.         public float Speed = 1f;
    14.  
    15.         public float VerticalVelocityStart = 1f;
    16.         public float VerticalVelocityExponent = 1f;
    17.  
    18.         public Vector3 lastPosition = Vector3.zero;
    19.         public float VerticalVelocity = 0f;
    20.  
    21.         ShipNetworked ship;
    22.        
    23.         [SerializeField]
    24.         private GameObject splashPoint;
    25.         private Ceto.WaveQuery[] waves;
    26.  
    27.         void Start () {
    28.             ship = gameObject.transform.root.gameObject.GetComponent<ShipNetworked>();
    29.             lastPosition = transform.position;
    30.  
    31.             count = (int)(Height / fineResolution);
    32.  
    33.             waves = new Ceto.WaveQuery[count];
    34.             for (int i = 0; i < count; i++)
    35.             {
    36.                 waves[i] = new Ceto.WaveQuery(Vector3.zero);
    37.             }
    38.         }
    39.  
    40.         void Update()
    41.         {
    42.             splashPoint.transform.position = Vector3.Lerp(splashPoint.transform.position, lastPosition, Time.deltaTime * Speed);
    43.         }
    44.  
    45.         void FixedUpdate () {
    46.             //make sure it is attached to a ship
    47.             if (ship == null) { return; }
    48.  
    49.             //check forward velocity
    50.             if (ship.CurrentSpeed > 0.2f)
    51.             {
    52.                 //get the highest point where water intersects the probe
    53.                 for (int i = 0; i < waves.Length; i++)
    54.                 {
    55.                     waves[i].posX = (transform.position + (transform.up * (fineResolution * (i + 1)))).x;
    56.                     waves[i].posZ = (transform.position + (transform.up * (fineResolution * (i + 1)))).z;
    57.                 }
    58.  
    59.                 Ceto.Ocean.Instance.QueryWaves(waves);
    60.                 for (int j = 0; j < waves.Length; j++)
    61.                 {
    62.                     if (waves[j].result.height > (transform.position + (transform.up * (fineResolution * (j + 1)))).y)
    63.                     {
    64.                         //this one is underwater
    65.                         lastPosition = (transform.up * offsetY) + (transform.position + (transform.up * (fineResolution * (j + 1))));
    66.                     }
    67.                 }
    68.  
    69.                 foreach (ParticleSystem p in SmallParticle)
    70.                 {
    71.                     p.emissionRate = 50f * (Mathf.Clamp(ship.CurrentSpeed / 10f, 0f, 1f));
    72.                     if (p.isStopped) {
    73.                         p.Play();
    74.                     }
    75.                 }              
    76.             }
    77.             else
    78.             {
    79.                 foreach (ParticleSystem p in SmallParticle) {
    80.                     p.Stop();
    81.                 }              
    82.             }
    83.         }
    84.  
    85.         void OnDrawGizmos()
    86.         {
    87.  
    88.             Gizmos.color = Color.blue;
    89.             Gizmos.DrawSphere(transform.position, .1f);
    90.  
    91.  
    92.             Gizmos.DrawLine(transform.position, transform.position + (transform.up * Height));
    93.             Gizmos.color = Color.green;
    94.             Gizmos.DrawSphere(splashPoint.transform.position, .15f);
    95.  
    96.         }
    97.     }
    98. }
    99.  
     
    Shodan0101, twobob and ernov like this.
  50. Tony-Lovell

    Tony-Lovell

    Joined:
    Jul 14, 2014
    Posts:
    127
    Scrawk -- the waveoverlay fix seems to be working, but I think I also need a similar treatment for the wave geometry itself -- it does not follow the Ocean's transform.

    If you can address this, would it be possible to gather all the logic necessary in a static call on Ceto_Ocean, e.g. public static TranslateOcean(Vector2 moveByXZ);

    tone