OpenGL ES 3.0 and newer on android

Hi @joliver82, are you still working on PBR for android?

What is the change we can get fixes for the other Post processor filters such as FOG and Bloom, etc.


Again thanks for the awesome fixes you have made so far.


@Riccardo, Thanks for the comment but I just used RGB8 to be able to test it on all my android devices although it wasn’t looking good. In all cases the (either using RGB8 or RGB16F in mobiles supporting it) the result was the same, the mobiles didn’t render it near to what was expected. Depending on the environment, a little brighter color (plain dark green in the test I was talking about in my previous comment).

@ndebruyn, Yes, I’m still on it but without good results. In the first place I though it was related to the shader but I made some tests with it (outputting normals, calculated “dominantR” which is used to lookup in the cubemap and finally outputting the map using both normals or dominantR as texture coordinates. All results were the same except when trying to output the map (g_PrefEnvMap). So from my point of view, now it seems that the maps are not properly uploaded to the GPU but I don’t undestand why.

I’m posting you two screenshots, one from the desktop and the other from the mobile supporting RGB16F

The big sphere in the middle of the screen is the LightsDebugState

I’ve reviewed the code and even traced the GL interface in the mobile and everything looks correct to I’m out of ideas :confused:

Any help would be nice :wink:

In the meanwhile, I think I’ll get focused on the shadows issue you told me, some rendering glitches I notices while using water filter in my GLES3.0 mobile and checking black screen rendering when multisamples are enabled in post processing filters

About the other filters you asked me, most of them should work now out of the box. I tested bloom, fxaa, ssao and some others. Feel free to play with them and give me feedback :wink:

Previously I forgot to add the screenshot before calculating the probe:


Quick update

I added a new cubemap to the material to test it deeper to overwrite the fragment color. I added the following to the shader:

//At the definition section
uniform samplerCube g_TestEnvMap;

//At the end of main
    #if NB_PROBES >= 1
        vec3 tCoord=renderProbeTest(viewDir, wPosition, normal, norm, Roughness, diffuseColor, specularColor, ndotv, ao, g_LightProbeData, g_ShCoeffs, g_PrefEnvMap, color1).xyz;
        vec3 cbCol=textureCube(g_PrefEnvMap, tCoord).rgb;
        vec3 tCoord=normalize(;
        vec3 cbCol=textureCube(g_TestEnvMap, tCoord).rgb;

The renderProbeTest function is the same renderProbe in PBR.glsllib but returning the dominantR

This way, when the probe is not calculated still, it’s rendering the test map ( which I converted to RGBA8) using the normal as texture coordinate and once it’s calculated, uses dominantR as texture coordinate for the EnvMap.

The texture is loaded as follows:

    TextureKey key = new TextureKey("Scenes/Beach/", true);
    Texture skyTex = assetManager.loadTexture(key);

The EnvMap is calculated as RGBA8 also so there’s no difference in the format of each cubemap

final EnvironmentCamera envCam = new EnvironmentCamera(256, new Vector3f(0, 3f, 0), Image.Format.RGBA8);

I also tried using using dominantR as texture coord for the test map:

    #if NB_PROBES >= 1
        vec3 tCoord=renderProbeTest(viewDir, wPosition, normal, norm, Roughness, diffuseColor, specularColor, ndotv, ao, g_LightProbeData, g_ShCoeffs, g_PrefEnvMap, color1).xyz;
        vec3 cbCol=textureCube(g_TestEnvMap, tCoord).rgb;
        vec3 tCoord=normalize(;
        vec3 cbCol=textureCube(g_TestEnvMap, tCoord).rgb;

Here are the results:

Normal as texture coord and test map:

dominantR as texture coord and EnvMap:

dominantR as texture coord and test map:

Any ideas why GLES is ignoring the probe generated texture?

Did you try to run a renderdoc capture to see what is going on?

I used gapid and now checked also with renderdoc. Both are exactly the same except from the filtering (mip none vs mip linear):

Default cube map (rendering correctly):

Probe generated cubemap (rendering black):

Both maps have mipmaps (I forced jme to generate them for the first cubemap). Could that make android not to render it? Sounds weird to me :thinking:


Can you upload the capture?

Sure, later after I get out of the office, or tomorrow I’ll upload It.

In the meanwhile, I’ve read the following link: not specially related but near enough though. Copied from the answer:

A cube map sampler is called, and either the corresponding cube map texture image is not cube complete, or TEXTURE_MIN_FILTER is one that requires a mipmap and the texture is not mipmap cube complete.

Being that said… Maybe it’s not rendering because the probe generated cubemap has only 6 mipmaps instead of all of them till 1px in comparison with the other cubemap…?

Possible, but the code that generates the cubemap should set the proper max mipmap level. You can use textureCubeLod(tx,coord,0) instead of textureCube and see if it works.

OK, that’s the issue. From GLES specs:

Section 8.17 Texture Completeness

Using the preceding definitions, a texture is complete unless any of the following conditions hold true:

The minification filter requires a mipmap (is neither NEAREST nor LINEAR),
and the texture is not mipmap complete.

Section Texture Access

If a sampler is used in a shader and the sampler’s associated texture is not
complete, as defined in section 8.17, (0.0, 0.0, 0.0, 1.0), in floating-point, will be

In this case the cubemap is not mipmap complete (only 6 mips) and jme is setting min filter LINEAR_MIPMAP_LINEAR being a non-complete texture causing the shader to get 0,0,0,1 as sampler color

Either I could force jme to set a non mipmap filter for minification or generate all missing mips

It also sets GL_TEXTURE_MAX_LEVEL that is available in opengl es 3.0 .

1 Like

Good point, I didn’t know it was added to GLES3. I’ll try it and I’m mostly sure it’ll finally work. Thanks for the tip :wink:

You were right @Riccardo, making jme set GL_TEXTURE_MAX_LEVEL made it finally work!! Thanks!!!

Change comited and here’s the video demo:

Devices not having RGB16F support will use RGB8 instead which will not look that good but at least won’t just fail. I’ll have a look at it later and also I’m thinking in trying to support it for GLES20 devices but I’m not sure if it’s a nonsense work as GLES30 specification is almost 3 year old now and most people don’t keep a mobile phone that long nowadays


Oh i see… tbh i thought jme was already doing that for gl es 3… good job

No sadly jme was not using gles3 features at all :frowning: that’s why I started working on it :wink:


Finally some love to android.


I will give these fixes a try as soon as I get some time again.
Well done on getting this to work.


Just a quick update with new additions to the fork. Now 3D textures and texture arrays work on gl es 3.0


Hi @joliver82,
When do you thing will you create a pull request for you code to get into the master jME repo?

I would love to see your fixes in a release of jME.


Just after finishing all half-done work. Probably next week :thinking:

Now I’m still trying to make multisampling work but I’m stuck so I may remove related code and create the PR without it after I’ve finished all other stuff :wink:


Thanks that is very good news.