Real-time Water - Fast Water Simulation for Games Using Height Fields

Related tags

Game RealtimeWater
Overview

Real-time Water

In this project a water-simulation was implemented based on the approach suggested in the presentation "Fast Water Simulation for Games Using Height Fields" by Matthias Müller-Fischer. Some effort was invested to make the result visually pleasing.

I included the [document](https://github.com/hpatjens/Watersimulation/tree/master/documentation/Fast Water Simulation for Games Using Height Fields - Matthias Müller-Fischer.pdf) in this repository as well in case of the document being offline in the future.

This is my first attempt to simulate and render water. This is not a tutorial or even an attempt to do things right. Just keep this in mind when you browse the code.

The water simulation is based on the method that Fischer proposes for 2D heightfields and implemented using the compute shader. Everything is rendered with OpenGL 4.3 at real-time frame rates applying a simple ad-hoc shading - this is not a PBR renderer. Multiple rendering passes are used to determine the depth of the water and calculating fake refractions of the ground. Light is attenuated by the water based on the distance the light has to travel inside the medium. To give the impression of subsurface-scattering and shift in color a look-up texture is used. Caustics are achieved by projecting a texture onto the ground. Nothing real here either. To give the impression of small ripples on the water a normals are read from a normal-map.

alt tag

Installation

Linux

There is a compile.sh script you can execute. The needed packages are listed in the following table.

Package Installation on Ubuntu
GLEW sudo apt-get install libglew-dev
GLFW sudo apt-get install libglfw3-dev

Execute sudo apt-get update before installing the libraries.

Windows

There is a visual studio project in the visual studio folder.

Keys

Key Function
ESC Quit
F1 Wireframe
F2 Show Normals
F3 Free-fly
F4 -
F5 Render all
F6 Render ground
F7 Render watermap
F8 Render water

Simulation

The simulation directly operates on the vertices of the water mesh. This ties the simulation and rendering accuracy directly together which can be a drawback when it comes to dynamically scaling the rendering workload to ensure constant framerates. (Which is not happening in this application.) A huge benefit is the possibility to let the vertex and compute shader operate on the same buffer object. While rendering the buffer is interpreted via the GL_ARRAY_BUFFER target and for the simulation it is provided to the compute shader via the GL_STORAGE_BUFFER target.

These lines implement the above mentioned simulation method:

vec4 position = positionsPrev[index];

// f = c^2*(u[i+1,j]+u[i-1,j]+u[i,j+1]+u[i,j-1] – 4u[i,j])/h^2
float f = c * c * (
	positionsPrev[clampedIndex(gl_GlobalInvocationID.xy + uvec2(-1,  0))].y + 
	positionsPrev[clampedIndex(gl_GlobalInvocationID.xy + uvec2( 1,  0))].y + 
	positionsPrev[clampedIndex(gl_GlobalInvocationID.xy + uvec2( 0, -1))].y + 
	positionsPrev[clampedIndex(gl_GlobalInvocationID.xy + uvec2( 0,  1))].y - 
	4.0 * position.y) / (h * h);	

// v[i,j] = v[i,j] + f*∆t
position.w = position.w + f * DeltaTime;

// unew[i,j] = u[i,j] + v[i]*∆t
position.y = position.y + position.w * DeltaTime;

The vertices of the water surface are altered by the compute shader using a double buffering. This ensures results that are independent of the execution order of the compute shader threads. positionsPrev refers to the vertex positions from the previous frame. position holds the position of the vertex, that is currently computed. The w component of the position stores the velocity of that water column. The last line alters the height of the current vertex, which is the y-coordinate.

To make the simulation interesting the water is pulled up every few seconds by two gaussian bells.

Rendering

There are 3 framebuffers on which the rendering operates.

1. Watermap

The first framebuffer contains the water surface which is rendered from the position of the light source using an orthographic projection. A depth buffer and a color buffer is rendered. The color buffer is made up of 3 channels that store the normals of the water surface. This buffer has a resolution of 1024x1024.

Orthographic projection Normal buffer
alt text alt text

2. Background

The ground (without the water on top) is rendered from the viewers position. This framebuffer stores the color of the pixels and the depth from the viewer. This buffer as well as the third is rendered on full resolution.

Perspective projection Color buffer
alt text alt text

3. Water

The water surface is rendered from the viewers position.

Perspective projection Color buffer
alt text alt text

Default framebuffer

Finally the second and third buffer are combined and rendered onto the default framebuffer.

Attenuation

The light gets attenuated by the water on the way to the ground and on the way to the camera. From the watermap we can get the distance the light travels on the way to the ground by projecting the currently processed fragment onto the watermap and calculating the difference to the stored value (w). The attentuation on the way to the viewer can be obtained by calulating the difference between the water fragment and the depth value that is stored in the background buffer (b).

When the ground is rendered without the water, you can see how the depth of the water affects the lighting. On the right bottom in this image you can see that individual waves are included in the depth-calculation. High waves result in a stronger attenuation and therefore a darker ground. Additionally you can see some distortion in the caustics happen.

This is of course a very approximated model that assumes homogenous density distribution and no scattering at all.

Perspective projection Color buffer (depth buffer is not shown)
alt text alt text

Color Shift

To immitate spectral effects that change the color of the water a lookup table is used to control the change of colors in different depths. The table is implemented as a simple 1D texture.

struct Pixel  { GLubyte r, g, b; };

const int size = 3;
Pixel data[3];
data[0] = Pixel{ 2, 204, 147 };
data[1] = Pixel{ 2, 127, 199 };
data[2] = Pixel{ 1, 9, 100 };

...

glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, size, 0, GL_RGB, GL_UNSIGNED_BYTE, data);

Normals

Because the simulation constantly changes the water surface, the normals have to be recalculated every frame. The geometry shader is used to verify the calculations.

alt tag

You might also like...
A game - or rather, a simulation - of a non-Euclidean world.

neuc A game - or rather, a simulation - of a non-Euclidean world. Currently, I am just developing a 2D top down game (and having a blast in general).

Open-source, cross-platform, C++ game engine for creating 2D/3D games.

GamePlay v3.0.0 GamePlay is an open-source, cross-platform, C++ game framework/engine for creating 2D/3D mobile and desktop games. Website Wiki API De

A C math library targeted at games

Kazmath Kazmath is a simple 3D maths library written in C. It was initially coded for use in my book, Beginning OpenGL Game Programming - Second editi

3D games console based on RP2040 and iCE40 UP5k
3D games console based on RP2040 and iCE40 UP5k

PicoStation 3D This is an unfinished, untested project to develop a 3D games console based on an RP2040 microcontroller and an iCE40 UP5k FPGA. Quick

TIC-80 is a fantasy computer for making, playing and sharing tiny games.
TIC-80 is a fantasy computer for making, playing and sharing tiny games.

TIC-80 is a fantasy computer for making, playing and sharing tiny games.

Enfusion Artifical Intelligence for DayZ and future Bohemia Interactive games.

Enfusion AI Project (eAI) This mod adds headless player units under the control of a script on the server. Although the script is very rudimentary now

Game engine behind Sea Dogs, Pirates of the Caribbean and Age of Pirates games.
Game engine behind Sea Dogs, Pirates of the Caribbean and Age of Pirates games.

Game engine behind Sea Dogs, Pirates of the Caribbean and Age of Pirates games.

Recast is state of the art navigation mesh construction toolset for games. Cute Framework (CF for short) is the cutest framework available for making 2D games in C/C++
Cute Framework (CF for short) is the cutest framework available for making 2D games in C/C++

Cute Framework (CF for short) is the cutest framework available for making 2D games in C/C++. CF comprises of different features, where the various features avoid inter-dependencies. In this way using CF is about picking and choosing which pieces are needed for your game

Comments
  • Missing License?

    Missing License?

    First, the standard disclaimer: I am not a lawyer, and this does not constitute legal or financial advice.

    Generally, IMHO, it is a good idea to use FSF or OSI Approved Licenses (which can be found here https://www.gnu.org/licenses/licenses.html and here http://opensource.org/licenses/category)

    The Free Software Foundation has a useful guide for choosing a license: https://www.gnu.org/licenses/license-recommendations.html

    I often reference the Software Freedom Law Center's Legal Primer for both practical and academic purposes (highly recommended): https://www.softwarefreedom.org/resources/2008/foss-primer.html#x1-60002.2

    https://tldrlegal.com/ is quite a useful resource for comparing the various FOSS licenses out there once you have some context

    To get ahold of actual lawyers/advisors who help FOSS projects, you can reach out to the FSF, SFLC, and OSI at: licensing@fsf.org [email protected] [email protected]

    Hope this helps, and happy hacking!

    opened by liam-middlebrook 1
Owner
Henrik Patjens
Henrik Patjens
Insomniac games cache simulation tool plugin for UE4

Insomniac Games CacheSim plugin for UE4 This plugin for Unreal Engine 4 lets you use the Insomniac Games Cache Simulation tool to detect cache misses

Toni Rebollo Berná 29 Aug 27, 2022
This is a list of different open-source video games and commercial video games open-source remakes.

This is a list of different open-source video games and commercial video games open-source remakes.

Ivan Bobev 173 Jan 2, 2023
After a few loose attempts at porting Source-games; here comes my first real one!

StanleyParable-Vita After a few loose attempts at porting Source-games; here comes my first real one! (For anyone who wonders what happened to the HL2

Sleppo04 4 Sep 21, 2021
Ultralight is an ultra-fast, ultra-light, standards-compliant HTML renderer for applications and games.

Ultralight is an ultra-fast, ultra-light, standards-compliant HTML renderer for applications and games. It supports most modern HTML5, CSS, and JavaScript features while still remaining light in binary size and memory usage.

Ultralight 4.1k Dec 27, 2022
Perimeter is a real-time strategy video game with unique gameplay elements such as terraforming deformable terrain, morphing units, energy network, protective shield and surreal worlds.

Периметр | Perimeter About Perimeter is a real-time strategy video game with unique gameplay elements such as terraforming deformable terrain, morphin

null 414 Dec 27, 2022
CRYENGINE is a powerful real-time game development platform created by Crytek.

CRYENGINE This repository houses the source code for CRYENGINE. Instructions on getting started with git can be found here, along with details on work

Crytek 931 May 10, 2022
A set of libraries and tools to make MSX games using the C programming language.

ubox MSX lib This is a set of libraries and tools to make MSX games using the C programming language. There are three main components: ubox: thin wrap

Juan J. Martínez 42 May 30, 2022
A flutter package for making game levels map like candy crush or similar games using flutter with ability to be horizontal or vertical

Game Levels Scrolling Map A package for making game levels map like candy crush or similar games using flutter with ability to be horizontal or vertic

Mohamed Sayed 12 Oct 26, 2022
VERY simple cross-platform C++ analytics for games (using Google Analytics)

Tiniest Analytics is a very simple to use, cross-platform (tested on win/osx/linux/ios/android) and basically very tiny analytics system written in C++ (less than 100 lines of code), made specifically for games. It uses libcurl to post events to your Google Analytics account.

Mihai Gosa 96 Oct 11, 2022
C++ library for multi-physics simulation

Project Chrono represents a community effort aimed at producing a physics-based modelling and simulation infrastructure based on a platform-independent, open-source design.

null 1.6k Dec 29, 2022