2
\$\begingroup\$

I am facing a problem while porting one of my libGDX project from desktop to Android : My game uses Box2DLights. While the light effect look very fancy on the desktop version of the game, it looks really ugly on the Android version. The light gradient is not smooth at all. Take a look at the comparative screenshot below :

enter image description here

To use Box2DLights in my game, I use this code in my GameScreen :

 rayHandler = new RayHandler(world); 
 rayHandler.resizeFBO(Gdx.graphics.getWidth()/5, Gdx.graphics.getHeight()/5); 
 rayHandler.setBlur(true);   
 RayHandler.useDiffuseLight(true); 
 rayHandler.setAmbientLight(new Color(0.15f, 0.15f, 0.15f, 0.1f)); 

Of course, I tried to play with different parameters, such as :

RayHandler.useDiffuseLight(fasle);

Or

rayHandler.diffuseBlendFunc.set(GL20.GL_DST_COLOR, GL20.GL_SRC_COLOR);

Or

rayHandler.shadowBlendFunc.set(GL20.GL_DST_COLOR, GL20.GL_SRC_COLOR);

Everything I tried so fare gave the same ugly light gradient. I already played games that uses Box2DLights that rendered very well on my tablet, thus, I don't think it's due to a limitation of Android.

Does anybody know what's the trick to overcome this problem ?

Thanks !

\$\endgroup\$

2 Answers 2

2
+50
\$\begingroup\$

I suspect what's going on to cause that rainbow coloured banding is that the textures or render targets involved are of a low bit-depth on Android (maybe 5-6-5 instead of 8-8-8). There could also be some texture compression involved somewhere, as 5-6-5 usually only gives green and grey banding, because the green channel has an extra bit.

A quick search suggests that enabling dithering using Gdx.gl.glEnable(GL10.GL_DITHER); should help.

Alternatively, you could try changing the background to give it a bit of texture.

\$\endgroup\$
5
  • \$\begingroup\$ My texture atlas is in RGB8888 format. I added Gdx.gl.glEnable(GL20.GL_DITHER); to the render loop of the GameScreen, and that didn't change anything. Thanks for the answer though ! \$\endgroup\$
    – vdlmrc
    Commented Mar 26, 2016 at 14:18
  • \$\begingroup\$ What format is the render target / back buffer? \$\endgroup\$
    – Adam
    Commented Mar 26, 2016 at 18:08
  • \$\begingroup\$ I am not sure how to check that. It must be the default format of libGDX back buffer, since I've modified the back buffer format \$\endgroup\$
    – vdlmrc
    Commented Mar 27, 2016 at 15:01
  • \$\begingroup\$ OK, after diving a bit in the code of Box2DLights, I found that the image is rendered in a frame buffer with RGBA8888 format... So, back to square one. I have no idea what causes this color banding effect... \$\endgroup\$
    – vdlmrc
    Commented Apr 2, 2016 at 4:24
  • \$\begingroup\$ Finally ! I found where this RGB565 parameter was set. In the AndroidApplicationConfiguration.java there is public int r = 5, g = 6, b = 5, a = 0; This can be modified in the AndroidLauncher.java. I'll post a more detailed answer, for those who encounter the same problem. \$\endgroup\$
    – vdlmrc
    Commented Apr 3, 2016 at 15:14
1
\$\begingroup\$

Here is the solution :

As Adam said in his answer, the problem was linked to a low bit depth on Android. If you look to the code of AndroidApplicationConfiguration.java, you'll notice at lines 30 and 31 this code :

/** number of bits per color channel **/
public int r = 5, g = 6, b = 5, a = 0;

Thus, Android applications with libGDX render, by default, low bit images. This can be easily modified in the AndroidLauncher.java of your application.

The default AndroidLauncher.java of your app looks like this :

public class AndroidLauncher extends AndroidApplication {
    @Override
    protected void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
        initialize(new MyGdxGame(), config);
    }
}

All you have to do, to have a render format of RGBA8888 for your Android app is :

public class AndroidLauncher extends AndroidApplication {
    @Override
    protected void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
        config.r = 8;
        config.g = 8;
        config.b = 8;
        config.a = 8;
        initialize(new MyGdxGame(), config);
    }
}

Et voilà ! Here is a comparative screenshot of Android RGB565 VS Android RGBA8888 VS Desktop : enter image description here

You can see that the Android RGBA8888 is very close to the desktop version.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .