Physical Water Surface

I just moved a project from the archviz templates to a VR template, which means that lights go from 75k lux to 2 lux, and after making all adjustments and hitting rebuild on the lights, everything looks normal… except for the water that just goes incredibly dark:

Please try to adjust the ColorBright and ColorDark material parameters. By default, these are set to very dark colors. With your reduced lighting, you need to increase the brightness of the water color until it appears normal again.

If your experiments with forward shading, did you enable High Quality Reflections?
Another issue could bee that the Roughness of the water surface is too high so that no reflections show up. You can try to adjust the RoughnessMax and RoughnessMin parameters to make it more smooth. Before you do this, you might want to manually set the Roughness of the Water material to 0 as a test to see if the reflections show up.

1 Like

I had to set the reflection probe to a static HDRI instead of a scene capture and I also gave up trying to use the archviz templates. Too many bugs and glitches.

However, now that I reverted, for some reason my water is poking through even my extra-tall imported distance field replacement mesh that looks fine through the advanced visualizer.

What things could cause the water to not be masked by mesh distance fields?

PS. Replacing the “rocky” normals texture that come with the plug-in with an actual detail water normal texture makes the surface improve a bit…

1 Like

I’ve received the following question:
Is it possible to specify the target of Buoyancy in the Blueprint class to only one static mesh of this Blueprint class?

Here is how to achieve this:

You need to make a copy of the Buoyancy Blueprint and modify it like this: Look for the two CastToPrimitiveComponent nodes in the EventGraph. Add the following nodes and feed the output into both CastToPrimitiveComponent nodes, replacing the original input:

image

In your Blueprint class, add multiple StaticMeshes. For the one StaticMesh that you want to have Buoyancy enabled, add a Tag called EnableB:

image

My test Blueprint has two StaticMesh components, and only the cube has the EnableB tag:
image

The result is that Buoyancy is only active for the cube (it floats on the water), and the sphere stays without any motion:

image

Please note that the Blueprint code that I’ve shown above only works if exactly one StaticMesh component with the EnableB tag is present. If you want the modified Blueprint to also handle the cases that none or more than one StaticMesh components with the EnableB tag are present, then the Buoyancy Blueprint would need to be modified further to loop over all components with the EnableB tag and apply Buoyancy separately to them. Im not sure if it would be worth the effort to do this. The easier solution would be to create a separate Blueprint for each of your StaticMeshes, and to apply the original Buoyancy component to the ones that need Buoyancy.

@ I still have this issue. Do you know why the water isn’t being masked in newly created 4.27 projects (but still works in older ones)?

As you can see, distance fields are being generated, but the water doesn’t get masked out even though the material is set to do so.

The only issue similar to this that I’ve experienced is the following: Imagine that you have a boat that is hollow on the inside, and the hull of the boat is very thin. Inside the boat where the water should be masked out, it could happen that the water still pokes through the thin hull of the boat. I think can because the distance fields have only a limited accuracy, and if the hull of the boat is too thin then the water will not be masked out correctly. Does this sound like your issue?
It would be helpful if you could provide screenshots of your mesh and of the distance fields replacement mesh that you are using. You can also send an email to therealtheokoles@gmail.com with your screenshots.

1 Like

Well, this is embarrasing… I was just migrating a small example project for you when I noticed something…

image

At some point a year or so ago I did some performance testing and apparently switched off the masked material type… but a collapsed category panel in Unreal doesn’t indicate that anything inside of it has changed, so I didn’t remember it until just now when I saw that the water material was an instance!

:man_facepalming:

Entirely my fault and could have been avoidable months ago if I only had time to finish the performance testing (which I didn’t). Sorry for causing confusion!

EDIT: Ok, new issue… perhaps… does 5.1 calculate distance fields differently? It doesn’t look the same as in 4.27… I’m even using a custom water-tight mesh here for distance field calculation and 3.0 in quality setting (which was fine in 4.27)…

EDIT: One additional quirk of UE5 is apparently that you need to hit “refresh material” on the WaterPlane every time you do a “build all” because the water disappears…

EDIT: Oh… and don’t forget to check “scalability settings”… if set to “low”, masking won’t work…

Good that you found your issue :grinning:
I’m not supporting UE5 yet officially. I need to do some testing myself with UE5, I hope that I can do this in the next 1-2 months.

2 Likes

Hello again!

We’ve tried various plugins for ocean surfaces over the years and keep returning to PWS due to it’s simplicity and ease of use (and lack of bloat, so many other plugins offer everything but makes it impossible to customise)

Anyway, one thing we’re still doing is using a third party buoyancy plugin (DWP2). This plugin comes with some support for third party ocean plugins, namely Oceanology.

The implementation for Oceanology looks something like this:

So my thought was, let’s just swap out references and try it with Physical Water Surface.
Here is the setup:

Logically this seems to work. And actually in simulate mode I can see the location/rotation of the buoyant object (in my case, ship) changing, however it seems it’s grinding the entire game to a halt. I’ve captured a short video showing this:

My first thought was, well, the function I’m using (CalculateDeltaOnly) must be too heavy to run on tick, but it seems that’s what’s happening in the buoyancy component that comes included in PhysicalWaterSurface, so how can that be?

Now I’m thinking I have the answer - The DWP2 plugin acts on mesh vertices of a ‘hull’ mesh you provide. My hull mesh is 1300 vertices… I’m guessing there lies the problem.

I’m wondering if there is any other way that I can get the necessary data for this third party buoyancy implementation? Sadly the originally used Oceanology function is implementation in C++ so it is not as easy to edit.

Tried modifying a few things. Reducing the hull sim mesh down to around 150 verts and only looping through the first 8 waves in the CalculateDeltaOnly function gets it working, but it’s still hugely costly.


Will continue searching for a solution

For future reference, here is the section in my documentation that describes how the water height can be queried at any location.
For the shader, this calculation is done on the GPU, and for buoyancy it is calculated on the CPU. As you have noticed, when doing this on CPU you need to be careful, in order to not run into performance problems. Generally speaking, calculating this on every tick for many points (hundreds or thousands) is not a good idea. But I think in most situations, you will not have that many floating object on screen very close to the camera. Far away objects can (and should) be switched over to SinglePoints mode, and objects off screen should have the buoyancy disabled completely for performance reasons.
In general you should try to minimize the number of points at which you need to query the water height (5 or 10 points should be enough for most objects to give realistic looking buoyancy motion). Also, think carefully if you really need to query the water height on each tick. Buoyancy motion is quite slow, and you should be able to get away in most cases with querying the water height a few times per second (and interpolate/extrapolate the rest). These tricks are also used in the buoyancy component of Physical Wate Surface.
You should also be aware that the buoyancy performance that you see in the editor is worse than in the standalone game, because of all the blueprint debugging stuff that is active when playing in editor.
Also, and this is the most important point: The buoyancy blueprint can (and really really should) be nativized automatically to to C++ code (see documentation here). I’ve verified that this works with Physical Water Surface, and it brings a huge improvement in buoyancy performance.
I hope this information is helpful. As you have already recognized, the success of your endeavor will depend on the question if you can limit the number of water height calculation that are queried from Physical Water Surface each tick. Does the third party buoyancy plugin really need to query the water height on each tick? I would start by querying it every second tick, and to extrapolate the value when it is not queried.

Wonderful, thank you for that! I guessed correctly on the height query in that case. Luckily the blueprints are very well laid out, so it was easy to copy from.

As for the performance, I’ve managed to get to a decent place without nativizing to C++ which is preferable at this stage. Essentially I just modelled a new hull sim mesh with around 40 vertices, and only calculate the delta using the first 8 Gerstner waves in the sum up function. This gets pretty good results at this stage, though it’s not very scalable of course, something for me to assess later.

I’m going to drop you an email for another question regarding the wave spectra. Thank you again!