I´m developing a mobile VR web-app based on Three.js. To test the app I use two devices:
- Android NEXUS 5 (with Adreno 330), about 8 years old
- Android BQ AQUARIS X (with Adreno 506), about 3 years old
Here´s what I´m using:
GLTF models I load everything in this format, decimating the models when possible. In this app there are about 8 models (a few animals, some buildings, a boat, etc), quite lowpoly, some animated. Nothing special, I got 45-55fps if I only load the models in an empty scene with lights enabled. Similar results with StereoEffect (VR) enabled. No shadows casted.
Textures Every texture used by the GLTF models was previously compressed, which improved loading times. All images resized to power of two. Anyway, the terrain texture is quite big (300kb) and its normal texture even more (700kb). I can´t decrease it anymore or it will lose to much detail.
Materials I process all loaded materials and convert them to MeshLambertMaterial (if possible) and also MeshPhongMaterial.
Lights I use just a couple of lights: Ambient and SpotLight, which it´s used as a sun. No shadows casted (no needed).
Skybox There are two: one for the background (night sky) and one closer, with transparent clouds (autorotating).
Lensflare It´s quite expensive, but the app requires it. I set NoBlending mode in case it´s faster. DepthTest is set to false to avoid artifacts between the clouds. Also, I changed the render order setting of every model involved in the scene to not render before it.
Framerate is acceptable, both in normal mode and VR mode (with StereoEffect).
But when including "advanced" effects, such as sky/sun shader and water shader, framerate goes to hell.
I´m using this two, taken from the examples:
https://threejs.org/examples/webgl_shaders_sky.html
https://threejs.org/examples/webgl_shaders_ocean.html
These are some of the tests I did to improve this:
Shader precision I tried to modify the shaders code, but I simply don´t know what I´m doing (shader language is the hardest one I faced, obviously because of a lack of maths from my part..). I just added "mediump" precision to improve performance, but shader stops working (all black). In the ocean shader something similar happens: light reflects real bad and there´s a big white area where detailed light reflections should be. It looks like both shaders only work in "highp" precision, which makes them run really bad on mobile devices.
Device pixel ratio My laptop gets 1.25dpi and this this is enough even with antialiasing disabled. But mobile devices get 3dpi, which gets nice quality images but it´s really slow on low GPU devices, even more when you enable VR mode and the screen splits in two! I understand that I can limit to 2dpi on mobile devices, which certainly improves framerate, but I would like to avoid it if possible to not lose any quality (which is more noticeable when you look to the screen through some plastic lens on a VR cardboard..).
Antialiasing On the ADRENO506, with antialiasing enabled the framerate drops to 20fps.. and only 10 fps in VR mode. Results improve using FXAA composer, but not too much.
WebGLDeferredRenderer I can see some improvements in the ocean shader. But in the sky/sun shader it still very slow. Does it really worth it here? I thought it would help loading shaders.
Fullscreen The app needs to run fullscreen, but I lose 20fps when enabling it. Is this normal?
More ideas... I think there is something more I could try: to create an additional scene, render the sky and ocean there but with lower resolution, and then (somehow..) integrate it with the first scene where all the models are rendered. I don´t know if this would work, I have serious doubts about lightning, render orders, etc.. But the idea is to render the difficult parts at lower quality, leaving the models with high quality.
Any advice will be appreciated, I´m opened to everything at this point.