Saturday, October 5, 2019

Week 1 - Getting started with the Water Brief

As my first project for Year 3 I chose to work on the Water VFX Brief. My goal is to create an interactive water shader for a small stylized Environment. I spend my first week mainly on creating the water shader and made relatively good progress, but I still need to add some more features, like depth-based changes and distance field interaction.

1 - Custom Material Functions
As I wanted to create an Ocean Water shader I started of building a Gerstner Wave Material Function, based on the article from GPU Gems (https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch01.html)

Gerstner Wave World Position Offset

I initially struggled a bit with implementing the normals, but after figuring out, that I forgot to add World Position to the x and y Offset, it ended up working.
Gerstner Wave Normals

Since I knew, that I had to layer quite a few of those Gerstner Waves, to create a believable, and not too obviously tiling water surface, I made a quick function to combine 4 Waves.
Combined Gerstner Waves
Lastly, I did not particularely like the look of the water, when just using UE4's specular Reflections and wanted to get a strong sun glitter on the water.
Water with standard UE4 specular reflections

I did some research into computing specular reflection and settled on a simplified Phong model to achieve that, since it was relatively easy to understand and implement and delivered good results for my purposes. At the moment it works by defining a sun position, but I want to change it to approximating a sun position based on the directional light source, then it could also be easily used for a day/night cycle, etc. The output goes into the Emissive input of the Material.

Sunlight Reflection

I was really happy with the outcome, since just adding this simple function added a lot of believability to the water shader. Here are the results for a low and a high sun position:

Low Sun Position
High Sun Position
An additional Benefit of calculating specular reflections was, that I could use the Reflection Vector to add some fake Subsurface Scattering to the water. Of course the SSS is not accurate, since it doesn't account for refraction or similar things, but it adds a bit of variation to the water.

Faked Subsurface Scatter



2 - Water Master Material
Whilst working on all those Material Functions I also started working on the Water Master Material. It is essentially a combination of the Material Functions and some additional other features. Basically everything is parametrized, so anything like water color, wave height, speed, direction, etc can be changed. Here is an overview of what I got so far, I still want to change it quite a bit and add more features, like foam, depth based changes, etc.

Water Master Material


2 - Interactive Ripples
The last thing I worked on this week, was adding interactive ripples to the water. A while ago I found an interesting video by Coding Train about creating interactive ripples and he linked the following website: https://web.archive.org/web/20160418004149/http://freespace.virgin.net/hugo.elias/graphics/x_water.htm . This is where I learned about using multiple render targets to create effects like this. One problem however was, that the resulting ripples had no Normals. After some research I found a tutorial in the Unreal Documentation called "Creating a fluid surface with Blueprints and Render Targets" (https://docs.unrealengine.com/en-US/Engine/Rendering/RenderTargets/BlueprintRenderTargets/HowTo/FluidSurface/index.html) and since their setup was very similar I could use their material for creating the normals. Something they added, which I hadn't considered, was making the effect framerate independent, which I thought was really interesting, so I added that to by blueprint. The big problem with both was, that they receive location input through mouse interaction to apply force at a specific location. So essentially it only works for one actor at a time. After some thinking I decided to use a Scene Capture Component to render the objects, I want the water to interact with, to Custom Depth and then put it through a Spiral Blur Node to get soft edges. This way I also get different ripples depending on the object shape. One problem however was, that those objects then get always drawn to the Render Target and always produce ripples, even if they are not moving. My solution to this was checking for components overlapping the water surface and depending on their velocity enable or disable "Render to Custom Depth". The Ripple creation works in World Space.
This still needs some tweeking, especially figuring out a good offset for the Custom Depth, and there are a few things I want to change, but overall I am really happy with the result.


Write to persistant

Custom Depth Post Process for Scene Capture
Modified Blueprint to create Ripples
Here is, what the Ripples look like in action at the moment:


Next week I will start working on the environment, so I can also implement the shore interaction for the water material and translucency. I  want to tackle creating larger scale water surfaces, as that will be necessary for an ocean and also add some particle effects, like splashes, etc.



No comments:

Post a Comment