Wednesday, 18 November 2015

Low-poly water on UE4

Note: For some reason the original videos disappeared from blogger and I've had to create new ones.

Here's how to achieve a cool retro-style water effect using UE4

First of all, we need a suitable plane. While Unreal comes with one we can use straight out of the box, I prefer having one that's just right for my purposes. Here's one I made using Blender.

The UV map (to the left) is rather important to get right, or you'll just get wonky results. Make sure it maps the corners to 0,0 and 1,1.

And because I know you're in a hurry, here's the final shader (you can copy and paste this into an empty material to save you a lot of work):

How it works:

Firstly we take the current time and use it as UV coordinate modifiers to sample a nice, smooth and tiled noise texture. I found "LowResBlurredNoise" (make sure you're allowed to view engine assets in order to select it) perfect.

To avoid most issues with occlusion culling I then "normalize" the values between -0,5 and 0,5. Why is this important? It allows us to increase and decrease the vertices' height relative to their original position rather than just adding to it (and thus always skewing them upwards). You could multiply this by 2 to make the values range from -1 to 1 but you can achieve the same thing by tweaking the wave scale value.

Finally, with a suitable noise map, all we have to do it modify the original vertex position. We take the normal (which would point up in the case of your plane), multiply it by the noise values and as time pans the noise texture forward through all the vertices in our plane, we get a wave.

Why use the normal instead of just just an up vector (like 0,0,1)? It allows us to place water sideways and so some weird stuff with other shapes, like this:

The bits connected to the "normal" part of the material are a bit of "dark math magic" which recalculates the vertex normals after we modify their position. If it wasn't there, the lighting on our water would be constant and look completely hideous. I may go into more detail on this one day.

Usage Notes:

  • You CAN put several of these planes beside each other. They will cleanly fit and should have no seams if you've done the uv mapping properly.
  • As with all vertex-deforming materials, this one will become a bit iffy with occlusion culling, especially with huge "Wave Height Scale" values.
  • Make sure the water plane isn't casting shadows on itself or is otherwise baked by Lightmass
  • Keep in mind that due to oscillating height, it may clip through the ground if you're not careful.
  • Unfortunately, due to the way Unreal handles flat shading, this leaves us with a rather high poly count for a simple flat shaded plane. But this has nothing to do with the Water Material itself.

Addendum: If you're into Unity3D, /u/Ro9AM has posted a neat little tutorial (with source code) that does pretty much the same thing :)