Procedurally Generated Water Shader in UE4 | ebp
Post

Procedurally Generated Water Shader in UE4

A procedural water shader based on GPU Gems

Procedurally Generated Water Shader in UE4

Research Paper

GPU Gems, Chapter 1. Effective Water Simulation from Physical Models, NVIDIA

Procedural Water Shader

Final Result

Final Result The final result of the procedural water shader

Brief Introduction

This project is mainly trying to research and implement water shader based on GPU Gems Chapter 1 , the goal for the project is to create a believable, variant water shader that can provide dynamic visual looks, with large seamless scale water volume yet still have decent performance that can run on a modern GPU at realtime.

Materials and Material Functions Structure

Material Structure Material Structure

Core Material

MODULE BREAKDOWN

Basic Mathematics / Algorithms / Terms

The biggest challenge is to implement the shader in Unreal, by manipulating the water surface vertex in real-time.

According to the book, the key to simulate realistic water waves is to blend multiple sine waves together, then manipulate them to give them a more natural look. (Gerstner Wave function for example)

Base Color

Base Color Base Color

Firstly, base color is simply just a tint of distorted scene color (which creates a refraction effect, see “Refraction” below), then it is interpolated by a depth test, to mimic the feeling of depth.

Mathematically Generated Height: Gerstner

Since the wave function is using Gerstner: Mathematically Generated Height Mathematically Generated Height

This function can be translated to unreal hlsl by:

1
2
3
4
float3 p;
p = WavePos;
p = float3( p.x + CigmaX, p.y + CigmaY, CigmaZ );
return p;

Where float3 WavePos; float CigmaX; float CigmaY and float CigmaZ are all inputs from outside

Procedurally Generated Normal

The normal will be:

Procedurally Generated Normal Procedurally Generated Normal

Which is the cross product of a vertex’s Binormal and Tangent, in Unreal hlsl:

1
return float3(-1. DDX, -1. DDY, 1.);

Procedurally Generated Normal Procedurally Generated Normal

Here, DDX H(X,Y,T) is used to calculate the mix of all four curves:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Wavelength
// Speed
// Direction
// K
float Phi;
float Freq;
//float w;
float Px;
float3 WorldPos;
float2 Dir;

Dir = Direction;
Freq = sqrt(9.8 2 3.1415 / Wavelength);
Phi = Speed * Freq;
WorldPos = GetWorldPosition(Parameters);

float tempFunc1;
tempFunc1 = (sin((dot(Dir, WorldPos.xy)) Freq + Time Phi) + 1.) / 2.;

float tempFunc2;
tempFunc2 = cos((dot(Dir, WorldPos.xy)) * Freq + Time * Phi);

Px = K * Freq * Dir.x * Amp * pow(tempFunc1, (K - 1)) * tempFunc2;
return Px;

Distance-Based Tessellation

Distance-Based Tessellation Distance-Based Tessellation

Distance-Based Tessellation Distance-Based Tessellation

Refraction

Refraction is using a distort of the sample uv of background scene color buffer:

Refraction Refraction

This post is licensed under CC BY 4.0 by the author.