Heightmaps + normals


I’m trying to create terrain using the ImageBasedHeightMap. However, the terrain looks boring because there is no shading or shadows. Is there some sort of ‘normal generator’ I can use to shade my terrain?

I did add a directional light, but it seems that normals are not automatically generated. Did I do something wrong here?

DirectionalLight sun = new DirectionalLight();


sun.setDirection(new Vector3f(-1, -1, 1).normalizeLocal());


perhaps this will work, don’t know:


Do you use the TerrainLighting material or Terrain material? the first one is shaded, the second one is unshaded.

I used this (I got this from the tutorials on this website and modified it as I needed):

private TerrainQuad terrain;

private Material mat_terrain;


DirectionalLight sun = new DirectionalLight();


sun.setDirection(new Vector3f(-1, -1, 1).normalizeLocal());


/** 1. Create terrain material and load four textures into it. /

mat_terrain = new Material(assetManager,


* 1.1) Add ALPHA map (for red-blue-green coded splat textures) /

mat_terrain.setTexture(“Alpha”, assetManager.loadTexture(


* 1.2) Add GRASS texture into the red layer (Tex1). /

Texture grass = assetManager.loadTexture(



mat_terrain.setTexture(“Tex1”, grass);

mat_terrain.setFloat(“Tex1Scale”, 64f);

* 1.3) Add DIRT texture into the green layer (Tex2) /

Texture dirt = assetManager.loadTexture(



mat_terrain.setTexture(“Tex2”, dirt);

mat_terrain.setFloat(“Tex2Scale”, 32f);

* 1.4) Add ROAD texture into the blue layer (Tex3) /

Texture rock = assetManager.loadTexture(



mat_terrain.setTexture(“Tex3”, rock);

mat_terrain.setFloat(“Tex3Scale”, 128f);

* 2. Create the height map /

AbstractHeightMap heightmap = null;

Texture heightMapImage = assetManager.loadTexture(


heightmap = new ImageBasedHeightMap(

ImageToAwt.convert(heightMapImage.getImage(), false, true, 0));


// try {

// heightmap = new MidpointDisplacementHeightMap(129, 1, 0.5f, 0);

// } catch (Exception e) {}

* 3. We have prepared material and heightmap.

  • Now we create the actual terrain:
  • 3.1) Create a TerrainQuad and name it “my terrain”.
  • 3.2) A good value for terrain tiles is 64x64 – so we supply 64+1=65.
  • 3.3) We prepared a heightmap of size 512x512 – so we supply 512+1=513.
  • 3.4) As LOD step scale we supply Vector3f(1,1,1).
  • 3.5) We supply the prepared heightmap itself.


    int patchSize = 65;

    terrain = new TerrainQuad(“my terrain”, patchSize, 513, heightmap.getHeightMap());

    * 4. We give the terrain its material, position & scale it, and attach it. /


    terrain.setLocalTranslation(0, -100, 0);

    terrain.setLocalScale(2f, 1f, 2f);


    * 5. The LOD (level of detail) depends on were the camera is: */

    List cameras = new ArrayList();


    TerrainLodControl control = new TerrainLodControl(terrain, cameras);



mat_terrain = new Material(assetManager,“Common/MatDefs/Terrain/Terrain.j3md”);


that’s the problem



mat_terrain = new Material(assetManager,“Common/MatDefs/Terrain/TerrainLighting.j3md”);


java.lang.IllegalArgumentException: Material parameter is not defined: Alpha

at com.jme3.material.Material.checkSetParam(Material.java:374)

at com.jme3.material.Material.setTextureParam(Material.java:476)

at com.jme3.material.Material.setTexture(Material.java:524)

at HelloTerrain2.simpleInitApp(HelloTerrain2.java:46)

at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:230)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:129)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:205)

at java.lang.Thread.run(Thread.java:662)

line 47 is

mat_terrain.setTexture(“Alpha”, assetManager.loadTexture(


when I commented that line out the rest of the setTexture() calls throw similar exceptions

edit: I commented out ALL the setTextures() and the code succesfully ran; the terrain is gorgeous. But how do I get the textures to work?

I do need the texture splatting.

erf yeah there might be a couple of things to change

take a look at this test case



Nehon is correct. To have the terrain look pretty you want to use the TerrainLighting material, as shows in the TerrainTestAdvanced.java file.

This is what I did. I took nehon’s link and copied it into my code, making minimal changes to try and see if it works as is. I got a compiler error at :

heightmap = new ImageBasedHeightMap(heightMapImage.getImage());


assets = assetManager;

Material matTerrain = new Material(Artist.assets, “Common/MatDefs/Terrain/TerrainLighting.j3md”);

matTerrain.setBoolean(“useTriPlanarMapping”, false);

matTerrain.setFloat(“Shininess”, 0.0f);

matTerrain.setTexture(“AlphaMap”, Artist.assets.loadTexture(“Textures/alpha.png”));

matTerrain.setTexture(“AlphaMap_1”, Artist.assets.loadTexture(“Textures/alpha.png”));

Texture grass = Artist.assets.loadTexture(“Textures/grass.gif”);


matTerrain.setTexture(“DiffuseMap_1”, grass);

matTerrain.setFloat(“DiffuseMap_1_scale”, 16);

Texture dirt = Artist.assets.loadTexture(“Textures/mountain.gif”);


matTerrain.setTexture(“DiffuseMap”, dirt);

matTerrain.setFloat(“DiffuseMap_0_scale”, 16);

Texture rock = Artist.assets.loadTexture(“Textures/plains.gif”);


matTerrain.setTexture(“DiffuseMap_2”, rock);

matTerrain.setFloat(“DiffuseMap_2_scale”, 16);

Texture normalMap0 = Artist.assets.loadTexture(“Textures/grass.gif”);


Texture normalMap1 = Artist.assets.loadTexture(“Textures/mountain.gif”);


Texture normalMap2 = Artist.assets.loadTexture(“Textures/plains.gif”);


matTerrain.setTexture(“NormalMap”, normalMap0);

AbstractHeightMap heightmap = null;

Texture heightMapImage = assetManager.loadTexture(


heightmap = new ImageBasedHeightMap(heightMapImage.getImage());


int patchSize = 65;

TerrainQuad terrain = new TerrainQuad(“my terrain”, patchSize, 513, heightmap.getHeightMap());


terrain.setModelBound(new BoundingBox());


terrain.setLocalTranslation(0, -100, 0);

terrain.setLocalScale(1f, 1f, 1f);


DirectionalLight light = new DirectionalLight();

light.setDirection((new Vector3f(-0.5f, -0.5f, -0.5f)).normalize());



At the line: heightmap = new ImageBasedHeightMap(heightMapImage.getImage());

no suitable constructor found for ImageBasedHeightMap(com.jme3.texture.Image)

constructor com.jme3.terrain.heightmap.ImageBasedHeightMap.ImageBasedHeightMap(java.awt.Image,float) is not applicable

(actual and formal argument lists differ in length)

constructor com.jme3.terrain.heightmap.ImageBasedHeightMap.ImageBasedHeightMap(java.awt.Image) is not applicable

(actual argument com.jme3.texture.Image cannot be converted to java.awt.Image by method invocation conversion)

Apparently the compiler is confusing the awt Image class with jme3’s Image class. I tried various castings and some other stuff but it didn’t work.

You need to update to the latest version from SVN or the latest nightly build.