Having trouble to getting the height from an object being displaced by a shader

Hi, so I’m currently making a buoyancy script, but I’m having some trouble get the water height.
The height is controlled through a shader graph which looks like this…

My current code for getting the height is the following…

public float HeightAtPosition(Vector3 position)
    Vector2 uv = (new Vector2(ocean.position.x + position.x,
                              ocean.position.z + position.z) * waveDirection) * waveTiling;
    Vector2 tiling = new Vector2(waveTiling, waveTiling);
    Vector2 offset = Vector2.zero;

    offset.x = (Time.time * waveDirection.x / 20.0f * waveSpeed);
    offset.y = (Time.time * waveDirection.y / 20.0f * waveSpeed);

    uv = TilingAndOffset(uv, tiling, offset);

    float noise = SimpleNoise(uv, waveScale);
    return ocean.position.y + noise * waveStrength;

And the code for the simple noise node is from this unity document.
I’ve tried looking up how different people did it, but most of them use a height map texture, which I’m not doing. Also, I’m not the best at translating shader math over to C#, so if somebody’s a wizard at that and have some good tips and tricks for how to think when approaching a problem like this.

Thanks beforehand :slight_smile:

This is how you can translate ShaderGraphs to C# systematically (this is more or less how ShaderGraph generates HLSL code):

  1. For each node type that you use, make a function with the corresponding input and output parameters. For most nodes, you can look up how they work in the ShaderGraph documentation. Note that you sometimes need multiple overloads (e.g. for float and vector inputs).

  2. Turn each node in the graph into a line like this: NodeName(Input1, Input2, out var Output);. When an output is connected to an input, use the same variable name for them.

  3. Sort these lines so that all outputs are created before they are used.

    using UnityEngine;

    public class WaveDisplacement {
    public float WaveStrength;
    public float WaveSpeed;
    public float WaveScale;
    public Vector2 WaveTiling;
    public Vector2 WaveDirection;

    public float GetHeight(Vector2 Position) {
    	Multiply(Time.time, WaveDirection, out var h);
    	Divide(h, 20, out var g);
    	Multiply(g, WaveSpeed, out var e);
    	Multiply(WaveDirection, Position, out var f);
    	Multiply(f, WaveTiling, out var d);
    	TilingAndOffset(d, WaveTiling, e, out var c);
    	SimpleNoise(c, WaveScale, out var b);
    	Multiply(WaveStrength, b, out var a);
    	return a;
    void TilingAndOffset(Vector2 UV, Vector2 Tiling, Vector2 Offset, out Vector2 Out) {
    	Out = UV * Tiling + Offset;
    void Multiply(float A, float B, out float Out) {
    	Out = A * B;
    void Multiply(Vector2 A, float B, out Vector2 Out) {
    	Out = new Vector2(A.x * B, A.y * B);
    void Multiply(float A, Vector2 B, out Vector2 Out) {
    	Out = new Vector2(A * B.x, A * B.y);
    void Multiply(Vector2 A, Vector2 B, out Vector2 Out) {
    	Out = new Vector2(A.x * B.x, A.y * B.y);
    void Divide(Vector2 A, float B, out Vector2 Out) {
    	Out = new Vector2(A.x / B, A.y / B);
    void SimpleNoise(Vector2 UV, float Scale, out float Out) {
    	// Put SimpleNoise implementation here