Community Tutorial: Ocean Simulation

Hey guys. Let’s see if anyone can help me. I followed the tutorial and initially it looked good to me. Running on 5.6 btw. But upon close inspection i have found problems. I use the material in a simple landscape but i’ve tried it in other geometry and the same happens.

The problem is that there’s this black tint all over the water that keeps moving and makes the sea very unrealistic. I think it’s a problem with my RT_Roughness as it appears completely black in the content browser.

Any idea on what can it be and how to solve it? Thanks!

@Deathrey


While roughness seems indeed wrong, your problem is caused by mismatch between lumen scene /distance field version of geometry and / or virtual shadow maps. and rasterized geometry with WPO.

1 Like

Hello, I folowed this tutorial and it’s absolutely great sim. I’m using 5.6, I got 2 problems after finished the tutorial, can you help me fix it.

First one is I have to open the NS_Ocean tab in another window in order to make the sim run, if I switch to another tab on that window, the sim stop, it just freeze, same when I close the tab.
Please see the video here. https://youtu.be/M3PFV64__-k

Second one is that my sim reset every 10 seconds making it looks very jitter, how can I make that period longer. The “Repeat period” doesn’t seem to affect that.

Thank you!

Thanks for the reply. And sorry for being the guy bumping up this post again every few days. You must have your notifications full of this..

I thought about shadows initially but no matter what setting i change in the lights, it can still be seen. Even with cast shadows off, so it needs to be something else. Any other idea?

Regarding the RT_roughness, the problem is solved now.

I know they’re just warnings but I’m getting these in my build and would like to clean them up if I can–

LogNiagaraShaderCompiler: Warning: GPU shader compile failed! Id: 3 Name: FX_OceanWater/WaterSim/ParticleGPUComputeScript/FNiagaraShader/4

LogNiagaraShaderCompiler: Warning: GPU shader compile failed! Id: 3 Name: FX_OceanWater/WaterSim/ParticleGPUComputeScript/FNiagaraShader/3

LogNiagaraShaderCompiler: Display: There were issues for job “FX_OceanWater/WaterSim/ParticleGPUComputeScript/FNiagaraShader/4”

LogNiagaraShaderCompiler: Warning: /Plugin/FX/Niagara/Private/NiagaraEmitterInstanceShader.intermediate.usf(57,28-35): warning X3556: integer divides may be much slower, try using uints if possible.

LogNiagaraShaderCompiler: Warning: /Plugin/FX/Niagara/Private/NiagaraEmitterInstanceShader.intermediate.usf(54,17-49): error X4026: thread sync operation must be in non-varying flow control, due to a potential race condition this sync is illegal, consider adding a sync after reading any values controlling shader execution at this point

LogNiagaraShaderCompiler: Warning: /Plugin/FX/Niagara/Private/NiagaraEmitterInstanceShader.intermediate.usf(97,5-61): error X4026: this variable dependent on potentially varying data: stage_input

LogNiagaraShaderCompiler: Warning: /Plugin/FX/Niagara/Private/NiagaraEmitterInstanceShader.intermediate.usf(25,130-179): error X4026: this variable dependent on potentially varying data: gl_GlobalInvocationID

LogNiagaraShaderCompiler: Warning: /Plugin/FX/Niagara/Private/NiagaraEmitterInstanceShader.intermediate.usf(39,9-20): error X4026: this variable dependent on potentially varying data: _82

LogNiagaraShaderCompiler: Warning: /Plugin/FX/Niagara/Private/NiagaraEmitterInstanceShader.intermediate.usf(41,29-43): error X4026: this variable dependent on potentially varying data: _98

LogNiagaraShaderCompiler: Warning: /Plugin/FX/Niagara/Private/NiagaraEmitterInstanceShader.intermediate.usf(52,32-39): error X4026: this variable dependent on potentially varying data: _143

LogNiagaraShaderCompiler: Display: There were issues for job “FX_OceanWater/WaterSim/ParticleGPUComputeScript/FNiagaraShader/3”

LogNiagaraShaderCompiler: Warning: /Plugin/FX/Niagara/Private/NiagaraEmitterInstanceShader.intermediate.usf(55,28-35): warning X3556: integer divides may be much slower, try using uints if possible.

LogNiagaraShaderCompiler: Warning: /Plugin/FX/Niagara/Private/NiagaraEmitterInstanceShader.intermediate.usf(52,17-49): error X4026: thread sync operation must be in non-varying flow control, due to a potential race condition this sync is illegal, consider adding a sync after reading any values controlling shader execution at this point

Sure, go ahead. I appreciate the credit.

Thank you!

just change z location

Thank you for providing this amazing resource for free. One of the best looking water systems out there without paying a ton of money. Any tips for optimization? I get about 75FPS with this system hidden but it drops to about 55FPS when active. I figure that’s just the deal for such a robust system but I wasn’t sure if there were any small tweaks that could lower quality to gain a few frames. In any case, thank you.

Buoyancy performance post.

Don’t mind the look of the ocean, it’s a sphere, and I’m temporarily using ddx/ddy normals since so far I only made the displacement work on a sphere.

After countless nights messing with the buoyancy (posted here by @mjegen) I couldn’t find a way to scale down the grid size (to 64 or 32) while keeping the GPU grid at 256 and match the result. The displacement itself is just wrong. GPT Agent after exploring all the code told me it’s not possible by design, not sure if he’s right.

So I kept the grid size 256 both on GPU and CPU. And it was taking around 40 ms to calculate everything on CPU. I made some optimizations and now it runs almost free, or at least it feels this way. What I’ve done:

  • Replaced the old ParallelFor batching with an async pipeline:
    TimeStep → Row Pass → Col Pass, each stage running in its own background task, but of course one after another.
  • Let ISPC handle the parallelism inside each stage, using task + launch for tiled processing (better SIMD utilization). I had to add tasksys.cpp (from official ISPC examples) to the module in order to utilize the task system.
  • Moved all heavy work off the game thread, so there’s no frame stall while waiting for FFT to finish.
  • Switched to calling Calculate function only once per 0.05-0.1 seconds. This way it recalculates displacement some time after previous calculations were finished, and also I don’t think I need to update it every frame.
  • So, next I will have to average the resulting displacement in between each update, so that we get approximated, but smooth displacement change from frame to frame.

Now I have everything running across multiple frames and all the heavy job feels kind of free. Please note that the measurements you see on the screenshot is not how much time it actually takes to calculate everything across multiple frames. It’s just how long it takes to start the work, and while the job is running it keeps rendering next frames.

1 Like

You are making it more complex than it needs to.

Calculating iFFT at reduced resolution is as straight forward as taking middle part from the spectrum texture and rescaling final result. Only two steps, nothing else. No searching or GPTing is needed.

Secondly, Calculating iFFT of reduced size on CPU is not the only way.
In fact, it is much simpler and at times more practicable to just sum waves analytically at query location. Look at your picture, it has not more than a dozen of signals at amplitudes, that really contribute to the height meaningfully. Nothing stops you from summing up those signals analytically at query location. Up to some number of queries, it will be faster. And it has advantage of querying displacement at arbitrary time,.

1 Like

Well, I’ve read all your notes, and not once, you posted above about how to properly setup everything on the CPU side and I actually tried every suggestion but just couldn’t figure out why it wouldn’t work. The complexity of all this ping-pong-butterfly equations kind of things is just beyond my understanding. And in order to make something work, I have to have a clear picture of what’s going on.

So here we are, trying to fix something that we don’t know how it works.

Honestly, a very basic C++ example would really help. But I understand, it takes time and you don’t have to do it.

Meanwhile I will keep trying, maybe eventually I’ll find the right approach.

Ok…this worked and i feel suuper stupid. I still don’t understand what the plane was clipping with… there’s nothing else in the scene!

It’s an error in the material

Somewhere in this playlist I’ve seen him fixing it (although the fix was a little messy imho): https://youtube.com/playlist?list=PLg8qOa5gnZ3Bj8shSI7jZ6XvwOQ1Z7xAW&si=arA7yQGhS_YY71Ez

Couple screenshots of my progress on my Planetary Oceans plugin update.



What already works on a full sphere:

  • Waves (WPO), normals, foam, bubbles, scattering
  • Buoyancy — everywhere on the planet;

Still have a list to finish.

But the visual improvement is insane (previously I was using Gerstner waves). Would like to thank you guys who created this masterpiece and who worked on getting wave data.

1 Like

Looking very good!

1 Like

I was wondering if there’s a way to edit parameters without stopping/interrupting the simulation? Aka at runtime.

PS: I’ve just discovered that changing parameters via Blueprint/C++ does work without resetting or stopping the Niagara system and everything changes smoothly.

1 Like

Have you find any solution to this ?

It seems it happens if the Niagara System was not added to the level.