Problems with Performance on Mobile Devices

Hey! I’m Mau, and I’m developing a webpage for a client.
The goal is to make the webpage multiplatform (Desktop and mobile, (IOS, Android, Windows) etc.
We’re using Three.js and REACT.
Right now, the webpage crashes when I try to open it on my phone, and I don’t know if the problem is happening because we’re testing the website on mobile devices that are not powerful enough.
Any ideas on how can I make my code efficient for both desktop and mobile devices?

I’m using planes with a shader, but for it to look good, it needs many vertices, and I know that takes a lot of draw calls. Also, we’re using 1024 px and 2048 px textures. We’re not using any lights and no fog neither. The frustum of the camera is pretty big, and the dimensions of the meshes are also big.

Please take a look at the project.
[https://www.polyhedronuniverse.com/]

Can you please try to replace all custom shaders with a simple unlit material like MeshBasicMaterial? Also use no textures for this test. If the performance gets better, you app is fragment shader bound.

In the next step, try to change your custom shaders so they use no textures. If the performance is still good, your texture resolution is too high. Considering the amount of texture data you are using right now (according to the network tab), I guess this is the root cause for your performance issue.

Besides, you app needs to transfer over 90 MB until it can be started. This is way too much even for a Desktop we application.

1 Like

Thank you so much for the reply. Maybe I should’ve explained more about the shaders. I’m using a RawShaderMaterial that is attached to a THREE.BufferPlaneGeometry.
These are the vertex and fragment shader;

    attribute vec3 position;
    attribute vec2 uv;
    uniform mat4 projectionMatrix;
    uniform mat4 modelViewMatrix;
    uniform mat3 normalMatrix;
    uniform float time;
    uniform vec2 mousePosition;
    varying vec2 vUv;
    varying float vElevation;

    varying float vDisplacement;

    float PI = 3.141592;

    float mod289(float x){return x - floor(x * (1.0 / 289.0)) * 289.0;}
    vec4 mod289(vec4 x){return x - floor(x * (1.0 / 289.0)) * 289.0;}
    vec4 perm(vec4 x){return mod289(((x * 34.0) + 1.0) * x);}

    float rand(vec2 co){
      return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
    }

    float noise(vec3 p){
      vec3 a = floor(p);
      vec3 d = p - a;
      d = d * d * (3.0 - 2.0 * d);

      vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0);
      vec4 k1 = perm(b.xyxy);
      vec4 k2 = perm(k1.xyxy + b.zzww);

      vec4 c = k2 + a.zzzz;
      vec4 k3 = perm(c);
      vec4 k4 = perm(c + 1.0);

      vec4 o1 = fract(k3 * (1.0 / 41.0));
      vec4 o2 = fract(k4 * (1.0 / 41.0));

      vec4 o3 = o2 * d.z + o1 * (1.0 - d.z);
      vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x);

      return o4.y * d.y + o4.x * (1.0 - d.y);
    }

    float fbm(vec2 pos, float t){
      float r;
      r 	= 	noise( vec3( pos, t ) * 01.0 ) * 01.0000;
      r 	+= 	noise( vec3( pos, t ) * 02.0 ) * 00.5000;
      r 	+= 	noise( vec3( pos, t ) * 04.0 ) * 00.2500;
      r 	+= 	noise( vec3( pos, t ) * 08.0 ) * 00.1250;
      r 	+= 	noise( vec3( pos, t ) * 16.0 ) * 00.0625;
      return r / 1.9375;
    }

    void main() {
      vUv = uv;
      float t = time *.3;
      float t2 = time *.1;
      vec2 pos = vUv * 2.0;

      vec2 displacement = vec2(t, t2) + (1.0 + mousePosition * .5);

      float p = fbm( displacement * 2.0 + pos * 2.0, t * 1.1);
      vec2 pos2 = pos + vec2(p);

      float q = fbm( displacement * 3.0 + pos2 * 2.0, t * 1.23);
      vec2 pos3 = pos + vec2(q);

      float r = fbm( displacement * 4.0 + pos3 * 2.0, t * 1.23);
      vec2 pos4 = pos + vec2(r);

      float s = fbm( displacement * 5.0 + pos4 * 2.0, t * 1.32);

      float d = length( vUv - (0.5 + mousePosition));

      float ratioElevation = pow( (1.0 - d), 5.0);

      vElevation = s + .2 + ratioElevation * .2;

      vElevation *= 1.0 - smoothstep(0.0, 1.0, length(uv - .5));


      gl_Position = projectionMatrix * modelViewMatrix * vec4 ( position, 1.0);
    }
precision highp float;

    varying vec2 vUv;
    varying float vElevation;
    uniform float uHue;

    uniform float a;

    float hue2rgb(float f1, float f2, float hue) {
      if (hue < 0.0)
      hue += 1.0;
      else if (hue > 1.0)
      hue -= 1.0;
      float res;
      if ((6.0 * hue) < 1.0)
      res = f1 + (f2 - f1) * 6.0 * hue;
      else if ((2.0 * hue) < 1.0)
      res = f2;
      else if ((3.0 * hue) < 2.0)
      res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;
      else
      res = f1;
      return res;
    }

    vec3 hsl2rgb(vec3 hsl) {
      vec3 rgb;

      if (hsl.y == 0.0) {
        rgb = vec3(hsl.z); // Luminance
      } else {
        float f2;

        if (hsl.z < 0.5)
        f2 = hsl.z * (1.0 + hsl.y);
        else
        f2 = hsl.z + hsl.y - hsl.y * hsl.z;

        float f1 = 2.0 * hsl.z - f2;

        rgb.r = hue2rgb(f1, f2, hsl.x + (1.0/3.0));
        rgb.g = hue2rgb(f1, f2, hsl.x);
        rgb.b = hue2rgb(f1, f2, hsl.x - (1.0/3.0));
      }
      return rgb;
    }

    vec3 hsl2rgb(float h, float s, float l) {
      return hsl2rgb(vec3(h, s, l));
    }

    void main () {
      float hue = uHue + vElevation * .05;
      hue += smoothstep(.6, 1.0, vElevation) * .2;

      float highlight = sin ( smoothstep(.6, .91, vElevation) * 3.14 );

      hue += highlight * .1;

      float saturation = vElevation * 1.1;
      float darkborders = sin(vUv.x * 3.14) * sin(vUv.y * 3.14);
      float brightness = pow( darkborders * a + vElevation, 3.5);
      brightness *= .5 + smoothstep(.6, 1.0, vElevation) * .5;

      brightness += highlight * .2;
      vec3 col = hsl2rgb(hue, saturation, brightness);

      if(brightness < 0.1){
        vec3 col = hsl2rgb(hue, saturation, 1.0-brightness);
        gl_FragColor = vec4(col, 0.0);
      }else if(brightness < 0.13 ){
        vec3 col = hsl2rgb(hue, saturation, .05);
        gl_FragColor = vec4(col, 0.5);
      }
      else{
        vec3 col = hsl2rgb(hue-.01, saturation, brightness);
        gl_FragColor = vec4(col, 1.0);
      }

    }

so for what’s in the planes to look better, it needs a lot of triangles. When I lower that amount of width and height segments and I test it on mobile the performance gets better. The place where I use more textures is on the background of the scene, I already lowered the files sizes, and it just needs to transfer 40 MB (This changes are not yet in the public version).