Queries#
Usage#
All providers which can be queried use a similar interface.
The providers built into our system perform queries asynchronously; queries are offloaded to the GPU or to spare CPU cores for processing. This has a few non-trivial impacts on how the query API must be used.
Firstly, queries need to be registered with an ID so that the results can be tracked and retrieved later. This ID needs to be globally unique, and therefore should be acquired by calling GetHashCode() on an object/component which will be guaranteed to be unique. A primary reason why sample helpers are useful is that they are objects themselves and therefore can pass their own ID, hiding this complexity from the user.
Secondly, even if only a one-time query is needed, the query function should be called every frame until it indicates that the results were successfully retrieved. Querying a second time using the same ID will stomp over the last query points. See SamplingHelpers.cs for example usage - its Sample() function should be called until it returns true. Posting the query and polling for its result are done through the same function.
Finally due to the above properties, the number of query points posted from a particular owner should be kept consistent across frames. The helper classes always submit a fixed number of points this frame, so satisfy this criteria.
Important
For each unique query ID:
Queries should only be made once per frame.
Number of query points posted should be kept consistent across frames.
Collision Shape#
The system has a few paths for computing information about the water surface such as height, displacement, flow and surface velocity. These paths are covered in the following subsections, and are configured on the Water Renderer using the Collision Source dropdown.
The system supports sampling collision at different resolutions. The query functions have a parameter Min Spatial Length which is used to indicate how much detail is desired. Wavelengths smaller than half of this min spatial length will be excluded from consideration.
To simplify the code required to get the water height or other data from C#, the SampleHeightHelper is provided.
Research
We use a technique called Fixed Point Iteration to calculate the water height. We gave a talk at GDC about this technique which may be useful to learn more: https://www.gdcvault.com/play/1023011/Fixed-Point-Iteration-A-Simple.
The Collision Area Visualizer debug component is useful for visualising the collision shape for comparison against the render surface. It draws debug line crosses in the Scene View around the position of the component.
GPU Queries#
This is the default and recommended choice for when a GPU is present. Query positions are uploaded to a compute shader which then samples the water data and returns the desired results. The result of the query accurately tracks the height of the surface, including all wave components and depth caches and other Crest features.
Collision Layers#
GPU queries support collision layers. Collision layers allow excluding collision sources by querying the displacement data at certain points.
For example, using the After Animated Waves layer includes all waves, but excludes Dynamic Waves. This has often been requires as when using the Sphere Water Interaction to produce wakes, it can cause a feedback loop and jitters.
Collision layers can be enabled with
. When enabling a layer it will allow that layer to be included or excluded. On any object which queries collisions, like Floating Object, set the layer to what you want to include. The layers are in order (except Everything), and selecting a layer will include everything preceding it (eg After Dynamic Waves also includes Animated Waves).Example
To have a Floating Object exclude dynamic waves, make sure Dynamic Waves layer is enabled on Collision Layers, and then set
to After Animated Waves.See the boats in the Boats sample.
There is also the Displacement layer which is a layer at the end. It can be used to render inputs which affect underwater and have nested buoyant objects (eg floating barrel in a ship).
CPU Queries#
On platforms where a GPU is not present, or for authoritative servers, CPU queries are available.
Please see CPU Queries.
Flow#
Flow can also be queried which is done on the GPU only. Query against the Flow Provider or use the SampleFlowHelper.