3

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.

spacorum
  • 495
  • 6
  • 16
  • 1
    With all those requisites (high framerate, high dpi, full-screen, anti-aliasing, stereo view, on 8-year old devices), you shouldn't be using the sky and water shader examples. Those shaders make their calculations in the fragment shader, which means lots of calculations per pixel. You should try using, or writing your own materials that do the "heavy lifting" in the vertex shader, to lighten the GPU load. – M - Feb 06 '19 at 17:34
  • 1
    In fact, the 8-year old mobile gets double framerates than the 3-year old, weird: https://www.notebookcheck.net/Adreno-506-vs-Adreno-330_7443_4683.247598.0.html I understand these can be expensive shaders, but I need them for this app. I would prefer to try changing some parts of the code instead of removing them. Also, this is an VR app, so stereo view and fullscreen are a "must-have", sorry. The same goes for an acceptable framerate, anything below 50fps makes you sick in seconds. I want to tweak current code somehow, maybe rendering shaders in a different scene/renderer, don´t know. – spacorum Feb 06 '19 at 20:40

0 Answers0