Shadows and post processor filters issues and proposals

Hi,

After having solved the framebuffer issue in android, I’ve been testing multiple features and found the following.

Shadows are not working giving the following exception:

E/com.jme3.app.AndroidHarnessFragment(22594): com.jme3.renderer.RendererException: compile error in: ShaderSource[name=Common/MatDefs/Shadow/PostShadow.frag, defines, type=Fragment, language=GLSL100]
E/com.jme3.app.AndroidHarnessFragment(22594): Fragment shader compilation failed.
E/com.jme3.app.AndroidHarnessFragment(22594): WARNING: 0:10: extension 'GL_ARB_gpu_shader5' is not supported
E/com.jme3.app.AndroidHarnessFragment(22594): ERROR: 0:116: 'sampler2DShadow' : Reserved word.
E/com.jme3.app.AndroidHarnessFragment(22594): ERROR: 0:116: 'sampler2DShadow' : Syntax error: syntax error
E/com.jme3.app.AndroidHarnessFragment(22594): ERROR: 2 compilation errors. No code generated.

Reading the Shadows.glsllib file, it seems that it detects HARDWARE_SHADOWS to be declared but sampler2DShadow (and maybe all other shadow related types and/or functions) are not defined. Also according to this page OpenGL ES, Android and iOS TODOs · castle-engine/castle-engine Wiki · GitHub there’re not supposed to be defined on openglES20. I’ve not found any other reference

So, I modified Shadows.glsllib file with the following patch to try to solve it:

--- Shadows.glsllib     2018-05-18 15:23:17.339274200 +0200
+++ ./jme3-core/src/main/resources/Common/ShaderLib/Shadows.glsllib     2018-05-18 15:23:37.390448000 +0200
@@ -28,7 +28,10 @@
     #endif
 #else
     #define IVEC2 vec2
-    #ifdef HARDWARE_SHADOWS
+    #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

Depending on the mobile phone (SGS6), now it’s arrising a different shader compilation error:

05-18 13:59:58.620 31543 31561 E com.jme3.app.AndroidHarnessFragment: Grave Exception thrown in Thread[GLThread 11576,5,main]
05-18 13:59:58.620 31543 31561 E com.jme3.app.AndroidHarnessFragment: com.jme3.renderer.RendererException: compile error in: ShaderSource[name=Common/MatDefs/Shadow/PostShadow.frag, defines, type=Fragment, language=GLSL100]
05-18 13:59:58.620 31543 31561 E com.jme3.app.AndroidHarnessFragment: 0:10: P0001: Extension directive must occur before any non-preprocessor tokens

In my xiaomi redmi3s it works.

This can be easily solved just by removing the line “#extension GL_ARB_gpu_shader5 : enable” . I don’t know which problems could generate this change but for android it’s ok and also, this line of code was not executed because it’s set to work at GLSL 100

About shadows, I have other weird issue, depending on the phone, some filters work or not, in SGS6 after removing the extension line, all work but in redmi3 just nearest and bilinear show the shadows properly.

Most of the filters I’ve tried (for example those needing multisampling) by now are failing in SGS6 with the same error (P0001: Extension directive must occur before any non-preprocessor tokens)

I think that some shaders would need a re-writing to be fully compatible with android but I’m not that good at it

That line is essential if the OpenGL core installed in a generic Android device doesn’t support what that extension is supposed to implement. However, as you pointed, It may generate a crash if the extension itself is not supported. Are you sure the phones you used to test are powerful enough to run the shaders you want to use (with decent performances too)?

Yeah android part would need some love…
Your first patch seems good.

The second error is because you have a #extension after non preprocessor directive like #ifdef.
So basically if it was on top… it should work.
Now we get to the weird part, the engine is supposed to collect #extensions lines in the source and put them on top… it seems it obviously fails to do so here…

I’m gonna look into this… though it’s been a crazy long time since I didn’t use android (hence the issues…) so I’ll need you to test.

Ok I found the issue

This adds “precision mediump float;” right after the version

1	#version 150 core
2	precision mediump float;
3	#define FRAGMENT_SHADER 1
4	#define FILTER_MODE 3
5	#define PCFEDGE 1.0
6	#define SHADOWMAP_SIZE 1024.0
7	#define PSSM 1
8	#define BACKFACE_SHADOWS 1
9	    #extension GL_ARB_gpu_shader5 : enable

It’s before the extension, and since it’s not a preprocessor directive, it’ crashes with your error.

I’m gonna dig a bit to see if we can efficiently add it after the #extension stuff.

I pushed a fix Fixes post shadows compilation issue on android · jMonkeyEngine/jmonkeyengine@6b2af99 · GitHub

I also integrated your patch for the Shadows.glsllib
Could you test please?

1 Like

Thanks @nehon for the quick response and push!!! I’m sorry but I’m travelling until next wednesday and as soon as I get back home I’ll try it :wink:

Hi @nehon,

I just tested it. The extension directive error is solved with your patch. About the Shadows.glsllib patch, you changed it in the “VERSION >= 130” section instead of the other section in which I changed it. So it’s still failing with the same exception.

Although it’s easy, here is the patch in case you want to apply it directly:

--- Shadows.glsllib     2018-05-23 11:57:10.006948194 +0200
+++ jme3-core/src/main/resources/Common/ShaderLib/Shadows.glsllib       2018-05-23 10:32:59.480822119 +0200
@@ -31,7 +31,10 @@
     #endif
 #else
     #define IVEC2 vec2
-    #ifdef HARDWARE_SHADOWS
+    #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

I think that this behaviour is weird because both my devices have GLSL higher releases than 1.30 but the shader detects it to lower… According to GLView, my specs are:

  • Samsung galaxy S6 with openGL ES 3.2 with GLSL ES 3.20
  • Xiaomi redmi 3s with openGL ES 3.0 with GLSL ES 3.00

Maybe is jme3 overwritting it to just use basic openGL ES 2.0 and shader level 1.00?

Additionally, for android devices extension GL_EXT_gpu_shader5 or GL_OES_gpu_shader5 (both supported in SGS6 and probably most more modern devices) could be used instead of GL_ARB_gpu_shader5. I’m just asking, I don’t know the differences between them.

Thanks

DOH

Yes that could be the case. As said… Android stuff didn’t have love since a long time… and things move fast on the android mobile front.

Yes, in fact that’s the case, at line 127 of OGLESContext.java :

    // setEGLContextClientVersion must be set before calling setRenderer
    // this means it cannot be set in AndroidConfigChooser (too late)
    view.setEGLContextClientVersion(2);

As my main jme3 based project was intended to be published on android and assuming (as you said) that nowadays there’s noone giving love to android part I’ll be having a deeper look into android code to try to make some improvements on it in my own fork and get back to you with the findings and improvements :wink:

I hope I can help make jme better on android

3 Likes

That would be really great, thanks a lot.

It’s been a year now but I made some efforts on this topic. I added a new post on the contribution depot: