jPCT-AE vs. jPCT (and the future of jPCT-AE)

Started by AeroShark333, January 17, 2022, 06:14:21 PM

Previous topic - Next topic

AeroShark333

Hello,

I'm back with some questions I had wondered about for quite some time but never really bothered to ask.
Maybe a few things could be suggestions for the future of jPCT-AE as well...
It's a long list (and I'm not necessarily in a rush/hurry for answers so please take your time...) but anyway, here goes:

1. Why can a Light object only be assigned to one World? As far as I know you can only add a Light to the World using the constructor of Light.
When you look further, World does have the option to remove all lights with World.removeAll() or World.removeAllLights().
But there is no World.addLight(Light light) or World.addLights(Light[] lights) option... ???
In one of my projects, I remember having had 2 Worlds with diffent fogging parameters but same Lights, where I had to declare the 'same' Lights twice.

2. Is there any beneficial multi-threading capabilities jPCT-AE has or could have?
I have tried World.setDefaultThread(...) for instance but I never really understood its purpose entirely in jPCT-AE...
I tried to set it to a "new Thread()" but the application only became slower I believe...
I am not entirely sure if jPCT-AE has any other beneficial multi-threading capabilities (I haven't really found so far)...
I believe OpenGL doesn't entirely allow it anyway. But maybe some non-OpenGL things that jPCT does before rendering could still be done using multi-threading..? Pre-processing or anything like that
I figured that since devices become much better at multi-threading, maybe it would be nice to have some multi-threading options.
I found something interesting in the jPCT documentation: https://www.jpct.net/doc/com/threed/jpct/threading/package-summary.html and https://www.jpct.net/doc/com/threed/jpct/WorldProcessor.html but I haven't found something similar for jPCT-AE.

3. Will ReflectionHelper be ported to jPCT-AE?
I am referring to: https://www.jpct.net/doc/com/threed/jpct/util/ReflectionHelper.html
I believe ShadowHelper has been ported to jPCT-AE at a later stage too but I thought ReflectionHelper would be interesting too.
For mirror-like surfaces I believe it would be nice to have.

4. Will BloomGLProcessor be ported to jPCT-AE?
Here, I am referring to: https://www.jpct.net/doc/com/threed/jpct/procs/BloomGLProcessor.html
I am not sure if it is heavy or something but I thought it would be interesting to have.

5. Why can a VertexController only be assigned to a single mesh?
When you try to apply the same VertexController to another mesh you will get an error like:
"java.lang.RuntimeException: [ 1639357199784 ] - ERROR: This instance has already been assigned to another Mesh!"
I thought that maybe it would work too if the same VertexController was applied to multiple meshes, but I guess not...

6. Why does jPCT-AE use a static TextureManager instance?
I thought it would have made more sense to make a TextureManager per renderer or something
I believe it would be possible to have both too (so even Textures loaded from other renderers are accessible for whatever reason you have...)
With having both I mean that you have a 'TextureManager' per renderer but also still the global static one.

7. Why does jPCT-AE still attempt to draw non-visible polygons?
I believe polygons that are not visible in the scene are still sent to the GPU to 'draw' while they won't really be drawn.
Examples:
- polygons out of the FOV of the camera (or it seems jPCT still processes these unless they have been manually set to Object3D.setVisibility(false).
- polygons out of max fogging distance range.
- also this is not available in jPCT-AE: https://www.jpct.net/doc/com/threed/jpct/Portals.html

8. Is there any other plans for the future of jPCT-AE?
Further development? (implement new techniques and such; better lighting (Phong), more control for lighting (specularity))
Optimizing? (speeding up/improving existing implementations, multi-threading, etc.)
New features? (support for OpenGL3+ (compute shaders or something) or Vulkan or something)
More future-proofing? (I believe some things in jPCT-AE have been made for when Android 2.2/2.3 was more popular; so maybe they need to be reconsidered; think of memory limitations, max. texture size, max. texture stages, Phong shading, loading newer 3D models (other/newer file types), etc.)
Open-sourcing? (on GitHub or something so people can contribute)
Porting from other graphics libraries or jPCT? (some features that are present in other graphics libraries or jPCT but missing in jPCT-AE)

9. Any idea what causes these crashes..?
Most of these are native crashes but they might still point to some clue in the stacktrace (as some refer to the Java code)

signal 11 (SIGSEGV), code 2 (SEGV_ACCERR)
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
pid: 0, tid: 0 >>> com.aeroshark333.artofearthify <<<

backtrace:
  #00  pc 000000000001706c  /vendor/lib64/libsrv_um.so
  #00  pc 00000000000cc808  /vendor/lib64/egl/libGLESv2_mtk.so
  #00  pc 000000000002dcc4  /vendor/lib64/egl/libGLESv2_mtk.so
  #00  pc 0000000000031fb0  /vendor/lib64/egl/libGLESv2_mtk.so
  #00  pc 000000000002c4c8  /vendor/lib64/egl/libGLESv2_mtk.so
  #00  pc 000000000002bf24  /vendor/lib64/egl/libGLESv2_mtk.so (glDrawElements+120)
  #00  pc 00000000000e7e1c  /system/lib64/libandroid_runtime.so (android_glDrawElements__IIILjava_nio_Buffer_2(_JNIEnv*, _jobject*, int, int, int, _jobject*)+276)
  #00  pc 00000000002d3504  /system/framework/arm64/boot-framework.oat (art_jni_trampoline+196)
  #00  pc 00000000020072fc  /memfd:/jit-cache (com.threed.jpct.GL20.glDrawElements+60)
  #00  pc 0000000002020fc0  /memfd:/jit-cache (com.threed.jpct.CompiledInstance.render+11664)
  #00  pc 000000000203cc88  /memfd:/jit-cache (com.threed.jpct.GLRenderer.drawVertexArray+2088)
  #00  pc 0000000002047390  /memfd:/jit-cache (com.threed.jpct.World.draw+704)
  #00  pc 000000000204a11c  /memfd:/jit-cache (com.threed.jpct.World.draw+60)
  #00  pc 0000000002018c28  /memfd:/jit-cache (com.aeroshark333.artofearthify.lw.ArtOfEarthify.onDrawFrame+9096)
  #00  pc 0000000000137334  /apex/com.android.runtime/lib64/libart.so (art_quick_invoke_stub+548)
  #00  pc 00000000001460ac  /apex/com.android.runtime/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+244)
  #00  pc 00000000002e3758  /apex/com.android.runtime/lib64/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+384)
  #00  pc 00000000002de7e4  /apex/com.android.runtime/lib64/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+900)
  #00  pc 00000000005a8a8c  /apex/com.android.runtime/lib64/libart.so (MterpInvokeVirtualQuick+596)
  #00  pc 0000000000135594  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_virtual_quick+20)
  #00  pc 000000000022cd84  /data/app/com.aeroshark333.artofearthify-yaNv3ycyylpEX_4FbNxKmA==/oat/arm64/base.vdex (com.aeroshark333.artofearthify.lw.LiveWallpaperRenderer.onDrawFrame+4)
  #00  pc 00000000005a4364  /apex/com.android.runtime/lib64/libart.so (MterpInvokeInterface+1740)
  #00  pc 0000000000131a14  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_interface+20)
  #00  pc 00000000002f475c  /system/framework/framework.jar (android.opengl.GLSurfaceView$GLThread.guardedRun+2068)
  #00  pc 00000000005a4f00  /apex/com.android.runtime/lib64/libart.so (MterpInvokeDirect+1168)
  #00  pc 0000000000131914  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_direct+20)
  #00  pc 00000000002f5152  /system/framework/framework.jar (android.opengl.GLSurfaceView$GLThread.run+114)
  #00  pc 00000000002b4088  /apex/com.android.runtime/lib64/libart.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.13310094408155829753)+240)
  #00  pc 0000000000593d00  /apex/com.android.runtime/lib64/libart.so (artQuickToInterpreterBridge+1024)
  #00  pc 0000000000140468  /apex/com.android.runtime/lib64/libart.so (art_quick_to_interpreter_bridge+88)
  #00  pc 0000000000137334  /apex/com.android.runtime/lib64/libart.so (art_quick_invoke_stub+548)
  #00  pc 00000000001460ac  /apex/com.android.runtime/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+244)
  #00  pc 00000000004b2da0  /apex/com.android.runtime/lib64/libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*)+104)
  #00  pc 00000000004b3e50  /apex/com.android.runtime/lib64/libart.so (art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, jvalue const*)+416)
  #00  pc 00000000004f43a8  /apex/com.android.runtime/lib64/libart.so (art::Thread::CreateCallback(void*)+1176)
  #00  pc 00000000000e5614  /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+36)
  #00  pc 0000000000085458  /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64)



signal 11 (SIGSEGV), code 2 (SEGV_ACCERR)
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
pid: 0, tid: 0 >>> com.aeroshark333.artofearthify <<<

backtrace:
  #00  pc 000000000001706c  /vendor/lib64/libsrv_um.so
  #00  pc 00000000000ce0d8  /vendor/lib64/egl/libGLESv2_mtk.so
  #00  pc 000000000002e2cc  /vendor/lib64/egl/libGLESv2_mtk.so
  #00  pc 000000000003264c  /vendor/lib64/egl/libGLESv2_mtk.so
  #00  pc 000000000002ca84  /vendor/lib64/egl/libGLESv2_mtk.so
  #00  pc 000000000002c4dc  /vendor/lib64/egl/libGLESv2_mtk.so (glDrawElements+120)
  #00  pc 0000000000079d38  /vendor/lib64/egl/libGLES_meow.so
  #00  pc 00000000000e6cac  /system/lib64/libandroid_runtime.so (android_glDrawElements__IIILjava_nio_Buffer_2(_JNIEnv*, _jobject*, int, int, int, _jobject*)+276)
  #00  pc 00000000002ca994  /system/framework/arm64/boot-framework.oat (art_jni_trampoline+196)
  #00  pc 0000000000088d88  /data/app/com.aeroshark333.artofearthify-qsfIgfJfssMx7-jwHqMHFA==/oat/arm64/base.odex (com.threed.jpct.GL20.glDrawElements+72)
  #00  pc 0000000000064158  /data/app/com.aeroshark333.artofearthify-qsfIgfJfssMx7-jwHqMHFA==/oat/arm64/base.odex (com.threed.jpct.CompiledInstance.render+12008)
  #00  pc 000000000006cf88  /data/app/com.aeroshark333.artofearthify-qsfIgfJfssMx7-jwHqMHFA==/oat/arm64/base.odex (com.threed.jpct.GLRenderer.drawVertexArray+2264)
  #00  pc 000000000007f18c  /data/app/com.aeroshark333.artofearthify-qsfIgfJfssMx7-jwHqMHFA==/oat/arm64/base.odex (com.threed.jpct.World.draw+844)
  #00  pc 000000000007fc10  /data/app/com.aeroshark333.artofearthify-qsfIgfJfssMx7-jwHqMHFA==/oat/arm64/base.odex (com.threed.jpct.World.draw+64)
  #00  pc 0000000000051178  /data/app/com.aeroshark333.artofearthify-qsfIgfJfssMx7-jwHqMHFA==/oat/arm64/base.odex (com.aeroshark333.artofearthify.lw.ArtOfEarthify.onDrawFrame+9240)
  #00  pc 0000000000056930  /data/app/com.aeroshark333.artofearthify-qsfIgfJfssMx7-jwHqMHFA==/oat/arm64/base.odex (com.aeroshark333.artofearthify.lw.LiveWallpaperRenderer.onDrawFrame+64)
  #00  pc 0000000002006824  /memfd:/jit-cache (android.opengl.GLSurfaceView$GLThread.guardedRun+6852)
  #00  pc 0000000000137334  /apex/com.android.runtime/lib64/libart.so (art_quick_invoke_stub+548)
  #00  pc 00000000001460ac  /apex/com.android.runtime/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+244)
  #00  pc 00000000002e3c38  /apex/com.android.runtime/lib64/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+384)
  #00  pc 00000000002decc4  /apex/com.android.runtime/lib64/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+900)
  #00  pc 00000000005a4a40  /apex/com.android.runtime/lib64/libart.so (MterpInvokeDirect+400)
  #00  pc 0000000000131914  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_direct+20)
  #00  pc 00000000002d79b6  /system/framework/framework.jar (android.opengl.GLSurfaceView$GLThread.run+114)
  #00  pc 00000000002b4568  /apex/com.android.runtime/lib64/libart.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.14186875840613789731)+240)
  #00  pc 0000000000593b40  /apex/com.android.runtime/lib64/libart.so (artQuickToInterpreterBridge+1024)
  #00  pc 0000000000140468  /apex/com.android.runtime/lib64/libart.so (art_quick_to_interpreter_bridge+88)
  #00  pc 0000000000137334  /apex/com.android.runtime/lib64/libart.so (art_quick_invoke_stub+548)
  #00  pc 00000000001460ac  /apex/com.android.runtime/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+244)
  #00  pc 00000000004b2898  /apex/com.android.runtime/lib64/libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*)+104)
  #00  pc 00000000004b3948  /apex/com.android.runtime/lib64/libart.so (art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, jvalue const*)+416)
  #00  pc 00000000004f3e98  /apex/com.android.runtime/lib64/libart.so (art::Thread::CreateCallback(void*)+1176)
  #00  pc 00000000000e2364  /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+36)
  #00  pc 0000000000083d98  /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64)



signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
pid: 0, tid: 0 >>> com.aeroshark333.artofearthify <<<

backtrace:
  #00  pc 0000000000019164  /system/lib/libc.so (memcpy+96)
  #00  pc 00000000000b37db  /vendor/lib/libgsl.so (ioctl_kgsl_sharedmem_write+114)
  #00  pc 00000000000f99b3  /vendor/lib/egl/libRBGLESv2_adreno.so (rb_vbo_cache_vertex_attrib+278)
  #00  pc 000000000006a97d  /vendor/lib/egl/libRBGLESv2_adreno.so (cache_vertex_array+1396)
  #00  pc 000000000006b643  /vendor/lib/egl/libRBGLESv2_adreno.so (cache_vertex_elements+3162)
  #00  pc 0000000000074bfd  /vendor/lib/egl/libRBGLESv2_adreno.so (core_glDrawElementsInstancedXXX+984)
  #00  pc 00000000000752bd  /vendor/lib/egl/libRBGLESv2_adreno.so (core_glDrawElements+20)
  #00  pc 0000000000052a51  /vendor/lib/egl/libRBGLESv2_adreno.so (glDrawElements+72)
  #00  pc 0000000000d6352b  /system/framework/arm/boot-framework.oat (offset 0x637000) (android.opengl.GLES10.glClearColorx [DEDUPED]+122)
  #00  pc 0000000000012c37  /dev/ashmem/dalvik-jit-code-cache_12126_12126 (deleted)



signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
pid: 0, tid: 0 >>> com.aeroshark333.artofearthify <<<

backtrace:
  #00  pc 0000000000018da0  /system/lib/libc.so (memcpy+100)
  #00  pc 0000000000093e03  /vendor/lib/egl/libGLESv2_mtk.so
  #00  pc 000000000001c137  /vendor/lib/egl/libGLESv2_mtk.so
  #00  pc 000000000001f1c7  /vendor/lib/egl/libGLESv2_mtk.so
  #00  pc 000000000001af75  /vendor/lib/egl/libGLESv2_mtk.so
  #00  pc 000000000001aabf  /vendor/lib/egl/libGLESv2_mtk.so (glDrawElements+54)
  #00  pc 000000000008441d  /system/lib/libandroid_runtime.so (android_glDrawElements__IIILjava_nio_Buffer_2(_JNIEnv*, _jobject*, int, int, int, _jobject*)+116)
  #00  pc 0000000000a09d75  /system/framework/arm/boot-framework.oat (offset 0x5ea000) (android.graphics.Color.nativeRGBToHSV [DEDUPED]+140)
  #00  pc 00000000000102f7  /dev/ashmem/dalvik-jit-code-cache (deleted)


java.lang.RuntimeException:
  at com.threed.jpct.Logger.log (Logger.java:206)
  at com.threed.jpct.GL20.checkFrameBufferObject (GL20.java:2100)
  at com.threed.jpct.GL20.setRenderTarget (GL20.java:2060)
  at com.threed.jpct.GLRenderer.setRenderTarget (GLRenderer.java:2179)
  at com.threed.jpct.FrameBuffer.setRenderTarget (FrameBuffer.java:287)
  at com.threed.jpct.FrameBuffer.setRenderTarget (FrameBuffer.java:249)
  at com.aeroshark333.blackhole3d.BlackHole3D.onDrawFrame (BlackHole3D.java:415)
  at com.aeroshark333.blackhole3d.livewallpaper.LiveWallpaperRenderer.onDrawFrame (LiveWallpaperRenderer.java:83)
  at android.opengl.GLSurfaceView$GLThread.guardedRun (GLSurfaceView.java:1591)
  at android.opengl.GLSurfaceView$GLThread.run (GLSurfaceView.java:1286)


I guess this is all I have to ask for now. Looking forward to your reply!

Cheers,
Abiram

EgonOlsen

That's quite a lot to answer... ;) I'll do my very best...

On a general note: The basic "design" of jPCT is almost 23 years old now. That alone explains a lot and I'll refer to this as an excuse explaination in the latter. This will become more clear once I manage to reply to the "jPCT origins thread"...

Anyway, here we go...

Quote1. Why can a Light object only be assigned to one World? As far as I know you can only add a Light to the World using the constructor of Light.
That's because I was stupid/lazy when doing the light implemention in the early days of jPCT. I simply coded the lights to be part of the world in a way that they are bound to it, because of...reasons...I guess. I didn't change that, when I released jPCT to the public after doing some cleanup work. However, I then added the Light class to hide this to a degree. See the documention of the Light class for desktop jPCT, which also tries to explain this. When converting jPCT to jPCT-AE, I kept this behaviour for compatibility reasons, but I tried to hide the actual implementation completely by solely relying on the Light class and removing all light related methods from World...except for removeAllLights(). I kept this, because I had to give the user at least some way to remove the lights from a World instance that he actually never attached to it directly. Yes, this all sucks...but that's the way it is now and it will stay this way.

Quote2. Is there any beneficial multi-threading capabilities jPCT-AE has or could have?
No, there isn't. OpenGL is a state machine. It can't handle multiple threads. You could do the processing in multiple threads, of course. But in almost all cases, it's not worth it for what you do with such an engine like jPCT. The desktop version supports multiple threads for the software renderer (which really helps a lot) and for the processing (via the WorldProcessor), which isn't worth it expect in some rare and almost artifical cases. Also, jPCT isn't thread-safe and jPCT-AE is even less thread-safe. The reason for the latter is, again, history. When I started jPCT-AE in 2008, Android used the Dalvik-VM on single core processors running at around 800Mhz. The VM had no JIT, a maximum ram size of 24mb and only a stop-the-world-garbage collector. Which was very slow as well. That meant that garbage collection took somewhere between 80 and 500ms once triggered. And that meant, that the usual game loop when using jPCT-AE wasn't allowed to produce any garbage at all, or the application would have suffered greatly from stuttering. To achieve that, I added some static "caches" if you will call them that. Variables and instance pools, that could be reused instead of created/destroyed each time you called the method. But this, of course, limits the ability to multi-thread even more.
If you abstract your game logic/entities from jPCT's objects and couple jPCT loosly to render your entities, then you have more options to multi-thread things on your own. I did this for the grass rendering in Naroth...turns out, it wasn't worth it, so I disabled it ;)

Quote3. Will ReflectionHelper be ported to jPCT-AE?
Not very likely. OpenGL ES doesn't support some functions (clipping plane related IIRC) that this implementation is using in desktop jPCT. You would have to do in a shader yourself but that would make the default shaders overly complicated, so I didn't do that. It's just a helper class anyway. It's not part of the core.

Quote4. Will BloomGLProcessor be ported to jPCT-AE?
Again, no. This thing is more of a hack anyway. It requires huge amounts of fillrate, which still isn't there on mobile.

Quote5. Why can a VertexController only be assigned to a single mesh?
Because the GenericVertexController implementation stores some mesh related data on initialization.

Quote6. Why does jPCT-AE use a static TextureManager instance?
Again, it's a design decision that I made over 20 years ago. However, I think it's still fine (unlike the lights...). I see it as a pool for textures that each class can easily access without the need to pass instances around. I fail to see the benefit of having multiple texture pools in an app.

Quote7. Why does jPCT-AE still attempt to draw non-visible polygons?
Because it has to. It culls away objects on all six planes, but you can't cull single polygons that are part of a single mesh. OpenGL is most efficient when rendering large batches of polygons, not single ones. The per-polygon culling happens later on the GPU. That said, desktop jPCT culls single polygons when using the software renderer or the hybrid hardware rendering mode (i.e. the one without compiled objects), but both aren't feasible on mobile. I didn't port Portals, because it requires some preconditions that usually aren't met in most scenes and it greatly simplified the port to leave them out. Nobody ever used them anyway except me in one single demo application. Portals were all the rage when I started with jPCT, but given their limitations and the fact that we went from software to hardware rendering, their significance faded.

Quote8. Is there any other plans for the future of jPCT-AE?
I'll continue to support it, fix problems and maybe add some things if people need them, but I haven't got a big plan for it apart from that. The default lighting model will stay like it is. If you need more complex lighting, then write your own shaders. Naroth for example uses a lot of custom shaders for texture splatting, foilage, phong shading, dynamic recoloring of textures, parallax mapping in dungeons etc. I can't possibly cover all these things in a way that they will still work with the given lighting model.
I once looked into Vulkan, laughed and never looked at it again. It's completely low level. Don't get me wrong, I like my low level stuff as much as the next guy. After all, I'm still coding in assembly language for old 8-bit computers. But to support Vulkan, one would have to implement a new library of functions that would map what jPCT-AE needs to Vulkan calls. And I really don't see the point of this. Draw call performance isn't an issue for an app running in a VM on Android.
Regarding open source: I usually open source all of my stuff (https://github.com/EgonOlsen71/), but jPCT. Mainly because I don't feel comfortable without some major rewrite of some parts (like the lights... ;) ) on the one hand but I can't be bothered to do this on the other hand.

Quote9. Any idea what causes these crashes..?
No. I see similar crashes every now and then in my own developer console as well but I don't know what causes them. I've never experienced anything like this in all my testings on all of my devices...not once. I checked some code paths in the engine at least a dozen times without finding any issue, so I doubt that it's that. Might be driver problems or problems when an app returns from sleep or when a context change goes wrong...I really don't know, I'm just guessing widely here.




AeroShark333

#2
Quote from: EgonOlsen on January 18, 2022, 05:38:32 PM
That's quite a lot to answer... ;) I'll do my very best...
Hehe... Thanks for answering, and so extensively too!

Quote from: EgonOlsen on January 18, 2022, 05:38:32 PM
On a general note: The basic "design" of jPCT is almost 23 years old now. That alone explains a lot and I'll refer to this as an excuse explaination in the latter. This will become more clear once I manage to reply to the "jPCT origins thread"...
I never knew jPCT was that old... That's nearly my age :o
Getting more curious about the ' jPCT origins thread' now

Quote from: EgonOlsen on January 18, 2022, 05:38:32 PM
Quote1. Why can a Light object only be assigned to one World? As far as I know you can only add a Light to the World using the constructor of Light.
That's because I was stupid/lazy when doing the light implemention in the early days of jPCT. I simply coded the lights to be part of the world in a way that they are bound to it, because of...reasons...I guess. I didn't change that, when I released jPCT to the public after doing some cleanup work. However, I then added the Light class to hide this to a degree. See the documention of the Light class for desktop jPCT, which also tries to explain this. When converting jPCT to jPCT-AE, I kept this behaviour for compatibility reasons, but I tried to hide the actual implementation completely by solely relying on the Light class and removing all light related methods from World...except for removeAllLights(). I kept this, because I had to give the user at least some way to remove the lights from a World instance that he actually never attached to it directly. Yes, this all sucks...but that's the way it is now and it will stay this way.
Hmmm, okay... Is there a possibility to still add some more control for lighting?
I believe there's variables/attributes passed to the shader that are more or less unused or unchangable?
At least, I haven't found a way to change the specularColor for instance.

Quote from: EgonOlsen on January 18, 2022, 05:38:32 PM
Quote2. Is there any beneficial multi-threading capabilities jPCT-AE has or could have?
No, there isn't. OpenGL is a state machine. It can't handle multiple threads. You could do the processing in multiple threads, of course. But in almost all cases, it's not worth it for what you do with such an engine like jPCT. The desktop version supports multiple threads for the software renderer (which really helps a lot) and for the processing (via the WorldProcessor), which isn't worth it expect in some rare and almost artifical cases. Also, jPCT isn't thread-safe and jPCT-AE is even less thread-safe. The reason for the latter is, again, history. When I started jPCT-AE in 2008, Android used the Dalvik-VM on single core processors running at around 800Mhz. The VM had no JIT, a maximum ram size of 24mb and only a stop-the-world-garbage collector. Which was very slow as well. That meant that garbage collection took somewhere between 80 and 500ms once triggered. And that meant, that the usual game loop when using jPCT-AE wasn't allowed to produce any garbage at all, or the application would have suffered greatly from stuttering. To achieve that, I added some static "caches" if you will call them that. Variables and instance pools, that could be reused instead of created/destroyed each time you called the method. But this, of course, limits the ability to multi-thread even more.
If you abstract your game logic/entities from jPCT's objects and couple jPCT loosly to render your entities, then you have more options to multi-thread things on your own. I did this for the grass rendering in Naroth...turns out, it wasn't worth it, so I disabled it ;)
Hmmm, okay... fair enough.
Is https://www.jpct.net/jpct-ae/doc/com/threed/jpct/World.html#setDefaultThread-java.lang.Thread- useful in some scenarios?

Quote from: EgonOlsen on January 18, 2022, 05:38:32 PM
Quote3. Will ReflectionHelper be ported to jPCT-AE?
Not very likely. OpenGL ES doesn't support some functions (clipping plane related IIRC) that this implementation is using in desktop jPCT. You would have to do in a shader yourself but that would make the default shaders overly complicated, so I didn't do that. It's just a helper class anyway. It's not part of the core.
Hmmm, okay... I thought because the ShadowHelper was ported, maybe it was possible with the ReflectionHelper as well...
I might try something myself if I find the time for it...

Quote from: EgonOlsen on January 18, 2022, 05:38:32 PM
Quote4. Will BloomGLProcessor be ported to jPCT-AE?
Again, no. This thing is more of a hack anyway. It requires huge amounts of fillrate, which still isn't there on mobile.
Okay, I guess there's other ways to create a bloom shader/post-processor.
I was thinking to render the scene (with lightsources only/or filtering the bright areas afterwards) to a lower-resolution RenderTexture.
Then blitting it additively to the scene with linear filtering (for some blur effect)... I'm not entirely sure if it's all possible like this but yeah...
Otherwise I'd need a one-pass/two-pass Gaussian filter or something...

Quote from: EgonOlsen on January 18, 2022, 05:38:32 PM
Quote5. Why can a VertexController only be assigned to a single mesh?
Because the GenericVertexController implementation stores some mesh related data on initialization.
Okay, I guess that makes sense.

Quote from: EgonOlsen on January 18, 2022, 05:38:32 PM
Quote6. Why does jPCT-AE use a static TextureManager instance?
Again, it's a design decision that I made over 20 years ago. However, I think it's still fine (unlike the lights...). I see it as a pool for textures that each class can easily access without the need to pass instances around. I fail to see the benefit of having multiple texture pools in an app.
Hmmm, I usually add textures with a renderer-ID as suffix in the texture-name to the texturemanager to seperature textures per renderer (so they don't get overriden).
I have only found it a bit more troublesome with imported Object3D's from model files with predefined texturenames (these might conflict/override with different renderers instances).
At the moment, I read the mat-files and change the file-names of the textures so they stay 'unique'...

Quote from: EgonOlsen on January 18, 2022, 05:38:32 PM
Quote7. Why does jPCT-AE still attempt to draw non-visible polygons?
Because it has to. It culls away objects on all six planes, but you can't cull single polygons that are part of a single mesh. OpenGL is most efficient when rendering large batches of polygons, not single ones. The per-polygon culling happens later on the GPU. That said, desktop jPCT culls single polygons when using the software renderer or the hybrid hardware rendering mode (i.e. the one without compiled objects), but both aren't feasible on mobile. I didn't port Portals, because it requires some preconditions that usually aren't met in most scenes and it greatly simplified the port to leave them out. Nobody ever used them anyway except me in one single demo application. Portals were all the rage when I started with jPCT, but given their limitations and the fact that we went from software to hardware rendering, their significance faded.
Hmmm, okay I guess portals aren't so necessary then...
What about meshes that are well outside of the fogging parameters (too far away), these are still 'visible' it seems...
Would it be better to clip the farPlane then or to manually set these 'out of range' Object3D's visibility to false?

Quote from: EgonOlsen on January 18, 2022, 05:38:32 PM
Quote8. Is there any other plans for the future of jPCT-AE?
I'll continue to support it, fix problems and maybe add some things if people need them, but I haven't got a big plan for it apart from that. The default lighting model will stay like it is. If you need more complex lighting, then write your own shaders. Naroth for example uses a lot of custom shaders for texture splatting, foilage, phong shading, dynamic recoloring of textures, parallax mapping in dungeons etc. I can't possibly cover all these things in a way that they will still work with the given lighting model.
I once looked into Vulkan, laughed and never looked at it again. It's completely low level. Don't get me wrong, I like my low level stuff as much as the next guy. After all, I'm still coding in assembly language for old 8-bit computers. But to support Vulkan, one would have to implement a new library of functions that would map what jPCT-AE needs to Vulkan calls. And I really don't see the point of this. Draw call performance isn't an issue for an app running in a VM on Android.
Regarding open source: I usually open source all of my stuff (https://github.com/EgonOlsen71/), but jPCT. Mainly because I don't feel comfortable without some major rewrite of some parts (like the lights... ;) ) on the one hand but I can't be bothered to do this on the other hand.
Okay, that seems fine. I guess I will write some default Phong shading shader or something at some point...
I took a look, it seems you're a lot into retro devices/development (such as for C64 or something); an OpenGL graphics library seems something completely different, however..? I mean compared to your other work which is open sourced...

Quote from: EgonOlsen on January 18, 2022, 05:38:32 PM
Quote9. Any idea what causes these crashes..?
No. I see similar crashes every now and then in my own developer console as well but I don't know what causes them. I've never experienced anything like this in all my testings on all of my devices...not once. I checked some code paths in the engine at least a dozen times without finding any issue, so I doubt that it's that. Might be driver problems or problems when an app returns from sleep or when a context change goes wrong...I really don't know, I'm just guessing widely here.
Hmmm, okay... I guess, I feel pretty clueless about these SIGSEGV errors... I don't know what causes it, nor when it happens nor what could possibly fix it.
What about the last stacktrace? That one is from Java (non-native), but it's out of my scope kinda I guess...

EgonOlsen

QuoteHmmm, okay... Is there a possibility to still add some more control for lighting?
I believe there's variables/attributes passed to the shader that are more or less unused or unchangable?
At least, I haven't found a way to change the specularColor for instance.

There isn't, because specular reflection is just a variant/addition to normal lighting. It's based on the same light sources. If you need something different, you can always set your own uniforms and/or attributes to a custom shader and do whatever you want with it.

QuoteWhat about meshes that are well outside of the fogging parameters (too far away), these are still 'visible' it seems...
Would it be better to clip the farPlane then or to manually set these 'out of range' Object3D's visibility to false?
Everything behind the far clipping plane won't be rendered. If the fog is much nearer than the far clipping plane is, it might be a good idea to adjust the far plane.

What about the last stacktrace? That one is from Java (non-native), but it's out of my scope kinda I guess...

It's a check for frame buffer completeness...no idea, why it shouldn't be complete, though. Might be a driver issues or something with the context. My gut feeling is, that a lot of these errors happens on context changes and are actually hidden from the user, they don't happen during normal operation but then the user...I don't know...rotates the phone while switching it off or something...putting it into some state, from which it can't really recover properly. But that's just a guess based on the fact that personally, I've never seen such an exception on my own devices.


private void checkFrameBufferObject() {
int state = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
switch (state) {
case GLES20.GL_FRAMEBUFFER_COMPLETE:
break;
case GLES20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
Logger.log("FrameBuffer: " + fbo + " has caused a GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT exception", Logger.ERROR);
break;
case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
Logger.log("FrameBuffer: " + fbo + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT exception", Logger.ERROR);
break;
case GLES20.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
Logger.log("FrameBuffer: " + fbo + ", has caused a GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS exception", Logger.ERROR);
break;
default:
Logger.log("Unexpected reply from glCheckFramebufferStatus: " + state, Logger.ERROR);
break;
}
if (state != GLES20.GL_FRAMEBUFFER_COMPLETE) {
fbo = -1;
}
}


EgonOlsen

QuoteIs https://www.jpct.net/jpct-ae/doc/com/threed/jpct/World.html#setDefaultThread-java.lang.Thread- useful in some scenarios?

Not very likely. jPCT-AE sets is automatically to the main thread (i.e. the thread that created the world instance). If it's set to the wrong thread, all that happens is that more garbage objects will be created. There's no performance benefit in setting it to some other thread except if that thread is the actual thread that does the calculations.

Windmiller

Hi

About multithreading; I am using threading in this manner..

Thread 1: Calculating half of everything that is not graphics, but only the parts of graphics for flagging if objects should be visible or not.
Thread 2: Calculating the other half of everything that is not graphics, but only the parts of graphics for flagging if objects should be visible or not.
Thread 3: Checking what 3D objects that are flagged to be loaded and do that with the Loader.
JPCT-AE: The jpct´s graphics thread, displaying all the objects that should be visible, if flagged that they should not be visible it removes them.
Firebase: The Firebase real time database thread, storing and loading from the database.

I am creating a big multiplayer space game with over 200 planets that you can dock at and walk around, build stuff, dimensions that brings the players to mazes where they can find things they´ll need and hide things by building blocks around them. This method was the only way to use several threads, and it even runs on crappy phones too because of the way things are loaded, unloaded and removed from visible depending on where the player is in the world.

More multithreading than this is not needed, it will only complex things for you and might even slow things down.
That is my point of view.


AeroShark333

Thanks for the replies... (I haven't been actively programming lately due to broken PC so excuse me for the late reply)

Quote from: EgonOlsen on January 25, 2022, 08:47:54 AM
QuoteIs https://www.jpct.net/jpct-ae/doc/com/threed/jpct/World.html#setDefaultThread-java.lang.Thread- useful in some scenarios?

Not very likely. jPCT-AE sets is automatically to the main thread (i.e. the thread that created the world instance). If it's set to the wrong thread, all that happens is that more garbage objects will be created. There's no performance benefit in setting it to some other thread except if that thread is the actual thread that does the calculations.
Okay, I guess it is best then to leave it untouched...

Quote from: Windmiller on January 29, 2022, 10:55:51 AM
Hi

About multithreading; I am using threading in this manner..

Thread 1: Calculating half of everything that is not graphics, but only the parts of graphics for flagging if objects should be visible or not.
Thread 2: Calculating the other half of everything that is not graphics, but only the parts of graphics for flagging if objects should be visible or not.
Thread 3: Checking what 3D objects that are flagged to be loaded and do that with the Loader.
JPCT-AE: The jpct´s graphics thread, displaying all the objects that should be visible, if flagged that they should not be visible it removes them.
Firebase: The Firebase real time database thread, storing and loading from the database.

I am creating a big multiplayer space game with over 200 planets that you can dock at and walk around, build stuff, dimensions that brings the players to mazes where they can find things they´ll need and hide things by building blocks around them. This method was the only way to use several threads, and it even runs on crappy phones too because of the way things are loaded, unloaded and removed from visible depending on where the player is in the world.

More multithreading than this is not needed, it will only complex things for you and might even slow things down.
That is my point of view.
Hmmm okay, interesting... so far I have only used multi-threading for texture loading (as it can be very blocking process on the GL-thread from my experience).
I believe it would be good to try using multi-threading more to offload processing but I'm afraid to break something, to have dead-locks, and to get other synchronization issues so that has made me hold back a little.

Thanks both for the replies still