Click or drag to resize
DigitalRuneClouds

This topic contains the following sections:

Video

The following video demonstrates features of the cloud system:

Defining clouds

A CloudLayerNode can be used to add clouds to a scene. The clouds are rendered as a 2D layer in the sky.

The structure of the clouds is defined by a cloud texture in CloudMap. The cloud texture stores the transmittance of the sky (see CloudMapTexture for more information). It is possible to set an artist-defined texture (see BasicCloudMap) or dynamically generate a cloud texture at runtime (see LayeredCloudMap). (The clouds in the video use a LayeredCloudMap). consisting of 8 octaves of noise.)

The texture coordinates of a layered cloud map can be scrolled to create clouds moving in the wind. The cloud map can also be animated to simulate simple formation and dissipation of clouds. The Coverage of the LayeredCloudMap can be used to transition from a clear to an overcast sky.

DigitalRune.Graphics (Clouds)
Class Diagram: Clouds

The following example shows how to add a cloud layer to a scene.

Example (C#)
// The cloud map defines the settings for generating a cloud texture.
var cloudMap = new LayeredCloudMap
{
  Density = 15,
  Coverage = 0.5f,
  Size = 2048,
};
// The cloud is built from 8 octaves of static noise.
var scale = CreateScale(0.2f);  // Scale the noise to generate bigger clouds patches.
cloudMap.Layers[0] = new CloudMapLayer(null, scale * CreateScale(1), -0.5f, 1.0f, 0);
cloudMap.Layers[1] = new CloudMapLayer(null, scale * CreateScale(1.7f), -0.5f, 1.0f / 2.0f, 0);
cloudMap.Layers[2] = new CloudMapLayer(null, scale * CreateScale(3.97f), -0.5f, 1.0f / 4.0f, 0);
cloudMap.Layers[3] = new CloudMapLayer(null, scale * CreateScale(8.1f), -0.5f, 1.0f / 8.0f, 0);
cloudMap.Layers[4] = new CloudMapLayer(null, scale * CreateScale(16, 17), -0.5f, 1.0f / 16.0f, 0);
cloudMap.Layers[5] = new CloudMapLayer(null, scale * CreateScale(32, 31), -0.5f, 1.0f / 32.0f, 0);
cloudMap.Layers[6] = new CloudMapLayer(null, scale * CreateScale(64, 67), -0.5f, 1.0f / 64.0f, 0);
cloudMap.Layers[7] = new CloudMapLayer(null, scale * CreateScale(128, 127), -0.5f, 1.0f / 64.0f, 0);

// Add a new CloudLayerNode to the scene.
var cloudLayerNode = new CloudLayerNode(cloudMap)
{
  SkyCurvature = 0.9f,
  TextureMatrix = CreateScale(0.5f),  // Stretch the texture by 2X.
  ForwardScatterExponent = 10,
  ForwardScatterScale = 10f,
  ForwardScatterOffset = 0.3f,
  NumberOfSamples = 16,
  HorizonFade = 0.03f,
};
scene.Children.Add(_cloudLayerNode);

CreateScale in the example above is a helper method that creates a texture matrix.

Example (C#)
/// <summary>
/// Creates the texture matrix for scaling texture coordinates.
/// </summary>
/// <param name="s">The uniform scale factor.</param>
/// <returns>The texture matrix.</returns>
public static Matrix33F CreateScale(float s)
{
  return CreateScale(s, s);
}

/// <summary>
/// Creates the texture matrix for scaling the texture coordinates.
/// </summary>
/// <param name="su">The scale factor for u texture coordinates.</param>
/// <param name="sv">The scale factor for v texture coordinates.</param>
/// <returns>The texture matrix.</returns>
public static Matrix33F CreateScale(float su, float sv)
{
  return new Matrix33F(
    su, 0, 0,
    0, sv, 0,
    0, 0, 1);
}

Clouds are lit by sunlight and ambient light. The settings need to be updated by the game logic.

Example (C#)
// Read light values from light nodes or environment model.
cloudLayerNode.SunDirection = sunDirection;
cloudLayerNode.SunLight = sunlight;
cloudLayerNode.AmbientLight = ambientLight;

The cloud texture can be animated or used to render cloud shadows. These and other topics are demonstrated in the included sample projects.

Rendering clouds

A CloudLayerNode is a SkyNode and it is rendered by the SkyRenderer like all other SkyNodes.

Clouds are lit by the sun and ambient light settings of the CloudLayerNode. Clouds in front of the sun show forward scattering.

To create cloud shadows, the cloud map texture can be used as the texture of the directional light which represents the sun. The sun occlusion can also be computed by the renderer and is stored in the CloudLayerNode. This value can be used, for example, to reduce lens flare effects when the sun is occluded.

Cloud textures are created by a separate renderer, the CloudMapRenderer. (The CloudMapRenderer only creates the cloud textures for LayeredCloudMaps. It does not render the clouds into the sky.)

CloudMapRenderer

Cloud textures can be generates using a CloudMapRenderer. The CloudMapRenderer is a SceneNodeRenderer which handles CloudLayerNodes. If a CloudLayerNode references a LayeredCloudMap, the renderer creates the cloud texture and stores the result in the cloud map.

Cloud textures are usually generated at the start of the Draw-method, before the scene is rendered:

C#
// Generate the cloud textures of CloudLayerNodes.
cloudMapRenderer.Render(cloudNodes, context);

// Render scene...
Tip Tip

It is not necessary to call the CloudMapRenderer in every frame. Static cloud textures only need to be updated when the cloud map is changed. Dynamic, slow moving clouds can updated every second frame - or even less frequent.