I have made a simple shader graph that takes in a height map and modifies the objects vertices accordingly. I’m planning to use this to generate a sea with waves. This works just fine. See the shader graph in the image below.
I would like to have a boat float on the water and to do that I needed to implement the same functionalities the shader uses but in a C# script to calculate the buoyancy etc. And I have done just that but the problem is that when I sample the height map texture and read the values as they are, the shader handles height map values between 0 and 1 in a non-linear fashion. At least it seems like it.
The spheres in the image are placed on the water surface using my script and the “water” is rendered using the shader. Both use the same height map that has a simple gradient ramp edited in for testing purposes.
Just what does Sample Texture 2D LOD do exactly? I tired using Sample State node with filter set to ‘Point’ but it didn’t help. What causes the difference between the shader and the script implementation?
Here is the script I tried to use. It is by no means pretty or optimised in any way and is only used for testing this approach.
// Ocean plane has this function
public float GetWaterLevel(Vector2 point)
{
// Convert to positive coordinates
Vector2 pointPos = new Vector2(point.x + (oceanSize.x / 2), point.y + (oceanSize.z / 2));
float textureX = Mathf.Lerp(displMapSize.x, 0, Mathf.InverseLerp(0, oceanSize.x, pointPos.x));
float textureY = Mathf.Lerp(displMapSize.y, 0, Mathf.InverseLerp(0, oceanSize.z, pointPos.y));
float displacement = displacementMap.GetPixel((int) textureX, (int) textureY).grayscale;
float normalized = Math.Max(0, Math.Min(1, displacement)); // Clamp displacement between 0 and 1
return normalized * displacementStrength;
}
//Sphere has this script
void Update()
{
Vector3 positionInWater = water.transform.InverseTransformPoint(this.transform.position);
float surfaceHeight = waveManager.GetComponent<WaveManager>().GetWaterLevel(new Vector2(positionInWater.x, positionInWater.z));
this.transform.position = new Vector3(transform.position.x, surfaceHeight, transform.position.z);
}