Note: in case people don’t know… you can also just clone the repo, checkout the branch, and “gradlew install” it… then it will be available in your local maven repo and gradle can refer to the snapshot dependency without hitting the web for it.
For experimental source, sometimes this is better because you can pick and choose when you update.
I would be happy to help integrate occlusion-parallax into jme’s official terrain shaders now that terrains will be a lot more optimized with tile-deferred rendering.
I tried to include the occlusion-parallax when I made the shaders, but ran into some trouble implementing it when only some texture-slots had a parallax map and others didn’t, and it also tanked the framerate with too many texture reads, so I decided to postpone it.
It’s been almost two years since the last time I connected to jme hub and even more since last time I tried to contribute to the engine and the first post shown in the main hub page was this one.
I just read the whole thread and I’m really impressed of the work you’ve doing lately, it’s awesome and I just wanted to say THANK YOU @JhonKkk!!! My game project is still half-implemented and stuck in an old jme3.3 relese, but for sure I’ll have a look at your fork next week and comment back here.
Today I tested some complex PBR scenes on a machine with the following specs:
GPU: 2070
Resolution: 1600*900
Number of lights: 200
Effects: FXAA, Bloom, SSAO, ToneMap and VolumeLightFilter
The test results are as follows:
I am dissatisfied with the test results, because the PointLight radius is very large, so in this case the performance of DeferredShading and TileBasedDeferredShading is close. And I believe that even with so many post-processing effects, this scene should still be able to maintain 100+ fps (I may add Pre-Pass to reduce Overdraw cost and OcclusionCull to cull again before comparing the frame rates of this scene).
(It is worth noting that when I ran it full screen (2k resolution), Forward only had 5 frames, while Deferred and Tile-Based Deferred remained stable at around 70 frames.)
The following is another test scene:
I did a comparison with godot4, here the resolution is 1600*900 for both, with only one DirLight.
Post processing: Shadow, SSAO, ToneMap.
Differences: Light color combination…, Godot uses compressed texture formats.
However, I found the frame rate difference between the two is nearly 140 frames…
There may be some inaccuracies in the tests, but I can roughly guess the reasons: Godot’s compressed textures optimize texture cache (L1 Cache) very well, also Godot has PrePass (which reduces Overdraw, I didn’t enable Godot’s OcclusionCull here), and perhaps some other differences…
Additionally, why doesn’t the SDK’s GLTF importer provide an option to adjust texture filtering by default? I found that many imported GLTFs did not have linear texture filtering enabled, like in the image above - Godot has linear filtering enabled, while the J3O converted from JME3 does not have linear filtering…but nearest neighbor sampling instead…
If I turn off SSAO, JME3’s frame rate gets very close to Godot4, around 270 fps. But strangely Godot4 also has SSAO enabled, could Godot4’s SSAO be more performant?! I will investigate the reasons later. But overall, the following factors affected JME3’s frame rate:
Not using compressed texture formats, unfriendly TextureCache, serious bandwidth overhead (mostly 2k, 1k jpg images)
No PrePass performed to avoid Overdraw
JME3’s SSAO may have inconsistent performance compared to Godot4’s SSAO(But there is no doubt that JME3’s SSAO somehow wasted nearly 120 frames of overhead… )
Jme’s ssao does have to do a normal pre pass, which should not be necessary in a deferred pipeline.
Since it takes such a huge performance hit, what does your new implementation do if all viewport queues are rendered again using a forced technique?
You reminded me that I have not optimized JME’s built-in post-processors yet. I see some depend on the DepthRT, or draw their own NormalRT internally…(SSAO also has one that approximates normals in the FragmentShader directly without depending on the PreNormalPass, but when I compared with Godot the test had PreNormalPass enabled…).
I will add optimizing these built-in post-processors to my optimization checklist, for example when switching to the DeferredPath, directly use GBufferRT2 (NormalRT) as input for SSAO, to prevent SSAO from drawing the scene again…
for me JME one looks better lol - darker and little more realistic due to brick visible seams(ambient shadow/normals), while in godot it looks like diffuse without any normals/etc. idk why. Maybe light setting.
jme:
godot:
idk but especially here JME looks more proper and better. Godot like blender old(not eevee) preview, while jme like blender render lol.
I Belive its about what you said about texture scaling, tho they should load into gpu better quality here, since it looks blurry.
Tho in both cases i feel like there is no anti-aliasing kinda.
btw. great work Jhon
Hope you can solve SSAO frame issue.
It will be almost same framerate already i hope.
This issue is because when the SDK converts gltf to j3o, it does not enable Linear texture filtering, but uses nearest filtering instead. In fact, when you rotate the camera in the game, you will find a lot of flickering in JME (which is because Linear filtering is not enabled). So…Godot enables Linear filtering. Although it looks like block details are smoothed out, there is no massive flickering when the camera rotates.
Here is another comparison image, the first one is nearest filtering, the second one is linear filtering:
With no effects enabled, jme3 and godot render the same scene with similar frame rates on 2070 at 2k resolution. In larger scenes, godot should be faster than jme3 for three main reasons:
C++ (Undoubtedly, C++ is still faster than Java, and C++ has direct access to graphics APIs without JNI overhead)
Godot uses Vulkan (I run it with the Vulkan renderer by default)
Engine internal design (Godot has many things JME doesn’t have, such as Occlusion Culling, Vulkan parallel command drawing, OpenGL indirect drawing, optimized graphics algorithms, etc.)
However, there is nothing to worry about. I remain positive about Jme3 (I’m a senior Unreal Engine graphics programmer myself). Since I haven’t made any AAA-like games or demos with JME3 so far, I can’t tell you the real situation of JME3 in this regard. We just need to make JME3 better, so everyone can have a more enjoyable experience using JME3.
I really hope the SDK can have an option to set default texture filtering mode when converting gltf to j3o. This way I don’t have to traverse all objects in code or manually create Material.j3m for each Geometry to adjust texture filtering mode. Since this scene is very large, traversing all geometries in code may cause slow startup, so I didn’t adjust texture filtering in this test.
I really hope the SDK can have an option to set default texture filtering mode when converting gltf to j3o. This way I don’t have to traverse all objects in code or manually create Material.j3m for each Geometry to adjust texture filtering mode. Since this scene is very large, traversing all geometries in code may cause slow startup, so I didn’t adjust texture filtering in this test.
Hmm, maybe could just temporary replace “loader” for “.gltf” that will be copy of old one, but just setting Texture filtering for each texture. app.getAssetManager().registerLoader(ModifiedGLTFLoader.class, "gltf")
kinda?
Or just edit oryginal one in core, but allow some setting that change behaviour.
which gets very close to Godot in terms of frame rate (JME3 at this point is 270FPS, Godot 298FPS). I guess passing GBufferRT2 (Normals) directly to SSAO would make the frame rate identical to Godot.
Alright, after adjusting SSAO to approximate normal calculation.
GPU device: 2070
Resolution: 1600*900
Post processing: ToneMap, FXAA, SSAO, Bloom, VolumeLight.
Number of lights: 200
Full scene PBR materials.
Finally reached a result I’m satisfied with, which is maintaining around 130FPS :