Realistic Natural Effect Rendering: Water I
Notes about this article seriesThis is the first article in a series dedicated to realistic natural phenomena rendering. Starting with water, each natural effect will be extensively covered by 3 to 5 individual articles. It is not meant to be a tutorial, nor an academic paper, but a comprehensive and in depth guide for the intermediate to experienced graphics programmer. Each effect is covered from the basic aspects to the more advanced details, and various implementation approaches are discussed. The series focuses mainly on the practical aspects of nature effect implementation. Source snippets and pseudo code are provided for many important functions, and the amount of math is kept to the relevant minimum. The series tries to be as platform agnostic as possible, concrete examples are however written according to the OpenGL API. This has a few implications for users of other APIs: all matrices are column major order, texture coordinates are named s, t, r and q, and are assumed in the 0 to 1 range. All matrices are assumed to be 4x4 unless otherwise stated. Many of the effects presented are very shader heavy, mostly targeting current generation 3D chipsets. All shader code is written in the API independent Cg language [1], porting it to a different high level shader language (such as GLSL or HLSL) should be straightforward. IntroductionCG water has been a major research topic for a long time now. Realistically simulating liquids has proven very difficult, due to the inherent complexity of the physical processes involved. Most photorealistic solutions use a form of raytracing and complex differential equations to approximate the optical behaviour and motion dynamics of a water body. Unfortunately, such physically accurate approaches often take many hours of render time per frame. With the advance of programmable 3D hardware, many algorithms previously limited to offline processing have become available for realtime usage. But as always when implementing complex effects in interactive contexts such as video games, quality versus performance tradeoffs must be made. A lot of the visual properties of water can be approximated by efficient techniques that, even though not physically correct, look convincing to the human eye. This water series will discuss many such techniques, focussing on the simulation of finite size constrained water bodies. Both dynamic and optical properties will be covered. The basic water simulation targets ps1.3 / fp20 compliant 3D chipsets, the more advanced effects requires a ps2.0 / arbfp1 capable GPU. Simulating waterAs most physically based effects, water simulation is a combination of two distinct steps. The physical generation step, often called the wave model, simulates the motion of a water body under the influence of many different internal and external forces. The wave model is what makes the water move, change shape, and interact with its environment. Mathematically, many different approaches are possible. The simple ones apply procedural noise, often in the form of Perlin noise [2], simulating a rough and seemingly random movement without much user interaction. The more realistic ones often try to mimic the motion of a real water body by solving differential equations, approximating the physical laws of hydrostatics and hydrodynamics, and offering full interactivity between the player and the water. The second step is the visualization, which takes the water data computed by the wave model, and renders it onto the screen. For high realism, physical laws need to be taken into account again. A water surface exhibits complex interactions with the light from the environment, modelling these optical properties is crucial for a visually compelling result. Unlike the wave model, which can be computed on the CPU, the optical simulation of the water surface often requires complex terms to be evaluated per pixel. Modern ps2.0 level 3D hardware, offering both per-vertex and per-pixel programmability, is perfectly suited for this task. Finding a water representationThe wave model passes the information to the water renderer through a common data interface. Using a simple and abstract representation of the water body offers the advantage of high modularity: different wave models and renderers can access the same data set without requiring conversion and knowledge of each other. This is an important feature when adding both physical and visual level of detail schemes later on. Selecting an appropriate intermediate representation is an important aspect of water generation, and will impact on performance and visual quality of the simulation. The most natural representation of a liquid such as water is conceptually a particle system. While a simulation on molecular level is still impossible for obvious reasons, the approach can be made practical on a coarser level, by increasing the particle size. Each particle carries state information about a small subset of the water body, and is subject to a multitude of external forces acting on it. The particle state, such as velocity and position within the volume, as well as possible collision situations are resolved and updated by the wave model. The rendering is often done via meta particles, usually by an isosurface generation technique such as the well known marching cubes algorithm. Such a particle based approach offers the advantage of a very realistic and flexible framework, which doesn't impose any spatial constraints onto the water body. While realtime implementations are possible on a reduced number of particles, practical usage in games is limited due to the very high performance requirements. An alternative approach would therefore be desirable. The most performance intensive part of the particle model is the tracking of interactions between individual particles, and collisions with the outer environment. This step can be largely simplified by making the particle positions invariant - essentially replacing them by a fixed grid voxel field. Instead of tracking the trajectory of each individual particle through the water body, the voxel approach tracks the physical state of the liquid as it changes over a grid of fixed cells. The main advantage of a voxel representation is computational speed and implementation simplicity. Due to the nature of the fixed grid structure, interactions between adjacent cells can be efficiently computed. The precision of the simulation is given by the grid resolution, offering good hardware scalability and the possibility of speed vs. accuracy tradeoffs. A water body approximated by a 3D voxel grid offers much of the flexibility a more general particle model would provide, at a considerably lower performance impact. However, the voxel technique also suffers from inherent limitations. A particle-based system is open; it can operate within a virtually infinite spatial domain. A voxel based simulation is restricted to the spatial extends covered by the voxel field, and is therefore a closed system. As long as the liquid is kept within the boundaries of this system, might it be by forces such as gravity or by external geometric limits (boundary conditions), the results will be comparable to a particle system constrained by the same external conditions. But as soon as liquid exits the closed system, its state becomes undefined, as it isn't covered by the voxel representation anymore. A possible solution is to expand the field as necessary, either by increasing the distance between cells (losing precision, but keeping computational cost constant), or by adding cells at the appropriate side(s) of the field (keeping precision, but increasing the computational overhead). The best solution is to avoid such expansion altogether, by providing adequate physical constraints to the liquid (for example keeping water in a closed container such as a glass or a pool). Although being more efficient than large particle systems, solving and rendering 3D voxel based water can still become prohibitively expensive with increasing resolution of the grid. Especially in the context of a video game, where high frame rates are required, yet only a small fraction of the available frame time can be dedicated to water simulation, maximal speed is essential. An important observation is that typical 3D games rarely require a full 3D simulation of large water volumes. In fact, volumetric water is often limited to small and highly localized effects, such as for example a running water tap, or a waterfall. These effects can often be approximated by standard particle systems, and won't benefit from a complex physically based solution. In many cases, the water effects with the largest visual impact are not defined by their full volumetric behaviour, but by the appearance of the surface: from water puddles, over smaller pools and submerged areas, to entire lakes or oceans. All those water bodies have in common, that the precise dynamics below their surface are of secondary importance, often even completely invisible to the player. Their visual aspect is almost entirely defined by the dynamic properties of their surface. Ripples, waves, turbulences, along with the optical interactions they create are what make water look realistic. Unfortunately, the 3rd dimension cannot simply be dropped completely in favour of a purely 2D surface model. Volume has to be taken into account while computing the surface dynamics. The best way to combine both worlds is by using a 2.5D representation, commonly known as a heightfield. Each 2D grid cell stores the height of the water from the bottom (which is assumed flat) to the surface at position [x, y]. This extrusion defines a volume of water for each column, V = dx * dy * height, where dx is the size of a grid cell in horizontal direction, dy the size in vertical direction, and height the value stored in the cell at [x, y]. This trick allows the physical wave model to operate on a 3D water volume, while restricting all calculations to a single 2D slice of the volume data set: the surface. A heightfield offers several advantages beyond fast 2D calculations, such as easy rendering and low memory consumption. Converting a heightfield to a geometric mesh is very straightforward as no complex isosurface generation is required. Heightfields have been extensively researched for terrain rendering, most of the LOD and VSD techniques developed for terrains can be directly applied to water heightfields. Of course, water heightfields also inherit a set of limitations from their terrain counterparts: they're essentially extruded 2D maps, and can only simulate a subset of the physical effects a full 3D voxel field can. The slope of the mesh connecting two adjacent cells is limited to angles below 90°, which restricts the model to individually convex waves (i.e. no breaking waves). Also, only water under the influence of gravity can be simulated by a planar heightfield, zero gravity water requires a full 3D grid. In practice however, usability rarely suffers from those drawbacks, and the advantage of high performance outweighs the limitations.
|
|