OpenGL ES 3.0 and newer on android

Good day @joliver82,

I am busy testing you code but when I enable the DirectionalLightShadowFilter I get the following error. As a side note I am using the “Common/MatDefs/Light/Lighting.j3md” material on a box.

Error on android:

06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: SEVERE Exception thrown in Thread[GLThread 7707,5,main]
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: com.jme3.renderer.RendererException: compile error in: ShaderSource[name=Common/MatDefs/Shadow/PostShadowFilter.frag, defines, type=Fragment, language=GLSL100]
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 0:9: P0003: Warning: Extension 'GL_ARB_gpu_shader5' not supported
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 0:119: L0003: Keyword 'sampler2DShadow' is reserved
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.renderer.opengl.GLRenderer.updateShaderSourceData(GLRenderer.java:1418)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.renderer.opengl.GLRenderer.updateShaderData(GLRenderer.java:1445)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.renderer.opengl.GLRenderer.setShader(GLRenderer.java:1509)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.material.logic.DefaultTechniqueDefLogic.render(DefaultTechniqueDefLogic.java:94)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.material.Technique.render(Technique.java:166)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.material.Material.render(Material.java:1024)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:614)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.post.FilterPostProcessor.renderProcessing(FilterPostProcessor.java:230)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.post.FilterPostProcessor.renderFilterChain(FilterPostProcessor.java:314)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.post.FilterPostProcessor.postFrame(FilterPostProcessor.java:334)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1114)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.renderer.RenderManager.render(RenderManager.java:1158)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:270)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.app.AndroidHarnessFragment.update(AndroidHarnessFragment.java:577)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:342)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1649)
06-12 11:48:29.375  9092  9143 E com.jme3.app.AndroidHarnessFragment: 	at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1354)

Thanks for the feedback. I forgot to specify that I was working with shadow rederers not filters :confused: I’ll have a look at filters later also and get back to you :wink:

Just in case it was relevant, could you tell me the device you’re using?

Okay excellent let me test quickly.
I am running my tests on a Samsung Galaxy Note4 with android 6.0.1

Could you check if it has GL_EXT_shadow_samplers extension?

I find it weird that it’s using sampler2DShadow in any way compiling for GLSL100 as the shader code for that case uses sampler2D always for GLES in GLSL100 although hardware shadows are set. See the snippet:

// this else comes from #if __VERSION__ >= 130
#else
  #define IVEC2 vec2
  #if defined GL_ES
      #define SHADOWMAP sampler2D
      #define SHADOWCOMPARE(tex,coord) step(coord.z, texture2DProj(tex, coord).r)
  #elif defined HARDWARE_SHADOWS
      #define SHADOWMAP sampler2DShadow
      #define SHADOWCOMPARE(tex,coord) shadow2DProj(tex, coord).r
  #else
      #define SHADOWMAP sampler2D
      #define SHADOWCOMPARE(tex,coord) step(coord.z, texture2DProj(tex, coord).r)
#endif

Is there any quick way you could output the composed shader from your device and copy it?

I’ve also just commited a quick fix to use GLSL300 for shadow filters also so you can try it if you want too :wink: but I’ve not tested myself still, so I cannot assure you it’ll work :thinking:

Thanks

@joliver82, just to confirm I am doing the correct change to get your code in my app. I basically made a build of your fork with your changes and then I only replace my jme-core.jar and jme-android.jar with the ones your fork builds.
Is this correct?

Yes, it’s correct but double check you’re compiling android-gl3 branch and also copy jme3-effects

Cool I got it to work.
I do have some strange looking artifacts in the scene.
The shadows does not look 100% correctly.
Screenshot_2019-06-12-15-07-13-3

weird artifacts… are you using filter or renderer? Are the models just plain cubes or imported models?

Could you post your shadows initialization code? (map size, splits, filtering mode…)

Forget my last message. I’ve tried the filter and although I was trying not to, I had to set precision to highp to solve it. This will affect performance but I don’t think it’ll be that much.

In the long term I may need to define a way to just set precision highp for post processing filters :thinking:

Just started testing PBR and it’s doing something but nothing special. Screenshot on the upper side is previous to finishing rendering the env maps. The second one is just after

I got the screenshots debugging with gapid (GitHub - google/gapid: Graphics API Debugger) and at least the env map seems to be properly generated (although it took ages to finish rendering it).

Probably it’s out of my knowledge but I’m also interested in having this working too so I’ll try to look deeper into it

1 Like

Have you tried with a pre-generated env map?
Pre-generate a light probe in desktop and just load it in android.

If you want you can also try with my baked light probes:

you can attach it like this:

    Node probeNode = (Node) assetManager.loadModel("scenes/lightprobe/bright-sky.j3o");
    LightProbe probe = (LightProbe) probeNode.getLocalLightList().iterator().next();
    System.out.println("radius=" + probe.getArea());
    probe.setPosition(new Vector3f(0, 0, 0));
    rootNode.addLight(probe);

So I am using normal jME Box geometry and I tried it with the renderer and with a filter.
Different result on both of them and none working correctly.

I made a simple scene now with just 2 Boxes, a directional light and DirectionalLightShadow renderer with the same results.

Any idea?

Here is my setup for the shadows:

dlsr = new DirectionalLightShadowRenderer(assetManager, 1024, 1);
        dlsr.setLight(sun);

EDIT:
Interesting though, I found that when I change the floor cube to only receive shadows and the cube that should cast shadows to only have Cast shadows and not CastAndReceive it seems to work fine.
So it might be something with the CastAndReceive option.

I don’t know much about shaders so I don’t really know how to investigate this.

In this last test did you use last commit from 10 hours ago? Could share a screenshot?

Okay I spend some time this morning to create a test case for the shadows.
Please see video with the different option below.
Basically I noticed that my problem has to do with the ShadowMode.
If I change all entities to have ShadowMode.CastAndReceive all seems to work very good.

1 Like

Thanks for the time spent and the testcase. The weirdest scenario is the one having glitches when having boxes as Receive and floor castandreceive. The depth map should not affect the cubes. I’ll replicate your test to try to find out why it’s happening

1 Like

I’ve been working a little with some effects as I was bored of shadows :stuck_out_tongue: Here’s the TestPostWater running on my SGS6:

It was a quick modification of shaders and enabling GLSL300 for some materials and voila!

I removed the skybox because of android / GLES not supporting DXT1 and I was lazy to search how to convert it to other format :stuck_out_tongue:

I also set it to use just one sample, otherwise it rendered the whole screen black

It’s rendering exactly the same compared to my desktop PC.

Hope you like it

7 Likes

Excellent @joliver82, this is a good job.
I will now test the water in my test cases.

You can open it with GIMP and then convert it to another format like PNG.

I’ve been playing around with PBR and I don’t think it’ll work for android at least for a short time. First of all, most devices don’t support RGB16F fully so changing it to RGB8 as follows:

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

avoid the format unsupported exception but makes it render awful in comparison (Left RGB8, Right RGB16F):

This could be bypassed using pre-rendered light probes as RGB16F is supposed to be supported from GLES3.0 just as texture format not for frame buffers (and adding it to the GL image formats if this version or newer is detected). But at least in my tests SGS6 doesn’t render RGB16F properly and I don’t have other new enough mobile (without half float extension) to try.

In adition to that, the shaders don’t render exactly the same as in desktop. It’s just overwriting the color of the model with some plain dark green. Honestly, I still don’t understand why although I’ll try to look into it the next week

1 Like

You are using HDR with RGB8 images, the colors will get clamped to 0,1 and the tonemap filter will make it look like that. If you rebuild the scene to not use HDR and tonemap, i think it will end up looking good enough.