Surface Waves - Dynamic Rivers, Lakes and Oceans

Adding rivers to your game can be tricky when your scene has a lot of variation in height. And static water can feel a bit lifeless when you try to play with it.

That’s why I’ve made Surface Waves, a toolset that creates dynamic rivers, lakes and oceans by making waves interact with underlying terrain. It’s GPU accelerated by making use of Compute Shaders (when supported), or Fragment shaders.

Video demonstration and explanation:

You may have seen an early version of this project last year when I entered the DX11 competition with a Water Simulation. I got a lot of encouragement to turn it into a product. Back then, it was mostly just a tech demo, which wasn’t very suitable for anything other than the scene I created. I spent a lot of time trying to make it easier to use, easier to extend and easier maintain. I also made it work across platforms. Although so far I’ve only been able to test it on Windows and OSX.

The following will be part of it:

  • GPGPU framework for DirectCompute and vertex/fragment shaders

  • Shallow Water Simulation Shaders

  • Water Shaders:

  • Simple Water Shader

  • Reflection

  • Water Color

  • Transparency

  • Complex Water Shader

  • Reflection

  • Refraction (with adjustable filter color)

  • Depth Based Fog (with adjustable color)

  • Soft Shorelines

  • Light Wrapping

  • Foam (uses simulation data)

  • Opaque Liquid Shader

  • Reflection

  • Color

  • Adjustable Emissive Lighting (Self-illumin)

  • Mix between Diffuse and Emissive

  • Example Materials:

  • Water:

  • Fjord

  • Ocean

  • Muddy

  • Simple

  • Non-Water:

  • Blood (For making blood oceans, like you do)

  • Blue and Green Ink

  • Green Goop

  • Mercury

  • Milk

  • Oil

  • Unidentified Orange Stuff

  • Realtime Texture debugger

  • Custom Reorderable List Property Drawer

  • Experimental Buoyancy (DX11 only)

  • Freeflight Camera with Physics

You can buy it on the Unity Asset Store, and in the future I also want to make it available through a service like Patreon. I want to make it available in the Unity Asset Store and through Patreon. But I still have to do some work like creating store image, writing descriptions and creating a license for the Patreon version.

Quick setup guide, and Unity 5 info.

In the meantime you can play with a demo on my website.

Please let me know what you think of it so far.

  • RC-1290
4 Likes

Looks amazing! :smile: I will definitely get this!

1 Like

Looks superb with great performance. How large an area can you cover the water with before performance becomes an issue ? Could you have a large ocean and perhaps have it reduce the quality if you were flying very high above it or perhaps disable an entire section of map if you were very far away from it so you could simulate an entire ocean ? Also how accurate is it’s buoyancy simulations ? While you seem to mainly mention that the benefit of your system is that it is easy to setup I think the real benefit is that it is dynamic. having objects physically interact with it during game play is the real strength.

1 Like

Thanks!

It depends on a few things. There is the cost of the simulation and there’s the cost of rendering.

The cost of the simulation depends on your hardware and the simulation resolution you choose. In that demo, I’m covering a 2km by 2km terrain with a simulation resolution of 768 by 768 and a mesh tessellation of 1024 by 1024. There tends to be a sharp drop in performance when you use a simulation resolution above a certain level. For my HD5770 the limit is 1024 by 1024.For my HP tx2 laptop (even older hardware) it’s 512 by 512.

It seems like it’ll be possible to work around this limitation by tiling the simulation. I’ve done some early tests of that but it’s not really supported yet. Some parts of the simulation still assume there’s a single simulation (including the display materials).

Also, it is possible to change how often simulation steps are performed. For example, if your terrain is static, you don’t need to update the heightmap every frame.

The cost of rendering is relatively easy to change. You can use a simpler shader, or use a mesh with a lower vertex count. In the future I might add a DX11 tessellation shader that dynamically changes the density of the mesh, depending on its distance from the camera.

Buoyancy is still experimental. Right now I’m calculating forces on the GPU and feeding that back to the CPU. But I’m considering changing that, to make it easier to work with, and to stabilize the performance.

I’ve got sketches for a tiled, procedural generation game this would go great with, so I’ll be keeping an eye on your progress on that front. Though it strikes me that you could already use this to build something like From Dust. How easy is it to get the water data back, in case you want to see which parts of the terrain got covered? How does it handle something more viscous, like lava?

The link here on your site doesn’t work, by the way.

I’m doing something similar for Buoyancy right now, but I still need to create a generalized saving system that works without DX11. I have that planned as one of the first major projects after launch. The performance implications are a bit scary in any case, because most(if not all) GPUs need to be idle while copying. Saving data back to system RAM every frame might have quite a performance hit.

This should get a lot better over time as GPUs start working together more closely with the CPU.

Actually, fun story, I met the engineer who wrote the simulation for From Dust (Ronan Bel) the day before he was giving his talk about his simulation at GDC Europe, and I was telling him all about this water simulation I wrote in Flash/PixelBender. I saw him smiling, but it wasn’t until the next day that I realized just how similar our simulations were. Except for the part where his simulation was written in assembly for CPUs supporting SSE, already worked on several different platforms, and had way fancier stuff, like multiple materials, a plant simulation, etc. That was amusing.

In any case, yes, it would be possible to include viscosity settings, but right now it’s using a fixed value (1). Right now you can influence the apparent viscosity with the timestep setting (which is why that setting isn’t suitable for speeding up the simulation).
I don’t have support for interaction between multiple simulations, like Water and Lava yet. It is something I’d like to work on in the long run.

Ahh, right, yeah, thanks for reminding me. I knew I forgot something.

Ooh. Fancy :3

If you haven’t already done it some sort of occlusion culling may help improve performance (for Unity Indie users)?

Yeah, I haven’t done any kind of culling yet, so that might still be an interesting option in the future. Although it’s a bit tricky, because you can’t easily tell when a piece of the simulation isn’t doing anything. When the simulation becomes tiled, it should be possible to freeze any tile, but that will create odd waves when it’s re-enabled, because of the changes in the neighbouring tiles.

Does Unity Indie still exist? I thought it was just Unity (free) and Unity Pro now.
In any case, Surface Waves makes heavy use of RenderTextures, so it’s only for Unity Pro.

Great work

Will this work well without DX11 ?

Thanks!

Go ahead and try it for yourself, if you want. But yeah, that’s the idea. If compute shaders aren’t supported, it uses fragment shaders instead. Which was actually what it used before I entered the DX11 competition.

1 Like

Looks excellent, any ideas where to go from here? (apart from the edge-blending and so on). Also is there any chance of distance based LOD?

There are plenty of little things that I want to improve (including some GUI work), but that’s not particularly exciting to list here.

The big stuff on my personal wishlist (subject to change):

  • Cross-platform saving (opens up opportunities for secondary simulations, like vegetation)

  • Framerate independence

  • Top down water displacement (For things like boats)

  • Underwater graphics (fog mainly)

  • Velocity based Flow Mapping

  • Better buoyancy

  • Tiled Simulation

  • Forces (Wind would be cool)

  • Different input/output types (waterfalls and rain would be nice)

  • Realtime Erosion & Multiple surface types.

  • Sound

But I’m also very curious to hear what kind of things you’d be looking for.

What do you mean with that? The complex water shader already uses alpha blending in shallow areas, if that’s what you mean.

For the water graphics, yes, that might be interesting. I’m thinking of using DX11 tessellation for the mesh density, and I have some other options in mind. But right now high simulation resolutions dwarf the graphics rendering in terms of cost, so tiling the simulation has a higher priority for me.

That is great, cant wait for the release :slight_smile:

A very cool water render, but for my GPU is very heavvy (14FPS if i’m wieving all the world in the demo)

Ahh, so for you it IS dependent on the amount of water on screen? Good to know. Would you mind telling me what GPU you’re using?

crossfire software of two AMD ATI Radeon HD 6450 (two low performance GPUs used to make a strange PC, a server pc with 24GB of ram)

1 Like

That’s indeed a strange setup, I love it ^_^. I’m pretty sure you have enough memory ;). But I can see why it runs so slow. Right now, I’ve optimized the scene for the HD5770 I’m using, and while the HD6450 is newer, it’s not as fast.

I’m curious how the crossfire setup influences the simulation performance, especially when you start using buoyancy (which moves data back from GPU memory to system RAM). I don’t know how Crossfire works, so I’m wondering if it might actually speed up the data transfer.

I can usually get somewhat interactive framerates on my ancient laptop (with HD3200 integrated graphics), if I reduce the simulation resolution, so perhaps I should upload a version with a lower, or adjustable simulation resolution so you can see if that helps in the short term.

Amazing! When it’s released and I got the $ I’ll be very interested in buying (I’m assuming it will be a payed asset).

Would this kind of water be good for a dynamic map/ocean? Sorta like the bf4 maps and their water. So I could change the wave heights etc.

Keep it up :wink:

It looks very good RC-1290, the only problem I saw with it, was the speed of the water when moving around the terrain. (maybe slow it down, or add resistance.) Also it seemed like it just washed down towards the water(or the ‘deeper’ parts of the terrain.) without a trace. If you can somehow make the water get stuck between high points in the terrain(eg. puddles) I would really appreciate it,(and I’m sure many others would too.) other than that it looks great; keep up the great work RC.

Thanks :), I want to make it available through the Untiy asset store first, and later a cheaper, but subscription based version through Patreon (Where you only pay for one version).

If you only need it for waves in the background, a classic ocean simulation would be cheaper to render. Surface Waves is most useful when you need the water to be interactive. The waves are all simulated, so to change wave heights, you change the inputs, or apply forces to it.

In the initial release, there are basic tools for dynamically changing the input amount, and creating waves using a moving mesh, but I would like to be able to add a force like wind in some way.

Thanks :).

Maybe you’re talking about the problem with the simulation being frame rate dependent, so if you have a really high framerate, the waves seem to move way too fast. But you’re not to first to mention it, so there might also be something else going on.

Unfortunately, increasing ground resistance isn’t all that straight forward, because the waves only move vertically, and don’t really have a horizontal velocity (it’s estimated when calculating foam and buoyancy). You can decrease the timestep, which slows it down and changes the viscosity, but I’m not sure if that would fix the problem for you.

I removed the timestep setting from the demo at some point, because people were confused about what it did, but I might add it again so you can see if that fixes your problem.

In the long run, I would like to add different simulation shaders. The current simulation doesn’t conserve momentum correctly, and it might be nice to use a more realistic model.

It does form puddles, in the same way that it forms lakes, the puddles just aren’t very visible, because the water doesn’t affect the specularity of the terrain yet (doesn’t darken it), and the most shallow puddles are hidden because of the depth based soft shores effect.