About water: brushes



Map editing tools, such as:

On the 30th of September, 2020 the Ozonex editors renders water differently than in the game. Thus it is not representative to what you would see while playing. On the contrary, the GPG editor utilizes the exact same procedures as the game does and is therefore representative. If the Ozonex editor correctly represents the water when you read this then do notify me and I'll remove this paragraph 🙂 .


There are numerous water brushes available in Supreme Commander. The depth bias is not functional.

Highlighting the actions described earlier in the GPG editor

In the tool window you'll notice there is a combo box with three options, a pair of brushes and their according strength / size at the bottom.


Flatness depicts how rough the sea and therefore the reflections of the water are. You can use the red brush to make it less rough and the blue brush to make it more rough. By default all of the water is at its roughest.

A visual comparison with rough water in the top left and partially flattened water in the bottom right

Typically waves are generated by the wind. One can visualize that a lake is partially covered from the wind by some mountain by flattening it slightly. Generally completely flattened water looks strange - users are not used to water being completely flat because its rough on almost every map out there.

This is only a graphical effect - it does not affect the simulation.


Foam depicts how much wave crests / foam should be generated. You can use the blue brush to decrease the amount of foam and the red brush to increase the amount of foam. By default, all of the water generates foam.

Water of the map Paradise, with foam in the top left and without foam in the bottom right

Whether or not foam is generated depends on your water maps. The alpha channel of the water map determines whether foam should be generated. For more information about this see the article on water normal maps:

This is only a graphical effect - it does not affect the simulation.

Depth bias

This is not functional. Technically, it is not being used in the shaders that render every single frame. One can only imagine what it was supposed to be used for. You can change the depth manually by changing the heightmap of the terrain directly.

Under the hood

With Supreme Commander we're in a unique position in which we can not only toy around with graphical assets, we can also see how these assets are used in the rendering pipeline of the game. The (HLSL) shaders can be found at:


To strengthen our understanding of the article it is nice to see how the assets are used in the rendering pipeline. For this article, the following bits of code inside the water2.fx file are particularly interesting.

// file: water2.fx

float4 HighFidelityPS(...) : COLOR
    // (...)

    float3 up = float3(0,1,0);
    N = lerp(up, N, waterTexture.r);

    // (...)

The value inside waterTexture.r is the value we're painting with the flatness brush described earlier.

We need the red brush (the one that deducts) to decrease the roughness of the water: by default the value is 1 and through linear interpolation we therefore completely use the computed normal N at that pixel. Because every pixel will have a slightly different normal N, the water will appear rough.

When we decrease this value we'll slowly graduate towards the up vector that is uniform over the surface. Surrounding water will move towards the same up vector and therefore there is little to no difference between the normals of the neighboring pixels. In turn the water appears less rough or even completely flat.

// file: water2.fx

float4 HighFidelityPS(...) : COLOR
    // (...)

    // calculate the normal we will be using for the water surface
    float4 W0 = tex2D( NormalSampler0, inV.mLayer0 );
    float4 W1 = tex2D( NormalSampler1, inV.mLayer1 );
    float4 W2 = tex2D( NormalSampler2, inV.mLayer2 );
    float4 W3 = tex2D( NormalSampler3, inV.mLayer3 );

    float4 sum = W0 + W1 + W2 + W3;
    float waveCrest = saturate( sum.a - waveCrestThreshold );

    // (...)

    // Lerp in a wave crest
    refractedPixels.xyz = lerp( refractedPixels.xyz, waveCrestColor, ( 1 - waterTexture.a ) * waveCrest);

    // (...)

The value inside waterTexture.a is the value we're painting with the foam brush described earlier. The value inside waveCrest is computed according to the alpha channel which is stored in sum.a of the water maps. By default, the waveCrestThreshold is 1.0: only water that has a higher alpha channel than 1.0 will have foam.

We need the blue brush (the one that increases) to decrease the foam on the water: by default the value is 0 and through the computation done (1 - waterTexture.a) the resulting value is 1. By default all the water will have foam assuming that the water normal maps have support for it. The waveCrest value will be different on all pixels and ranging between 0.0 and 1.0. In turn this generates white shapes on top of the water that can be interpreted as foam with the right textures.

For more information on the operators used:

About you

If you have interesting sources, approaches, opinions or ideas that aren't listed yet but may be valuable to the article: feel free to leave a message down below or contact me on Discord. The idea is to create a bunch of resources to share our knowledge surrounding various fields of development in Supreme Commander.

If you've used this resource for one of your maps feel free to make a post below: I'd love to know about it!

A work of art is never finished, merely abandoned