Torque Waterblocks

Torque provides a shader driven waterblock system that can be customized for an amazing array of water visual effects.

Multiple waterblocks are supported, and both above water and under water rendering support is provided.

Waterblock Transforms

Unlike many of the other water parameters, the position, rotation, scale, and gridSize can all be changed and updated while in the editor without the need for reloading the mission to see the results. Moving and rotating a WaterBlock is done in the same way as any other object. The scale and gridSize control the size.

Waterblock Grid

The water is square in shape because it is set up as a brute-force grid mesh. It will draw all of the vertices in the grid regardless of what your view distance may be set to.

One of the most important performance parameters for the WaterBlock is gridSize. The gridSize controls how much spacing there is between vertices in the grid - and therefore how many vertices there are in the grid. It should be set as high as possible as suits the needs of the environment. The reason for this is that when the water draws, it will always draw the entire grid. So if you have a 2 kilometer by 2 kilometer size WaterBlock, it will process all of the vertices in the grid, even if you have a viewing distance of a few hundred meters. If your gridSize is set large enough in this case, it's not a big deal. A size of 100 for instance, would process 400 vertices for a 2000x2000 size grid. If your gridSize was 10, however, it would process 40000 vertices which is much slower and wouldn't look a whole lot better.

There are two reasons for having lower gridSize values. The first is fogging. Fog is calculated per-vertex, so if the fog distance less than or near to the gridSize, there will likely be artifacts in the fog because the grid is not fine enough. If the fog distance is very near, and the WaterBlock is large, it might be best to change the shader such that the fog calculations are done per-pixel instead of per-vertex. Then the WaterBlock could be expanded into one large quad.

The second reason for small gridSizes would be smaller WaterBlocks. A WaterBlock can only be as small as one grid element and the size of that element is the gridSize parameter. Ie. if you want a 10x10 size WaterBlock, you must have at most a gridSize of 10.

Wave Data

There are wave settings for the waves that are used in the ps 2.0 water shader. The wave parameters do not affect the 1.0 water movement. The water shader uses the wave parameters to sample the water bumpmap and combine it in different ways to get the final movement effect. It averages the first two waves and adds the third at 1/3 the strength of the first two. The purpose of the third wave is to break up repetitive patterns that the first two can form. It is best, therefore, to use a larger texture scale for the third wave. The parameters for the waves are:

  • waveDir --irection that the wave travels along the x/y plane. It is a 2D normalized vector
  • waveSpeed --speed that the wave travels in the specified direction. This is a single floating point value
  • waveTexScale --scale of the wave - how much the texture is stretched.


WaterBlocks are capable of providing full dynamic reflections for pixel shader 2.0+ hardware. They will reflect everything in the scene. To reflect only certain objects, the "objTypeFlag" variable can be changed in the WaterBlock::updateReflection() function. The reflections are updated at roughly 60htz. This can also be changed in the updateReflections() function.

Full reflections are expensive to render. To kick the reflections down to static cubemap reflections, set the "fullReflect" parameter to false;

The pixel shader 1.1 water reflects only a cubemap. The bump surface itself is generated by blending two normalmaps in a pixel shader to a render target. The render target is then used for a bump-environment map operation to get the "shiny" bump / cubemap interaction.


Fog is calculated on a per-vertex basis in the ps 2.0 rendering path. The gridSize can affect how the fog looks if the fog is fairly close in. The Grid section covers this in more detail. The fog uses the fog texture generated by the scenegraph for consistency with the rest of the scene.

The ps 1.1 path is rendered as a second pass over the bumpEnvMap pass. It uses a stencil operation to avoid z-fighting on the surface over large areas. A special fog mesh is generated for this path. It is a radial mesh (a set of linked concentric rings) that expands as it gets further out to reduce vertices. Rendering of the fog mesh can be turned off by setting the "renderFogMesh" parameter to false.

Surface Materials

There are several "Surface Material" slots that identify which Materials are to be used for varius passes. The MaterialType enum in WaterBlock.h dictates which slots are used for which passes. At the time of this writing, the first slot is used for the "base" material. The underwater material is in the second slot, followed by the fog material (for the 1.1 fog pass). The fourth material is used for blending the normal map used on the 1.1 base surface. The final material is used when dynamic textures are turned off.


You can have multiple WaterBlocks in the same level. NOTE - this can cause serious performance loss if full reflections are turned on.


The actual color of the water


Color of the fullscreen filter when the camera is underwater. Note you can make this more opaque with the alpha color.


How clear the water is. This is a linear slider between the refraction buffer and the baseColor of the water.


Water reflects more of the sky as the angle between it and the camera becomes greater (as it goes out into the distance). This is simulated using an approximation of Fresnel's reflection equation. The "fresnelBias" parameter indicates the minimum reflectance that the water will have. If this is set to zero, the water will not be reflective at all close to the camera.


The rate at which the water becomes more reflective as it stretches towards the horizon is exponential. This parameter sets the exponential power by which the rate changes.