Black terrain texture/Material in Android

Hi,

I’m trying to run a very basic example on Android and I always get the terrain rendered in black. What I’m doing is create a basic game project, create a new scene, add a simple terrain (tried also painting some textures, creating relief, etc.), add a directional light (I also added at some point all possible lights in the scene), and then from the main application, I’m loading that scene and adding it to the root node. On desktop everything is fine, but on Android the terrain renders all black.
I’ve also tried adding the directional light in the code, even applied a Terrain.j3md material from the code. Nothing helped.

I thought is the device, but then the SimpleTerrainAndroid example runs perfectly on the same device so I can’t seem to figure out what I am doing wrong.
Is there any declaration, modification that is required in the manifest, main application class, etc.? Also to mention that I have played in the past with JME3 beta and RC2 and the terrain rendered fine on Android, same device and without major modifications. I tried both stable (download and also Updated version) and nightly versions and it’s the same.

The only time I could get the terrain texture to render was when applying an unshaded material, however if I am to use the engine I need at least the Terrain.j3md material to render on mobile.

I’m sure it’s me that I’m doing something wrong, but hope someone can help me tell what am I missing. This is the simplest code I am using:

[java]
package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Spatial;

public class Main extends SimpleApplication {

public static void main(String[] args) {
    Main app = new Main();
    app.start();
}

@Override
public void simpleInitApp() {

    viewPort.setBackgroundColor(ColorRGBA.Blue);
        /** A white, directional light source */ 

Spatial scene = assetManager.loadModel( “Scenes/level1.j3o” );

    rootNode.attachChild(scene);
    
        DirectionalLight sun = new DirectionalLight();
sun.setDirection((new Vector3f(-0.5f, -0.5f, -0.5f)).normalizeLocal());
sun.setColor(ColorRGBA.White);
rootNode.addLight(sun); 
    

}

@Override
public void simpleUpdate(float tpf) {
    //TODO: add update code
}

@Override
public void simpleRender(RenderManager rm) {
    //TODO: add render code
}

}
[/java]

@alegri: You’re not doing something wrong. This is already discussed in this thread:
http://hub.jmonkeyengine.org/forum/topic/black-textures-in-android/page/2/

There is no real solution yet, other than replacing the generated material with some other material (from scene composer/at runtime).

As @Sploreg mentions in http://hub.jmonkeyengine.org/forum/topic/black-textures-in-android/page/3/#post-263989 we found why terrain generated in the SDK shows up all black on Android.

In jME Android projects, jME uses the Android Bitmap image loader to create the textures. Unfortunately, the Android Bitmap loader pre-multiplies the RGB values by the alpha channel value. This means that when generating terrain in the SDK, the RGB values in the alphamap are set to 0 when the alpha channel is 0. This happens for all pixels that do not have the 4th texture painted. And, of course, when the 4th texture is painted on the terrain, the first 3 textures won’t show up for those pixels either.

For jME 3.1, we’ve added a new image loader for Android that does not pre-multiply the RGB values by the alpha value. This allows the terrain generated in the SDK to show properly. Because this changes how all alpha channel textures are loaded for Android projects, it is only added to the latest jME 3.1 builds right now.

The reason running the SimpleTerrain tests work is that they use the Terrain.j3md material definition which does not use an alpha channel. The terrain generated in the SDK uses the TerrainLighting.j3md material definition which does use the alpha channel.

For the short term on jME 3.0, terrain will only work properly when using the Terrain.j3md material definition which is unlit and will only allow you to use 3 textures on the terrain.

@iwgeric

Hi there!

I’m having this same issue but with the regular Terrain.j3md. I’m using the scene composer/terrain editor to create my scene and then use the following method to change the lit terrain material to the regular terrain.j3md

[java] Material tat = new Material(assetManager, “Common/MatDefs/Terrain/Terrain.j3md”);

    if (geom.getMaterial().getTextureParam("DiffuseMap_1") != null) {
        
      tat.setTexture("Alpha", geom.getMaterial().getTextureParam("AlphaMap").getTextureValue());
      
      if (geom.getMaterial().getTextureParam("DiffuseMap") != null) {
       
      tat.setTexture("Tex1", geom.getMaterial().getTextureParam("DiffuseMap").getTextureValue());
      tat.getTextureParam("Tex1").getTextureValue().setWrap(Texture.WrapMode.Repeat);
      tat.setFloat("Tex1Scale", Float.valueOf(geom.getMaterial().getParam("DiffuseMap_0_scale").getValueAsString()));
      
      }
    
      if (geom.getMaterial().getTextureParam("DiffuseMap_1") != null) {
          
      tat.setTexture("Tex2", geom.getMaterial().getTextureParam("DiffuseMap_1").getTextureValue());
      tat.getTextureParam("Tex2").getTextureValue().setWrap(Texture.WrapMode.Repeat);
      tat.setFloat("Tex2Scale", Float.valueOf(geom.getMaterial().getParam("DiffuseMap_1_scale").getValueAsString()));
      
      }
    
      if (geom.getMaterial().getTextureParam("DiffuseMap_2") != null) {
          
      tat.setTexture("Tex3", geom.getMaterial().getTextureParam("DiffuseMap_2").getTextureValue());
      tat.getTextureParam("Tex3").getTextureValue().setWrap(Texture.WrapMode.Repeat);
      tat.setFloat("Tex3Scale", Float.valueOf(geom.getMaterial().getParam("DiffuseMap_2_scale").getValueAsString()));
      
      }

      geom.setMaterial(tat);
      
      }[/java] 

This works on the pc version but not on the android device as the terrain is black!

How do I make it work as you explained above with the regular terrain.j3md material!

Thanks for reading

Creating the images using the SDK will result in having images with the alpha channel = 0 (assuming you did not use a 4th image during painting).

Because of this, when the image is loaded during the app startup, the RGB values will also be 0 because of the pre-multiplying issue mentioned before.

Simply switching the material definition won’t help by itself. The image created by the SDK needs to have the alpha channel = 1 in order to not display black. You’ll have to do this manually with some graphics tool like gimp or photoshop.

@iwgeric said: ... Simply switching the material definition won't help by itself. The image created by the SDK needs to have the alpha channel = 1 in order to not display black. You'll have to do this manually with some graphics tool like gimp or photoshop.

You can do that in the SDK actually :slight_smile: Right click the image and select “Edit Texture”. Right above the toolbar in the image editor is a menu “Filters” -> “Invert” that can invert single channels in the image.

@iwgeric

So if I added a 4th layer of texture it would work properly? (Even though this won’t be switched over due to the terrain.j3md only having 3 layers?)

@jmaasing

It seems you are here to save me yet again! Which texture am I doing this on? Am I doing this in the scenecomposer?

I’ve never even used the filter explorer (though I have seen it down there on my menu list for quite some time)

@BigBob said:

It seems you are here to save me yet again! Which texture am I doing this on? Am I doing this in the scenecomposer?

The alpha map like iwgeric talked about.

I've never even used the filter explorer (though I have seen it down there on my menu list for quite some time)

Totally different thing. This is image processing, nothing to do with render filters.

@jmaasing

Oops!

Okay I’ve found what you’re talking about and I really don’t want to mess this up. I would do this to ALL the generated alpha textures in the “terrain-alpha” folder correct?

Also when I do invert the texture channel, it just opens up another window in the sdk and I have no idea how to save it, or overwrite the original.

Thanks for reading!

how to save?
use: Ctrl+S

10 steps to get happy …

  1. Find alphamaps?: Right click predefined scene, choose edit terrain

  2. Right click your terrain, in context box: click tools, click rename alpha maps: This shows the name of the current alphamaps assigned to it

  3. Find alpha texture in: ProjectAssets/textures/terrain-alpha/“nameOfYourAlphaMap”.png

  4. Rightclick alphamap: Edit texture

  5. Click on Filters, its above the zome button of the new window. Window should show the texture it could be that it shows nothing depens on alpha

  6. Click Filters, click Invert, click Alpha

  7. Open save popup with: Windows hotkey, Crtl+S

  8. On my system, windows explorer opens but the save button is named with open. Enter name.png press open. A couple seconds later, a screen appears: image saved

  9. Make bakup of old picture, overwrite old picture with new picture. check if the name is still the same, else you have to rename alpha map in scene composer, go back to point 2.

  10. Be happy
    Kind regards
    Alex

If this post was useful for you, rate it :wink: