15

I'm the lead developer for NASA's new gamma-ray constellations page, which is an interactive outreach tool to highlight what the night sky looks like at different wavelengths:

https://fermi.gsfc.nasa.gov/science/constellations/

Screenshot of the gamma-ray constellation page

I used ThreeJS to put together the interactive content and while the page works fine on a modern laptop, I've been seeking ways to improve performance on older devices as well as mobile platforms.

My apologies if this is too broad of a question, but I would appreciate any comments on how to improve the efficiency of ThreeJS in such an application. In particular, I'm curious to hear how experienced ThreeJS coders would potentially consolidate/merge geometries to cut down on CPU/memory overhead. I'm a scientist pulling double duty as a programmer, so any suggestions on how to improve the performance of the current code would be greatly appreciated.

Here's a basic breakdown of how the interactive scene is constructed, but the full code can be found at the link above:

  1. Create and texture a "sky" sphere
  2. Position the camera inside the sphere
  3. Create grid lines along the sphere
  4. Create the optical constellation lines
  5. Create the gamma-ray constellation lines
  6. Create geometries to contain the constellation art
  7. Create transparent click capture geometries to toggle constellation art

The final product has 1083 geometries, 75 textures, 125336 vertices, and 40642 faces. Viewing the page on my 2016 MacBook Pro for a few minutes will heat it up enough to fry an egg. Any suggestions on best practices to make the code more efficient would be appreciated.

7
  • I tried to view the page on my Sony xperia z5 and it is unusable, Things do not fit on the screen as they should and the popup at the start is too large for the screen. Touch events do not work so you cant rotate the scene at all. This probably has something do with the if/else in the code that only adds the Trackball controls for ipad and iphone. Why you have this if/else I don't know as TrackballControls should work fine on all devices. Commented Oct 21, 2018 at 0:07
  • jQuery and jQueryUI are loaded on to the page, but are not really used for anything that isn't easy with standard JS. Personally, I would ditch jquery and jqueryUI. Commented Oct 21, 2018 at 0:10
  • you create a TextureLoader early in your code, but the use the deprecated THREE.ImageUtils instead ??? Commented Oct 21, 2018 at 0:12
  • You are loading many images for the constellations and they all seem to be quite large files, especially considering what they are. For example Coliseum.png is 465KB. Maybe consider optimizing the images, maybe an 8bit .png, or even a .jpg would be better. Commented Oct 21, 2018 at 0:25
  • The file "js/Raleway.typeface.js" is loading many times. Commented Oct 21, 2018 at 0:27

3 Answers 3

11

You are currently rendering the scene 60 times per second. Your biggest improvement in performance should be achieved by rendering only when needed.

For a static scene, you only need to render when the camera moves -- an animation loop is not required.

For example, if you were using OrbitControls to control your camera, you would use this pattern.

var controls = new THREE.OrbitControls( camera, renderer.domElement );

// call this only in static scenes (i.e., if there is no animation loop)
controls.addEventListener( 'change', render ); 

Also, even though you are using TWEEN in your demo, you can instantiate an animation loop only for the duration of the tween by using a pattern like so:

// start animate loop
var id;
animate();

// tween
var time = { t: 0 };
new TWEEN.Tween( time )
    .to( { t : 1 }, 1000 )
    .onStart( function() {
        // custom
    } )
    .onUpdate( function() {
        // custom
    } )
    .onComplete( function() {
        // custom
        cancelAnimationFrame( id );
    } )
    .start();

function animate() {

    id = requestAnimationFrame( animate );

    TWEEN.update();

    render();

}

function render() {

    renderer.render( scene, camera );

}

three.js r.97

Sign up to request clarification or add additional context in comments.

8 Comments

This is a great optimization strategy on its own but i think it may be addressing a different issue. For example, if you don't want to drain your users battery. Without optimizing other stuff you could still experience stutters and lock the rest of the UI.
The user's issue is a hot cpu. I addressed that issue.
I think what I wanted to say is that I don’t know which answer to accept I think they’re both valid.
cancelAnimationFrame( id ); is called in Tween.onComplete().
Sorry, I have no idea what you are doing. I suggest your implement a simple example, show your code, and ask a new question. Study threejs.org/examples/misc_controls_orbit.html. The inline comments show you how to modify the example to work in a static scene. Then try to get tween to work.
|
7

Depending on the view position and angle, your app produces up to 600 draw calls per frame. You can easily see this by typing renderer.info.render in the browser console. A good starting point in context of performance optimization is the reduction of draw calls. You can do this in several ways e.g. by merging multiple geometries into a single one, using instanced rendering or avoiding multi material objects. If your application is CPU bound, reducing draw calls can greatly improve the performance of a 3D application.

Since you are using three.js R84, I suggest you upgrade to the latest version. We implemented this year some performance features like uniform caching or avoid redundant state changes in context of blending. Stuff like that might also have a positive impact on your app's performance.

BTW: There are many interesting discussion about performance optimization in the three.js forum.

Comments

0

The first thing I noticed are grid lines which create 70 draw calls. Then constellations which consist of multiple lines.

For the grid I'd use a custom shader like the one below and make a smaller sphere inside the main one with additive blending https://2pha.com/demos/threejs/shaders/simple_lines.html

For the constellations I'd either use LineSegments or render groups of lines into textures and use these in the scene https://threejsfundamentals.org/threejs/lessons/threejs-rendertargets.html

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.