More On Height Maps

Introduction

In this tutorial, our goal is to understand height maps, and to learn how to generate realistic grounds.

Final result

How can I do this ?

Introduction

Those mountains are very easy to generate with Babylon.js, and with only a single function. But before we do that, we have to create a new material, like we have done many times before:

// Create a material with our land texture.
var groundMaterial = new BABYLON.StandardMaterial("ground", scene);
groundMaterial.diffuseTexture = new BABYLON.Texture("Earth__land.jpg", scene);
// This shows how we would apply this material to a plane. In our later
// example we'll replace this with CreateGroundFromHeightMap.
var groundPlane = BABYLON.Mesh.CreatePlane("groundPlane", 200.0, scene);
// When our new mesh is read, apply our material.
groundPlane.material = groundMaterial;

Our material, a texture, applied to the plane

Explanations of a height map

Understanding height maps is the main objective of this tutorial. A height map is simply a grayscale image like the one we are going to use:

This image will now be used to generate our ground, using the different variants of gray of our picture. This image is the elevation data for your ground. Each pixel’s color is interpreted as a distance of displacement or “height” from the “floor” of your mesh. So, the whiter the pixel is, the taller your mountain will be.

To help you generate those grayscale height maps, you can use software such as “Terragen”, or ”Picogen”.

Javascript code

Now let’s see this powerful function named CreateGroundFromHeightMap:

// Create a material with our land texture.
var groundMaterial = new BABYLON.StandardMaterial("ground", scene);
groundMaterial.diffuseTexture = new BABYLON.Texture("Earth__land.jpg", scene);
// Use CreateGroundFromHeightMap to create a height map of 200 units by 200
// units, with 250 subdivisions in each of the `x` and `z` directions, for a
// total of 62,500 divisions.
var ground = BABYLON.Mesh.CreateGroundFromHeightMap("ground", "worldHeightMap.jpg", 200, 200, 250, 0, 10, scene, false, successCallback);
// When our new mesh is read, apply our material.
ground.material = groundMaterial;

There are many parameters here:

  • Name
  • Height map picture url
  • Width of mesh
  • Height of mesh
  • Number of subdivisions: increase the complexity of this mesh in order to improve the visual quality of the result

  • Minimum height : The lowest level of the mesh
  • Maximum height : the highest level of the mesh
  • Scene: the actual scene
  • Updatable: indicates if this mesh can be updated dynamically in the future (Boolean)
  • successCallback : will be called after the height map was created and the vertex data is created. It is a function with the mesh as its first variable.

Now we have a beautiful 3D view of the earth!

In my example, I have added a skybox (like we have learned before here), and a spotlight to simulate sun activity.

Here is another example showing what you can achieve with BabylonJS height maps:

Tips

When the user is manipulating the camera, it can be awkward if they can see under the ground, or if they zoom-out outside the skybox. So, to avoid that kind of situation, we can constrain the camera movement:

var camerasBorderFunction = function () {
//Angle
if (camera.beta < 0.1)
camera.beta = 0.1;
else if (camera.beta > (Math.PI / 2) * 0.9)
camera.beta = (Math.PI / 2) * 0.9;
//Zoom
if (camera.radius > 150)
camera.radius = 150;
if (camera.radius < 30)
camera.radius = 30;
};
scene.registerBeforeRender(camerasBorderFunction);

You may be interested in visiting the playground demo that goes with this tutorial:

Height Map Example