bw logo

Chapter 16. Water

Bodies of water can be placed in the world via World Editor, using the provided helper file bigworld/res/helpers/misc/water.xml — for details, see the document Content Creation Manual's lesson Add Water to the World.

As all water objects are VLO's, every instance will create two new files in the chunk folder (named with a unique ID for each instance):

  • .vlo file

    Contains the XML chunk item section for the water object.

  • .odata file

    Contains binary information related to the VLO (in this case, the water's per-vertex transparency/edging data).

16.1. Code overview

The water implementation is contained in the bigworld/src/lib/romp library, more specifically in the following files:

  • chunk_water.cpp, chunk_water.hpp

    Water's link to the BigWorld chunking system.

    See also: bigworld/src/lib/chunk/chunk_vlo.cpp, and bigworld/src/lib/chunk/chunk_vlo.hpp.

  • editor_chunk_water.cpp, editor_chunk_water.hpp

    Editor-related features, like saving, moving, and editing.

    See also: bigworld/src/lib/chunk/editor_chunk_vlo.cpp and bigworld/src/lib/chunk/editor_chunk_vlo.hpp.

  • water.cpp, water.hpp, water.ipp

    The main files. Contains the surface drawing/setup.

  • water_scene_renderer.cpp, water_scene_renderer.hpp

    Implementation of the water scene (reflection/refraction) generation.

  • water_simulation.cpp, water_simulation.hpp

    Implementation of the simulation of water surface.

The water features also uses the shaders below (located in res/shaders/water):

  • water.fx

    Main surface shader for the water.

  • simulation.fx

    Shader for simulation of GPU water interaction.

Each ChunkWater in the world creates its own Water object. A ChunkWater is created by the first reference ChunkVLO encountered. The water is a very large object (VLO), which means that it can span/belong to more than one chunk. This is implemented by placing a VLO reference object (ChunkVLO) into every chunk that the water overlaps. Each reference is treated like the actual large object, passing and retrieving data from/to it.

Each water object adds itself to the draw list at each frame, with Waters::addToDrawList. The engine then draws the list of water surfaces with a call to Waters::drawWaters.

16.2. Scene generation

A reflection scene are rendered based on the current water quality level (for details, see Setting the quality). The reflection scene is a render target that is updated in the main game loop, during the call to TextureRenderer::updateDynamics.

Multiple water surfaces can share a reflection render target (WaterScene class) if they are both in the same position on the y-axis. The water scene generation assumes a flat plane for the water to reflect/clip around the defined y-axis position.

The refraction scene uses the Distortion channel texture which contains a copy of the main render target.

16.3. Render settings

The terrain will always be drawn, but everything else is linked to the current quality setting defined by the following variables:

  • WaterSceneRenderer::s_drawDynamics_

    Determines if dynamic objects are drawn into the water scene.

  • WaterSceneRenderer::s_drawPlayer_

    Determines if the player model is drawn into the water scene.

  • WaterSceneRenderer::s_drawTrees_

    Determines if trees are drawn into the water scene.

  • WaterSceneRenderer::s_maxReflectionDistance_

    Maximum distance that a dynamic object can be away from the water. Default value is 25.

  • WaterSceneRenderer::s_maxReflections_

    Maximum number of dynamic objects to draw. Default value is 10.

  • WaterSceneRenderer::s_useClipPlane_

    Toggles the use of the hardware clipping planes

16.3.1. Setting the quality

The Water::init method is used to initialise the graphics settings options menu link and the FX files, and is only called once. It will make available the following menu items:

  • Water Quality High — Invoked method: Waters::setQualityOption

    All world items are drawn in the water scenes. Highest detail shader is also used.

  • Water Quality Mid — Invoked method: Waters::setQualityOption

    Except for dynamic objects, all world items are drawn in the water scenes.

  • Water Quality Low — Invoked method: Waters::setQualityOption

    Player, trees and sky are drawn in the Reflection. Reflection texture size is reduced.

  • Water Quality Lowest — Invoked method: Waters::setQualityOption

    Dynamic objects, player drawing, terrain and trees are disabled. Only the sky will be drawn into the reflection.

  • Water Simulation Quality High — Invoked method: Waters::setSimulationOption

    Perturbations can propagate between cellsA.

  • Water Simulation Quality Low — Invoked method: Waters::setSimulationOption

    Simulation is restricted to the individual cellsA.

  • Water Simulation Quality Off — Invoked method: Waters::setSimulationOption

    Simulation is disabled

A — Cells are sub-divisions of the water surface (for details, see Simulation).

16.4. Simulation

The water surface is divided up into cells with size defined by the water surface (defaulting to be 100.0 units). Each cell defines an area of water simulation that can be active.

There is a common pool of simulation textures (of size MAX_SIM_TEXTURE_BLOCKS) maintained by the SimulationManager class.

A cell is activated when a movement enters its defined area, and is deactivated after a period of inactivity (defined by SimulationManager::maxIdleTime_, with a default value of 5.0 seconds).

When the high detail simulation options are selected, water movements will propagate to (and activate) neighbouring cells.

The maximum number of active movements is defined by MAX_SIM_MOVEMENTS. Water movements are passed into the simulation manager through the Sway system — for details, see the Client C API's entry Class List ChunkWater, Public Member Fuction sway.

16.5. Rain

Water is automatically affected by rain — there is another simulation texture block reserved in the SimulationManager, and that is used for the rain.

16.6. Water depth

The water depth is determined by the lowest terrain point underneath the water. The bounding box generated from this value could also be used to define a water volume for gameplay purposes. This can be found by searching for the bbDeep_ references in bigworld/src/lib/romp/water.cpp.

This depth information is also used to colour the water's refraction based on the actual per-pixel depth of the water surface. This uses an MRT (multiple render target) depth texture generated in the main scene render. A foaming edge effect is also added using this information.

16.7. Watchers

To configure the behaviour of the water system, the watchers below are used (all watchers are prefixed by Client Settings/Water/):

  • character impact

    Strength at which a movement will hit the water surface simulation.

  • draw

    Defines whether water surfaces are drawn.

  • Draw Dynamics

    Linked to WaterSceneRenderer::s_drawDynamics_.A

  • Draw Player

    Linked to WaterSceneRenderer::s_drawPlayer_.A

  • Draw Trees

    Linked to WaterSceneRenderer::s_drawTrees_.A

  • Max Reflection Distance

    Linked to WaterSceneRenderer::s_maxReflectionDistance_.A

  • Max Reflections

    Linked to WaterSceneRenderer::s_maxReflections_.A

  • Scene/Use Clip Plane

    Linked to WaterSceneRenderer::s_useClipPlane_.A

  • water speed square

    Speed in which a wave will travel in the water simulation.

  • wireframe

    Toggles wireframe mode for water surface.

A — For details, see Render settings.