# How to Script Buoyancy with a Water Shader

How do I get objects to float on my shader’s waves?

I have a water shader I made in Shader Forge and I want to make objects float on the waves. From my understanding I need to calculate my shader’s wave functions in C#, because they are not accessible through script, and sort of mimic what is happening in my shader to calculate the distance from my boat to the wave surface.

If this is correct, the how would I achieve this? Or, if not, what is a good method of doing this? I could really use some help wrapping my head around this. Thanks!

I’m also confused for a long time, good question @coling1
_
If you have buoyancy physics and waves, you need a function that returns height of water of any point:
_

public float GetWaterHeight(Vector3 pos)

_

I know 3 ways to make buoyancy work:

1. Implement wave function in shader and duplicate the function in C# with all parameters (Wave Length, Speed, etc)

2. Implement wave function in C# using mesh manipulation

3. Pass all water mesh vertices to find the closest to selected point and use this vertex’s height (or approximate it)
_
The first way is fast but dangerous in usage (easy to mistake). For example, if you want to use sine wave function, you can generate wave in shader like this ([tutorial how it works][1]):
_

void vert(inout appdata_full vertexData) {
float3 p = vertexData.vertex.xyz;

float k = 2 * UNITY_PI / _Wavelength;
float f = k * (p.x - _Speed * _Time.y);
p.y = _Amplitude * sin(f);

float3 tangent = normalize(float3(1, k * _Amplitude * cos(f), 0));
float3 normal = float3(-tangent.y, tangent.x, 0);

vertexData.vertex.xyz = p;
vertexData.normal = normal;

}
_

Then you can find water height in C# like this:
_

public Transform waterTransform;
public float GetWaterHeight(Vector3 pos)
{
var localPoint = waterTransform.InverseTransformPoint(pos);
var func = _waveNumber * (localPoint.x - speed * Time.time);
var height = amplitude * Mathf.Sin(func);
return height;
}

_

The second way is what @coling1 assumed. [See documentation of mesh manipulation][2] and implement wave function right in C# (_mesh is water mesh):
_

void Update()
{
var vertices = _mesh.vertices;
var normals = _mesh.normals;

for (int i = 0; i < _mesh.vertices.Length; i++)
{
var vertex = _mesh.vertices*;*

var func = waveNumber * (vertex.x - speed * Time.time);
vertex.y = amplitude * Mathf.Sin(func);
var tangent = new Vector3(1, waveNumber * amplitude * Mathf.Cos(func), 0);
tangent.Normalize();
var normal = new Vector3(-tangent.y, tangent.x, 0);
vertices = vertex;
normals = normal;
}

_mesh.vertices = vertices;
_mesh.normals = normals;
}
_
Find water height after that is not too hard (for example, you can create vertices map). My implementation have very bad perfomance. If there is 10000 vertices in water mesh, there is 4 second for 1 Update call.