Timothy Cole did a detailed breakdown of his recent experiment with lighting in underwater environments, simulated with Unreal Engine.
Introduction
Hello, My name is Timothy Cole and I am an Unreal Engine Artist. I studied 3D Art for computer games at college, but have always been passionate about film as well so I try to have a hand in both fields. I initially started working at an animation studio in Sydney, making game cinematics and trailers using Unreal. From there I got involved in motion capture for real time, which led to working with Guy Norris (stunt director Mad Max Fury Road) and have just wrapped on Xmen Dark Phoenix. I head the realtime previs side of things in Unreal and have built a virtual camera setup in VR so that the Director and Cinematographer can lens a whole sequence before the set is even built. In addition to this I am Unreal Engine Lead on a number of VR projects with SpectreVR.
Water
I think with anything built in game engines it’s too expensive to have an actual fluid sim or something that is physically accurate, so the challenge becomes how you layer different elements to get as close as your reference. Load up on reference first to really visualize what you’re trying to create, but pick one reference as your ‘hero’. Sometimes if you are matching colour/texture across multiple images it’s easy to get lost and it doesn’t end up looking like any of them! So pick one main one that you try to get close to.
For this project, I have a Pinterest board of ongoing reference, and my hero reference was this photo by Sean Howard (instagram: @sean.howard).
In terms of real-time materials, I try to use opaque materials as opposed to relying on translucency. Translucency is expensive and doesn’t respond to lighting as nicely as an opaque material, but that really comes down to the use of the water. If the player sticks to one side of the water (either in or out) then you can make use of opaque materials, but if they’re able to go in and out you will probably need to work with translucency.
In this scene, the only translucent material is on the surface particles, and even then the blending mode is set to additive.
Layering
It’s all about layering. I break it down into the separate elements: water surface, light source and volume particles.
For the water surface, I have a reflective panning water material on a plane. This is actually opaque as i wanted to focus on just the underwater, and looking at reference the surface can be surprisingly opaque when looking from underneath! Ontop of this i have a ripple particle which distorts the surface and gives it a more organic feel. There are also ripple particles against the edges of the water to fake the lapping interaction around the edge.
The lighting rig I talk about in the next bit.
Lighting
The lighting has evolved into a bit of a complex rig but just started by looking at my reference and breaking it down layer by layer.
It’s basically a gradient from surface to depth, from transparent to the deep blue scatter. Also in terms of caustics think of them as being in focus near the surface to fall off to blurry the deeper it goes.
Also, some of the lights have shadows switched off, and the ones that have shadows on have a shadow resolution scale of 0.2. This helps to create the soft shadows look underwater and also with performance.
I am also making use of the new volumetrics in UE4 on the Exponential height fog. For this project I did not change the fog settings too much, just density at 0.5, set fog inscattering colour to black and switch on volumetric fog.
I started with a light material function for the caustics. It is basically a panning texture at 2 different scales, being UV warped by a large perlin noise. These 2 layers are then blended on top of each other with a Sine. This is then multiplied over the light at 0.8 opacity.
I then apply this to a spotlight. Caustics are sharpest near the surface so I keep the attenuation falloff quite short. This started as a white light, but I really wanted to mimic the spectrum breakup so I cheated and broke this light up into 3 lights, slightly offset from each other. Each one has the same material function, but are coloured red green and blue.
Then a second spotlight over the top that has a larger attenuation, so it goes deeper into the volume. It is also tinted blue as this is the main light faking the scatter from the water. Shadows are off on this layer. This light uses an instance of the same material function, however I change the mip bias of the textures so that they are blurry. You could use a different texture here if you like or actually blur the texture in photoshop or substance, but I find that this little trick is just as effective and way cheaper. This light gets baked to give indirect light too.
The next layer is a deep scatter with the largest attenuation of all the lights. I also up the volumetric contribution of this light to 10.
Finally I added a white light over the top just to neutralise the colours a little bit and exaggerate the light source.
Finally all the layers together:
Movement
I am fairly new to the realm of physics in Unreal and the physics engine has been revamped in the latest version so I am using this project to learn it. The current setup is using invisible colliders to cause the characters to move. I’ve turned off gravity and dampened the response to give it a more floaty feel. I’m also working with mocap data and blending physics over the top. I think this will be the route that I end up using because it means the simulation is more stable. The GPU particles within the volume have velocity fields applied, which helps to give the illusion of a body of water.
Could this be used in real-time environments?
Definitely. Anything I build is built with scalability in mind, and building environments in a layered way like this makes it easier to optimise. For example, you could easily just work with one or 2 layers of the light setup and/or turn off shadows and straight away you’re good for lower spec machines. The RGB split on the main caustics layer could easily just be one white light.