· Create the world is committed to creating the first “cloud CAD” collaborative design platform integrating viewing, modeling, assembly and rendering in China.

At the request of readers, we hope to set up a professional WEBGL and Threejs industry QQ communication group for front-end developers in Chengdu-Chongqing area to facilitate discussion. There are webGL and Threejs in the group, welcome to join! — Click the link to join the group chat [three.js/ webGL Chongqing Union Group] : jq.qq.com/?_wv=1027&k…

According to the need to load

In three.js they set up something like a requestAnimationFrame loop or rAF loop

   function render() {... requestAnimationFrame(render); } requestAnimationFrame(render);Copy the code

That makes sense for things that animate, but what about things that don’t animate? In this case, continuous rendering wastes device power and, if the user is using a portable device, the user’s battery.

The most obvious way to solve this problem is to render once at the beginning, and then render only when changes occur. Changes include the final loaded texture or model, data from some external source, user adjustments to Settings, or other relevant input provided by the camera.

First, let’s add the controller, OrbitControls, so that we can respond to something that can be changed.


   import * as THREE from './resources/three/r132/build/three.module.js';

   import {OrbitControls} from './resources/threejs/r132/examples/jsm/controls/OrbitControls.js';

Copy the code

And set them


   const fov = 75;

   const aspect = 2; // Canvas defaults

   const near = 0.1;

   const far = 5;

   const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);

   camera.position.z = 2;

    

   const controls = new OrbitControls(camera, canvas);

   controls.target.set(0.0.0);

   controls.update();

Copy the code

Since we will no longer animate the cubes, we no longer need to track them


   makeInstance(geometry, 0x44aa88.0);

   makeInstance(geometry, 0x8844aa, -2);

   makeInstance(geometry, 0xaa8844.2);

Copy the code

We can remove the animation cube code and call requestAnimationFrame


function render() {

   if (resizeRendererToDisplaySize(renderer)) {

       const canvas = renderer.domElement;

       camera.aspect = canvas.clientWidth / canvas.clientHeight;

       camera.updateProjectionMatrix();
   }

   renderer.render(scene, camera);

}

Copy the code

We need to render OrbitControls at any time to change the camera Settings. Fortunately, OrbitControls will schedule an event whenever something changes.


   controls.addEventListener('change', render);

Copy the code

We also need to deal with the user resizing the window. This was previously handled automatically because we render continuously, but now we don’t need to render when the window changes size.


   window.addEventListener('resize', render);

Copy the code

With this, we’ve got some render on demand stuff. As shown in the figure below

Check the instance

There is an option to add inertia in OrbitControls to make them feel less rigid. We can enable this feature by setting the enableDamping property to true.

   controls.enableDamping = true;
Copy the code

Along with enableDamping we need to call the renderer function of Controls.update to continue providing us with the new camera Settings while The OrbitControls move smoothly. However, this means we can’t call the change event directly in render because we end up in an infinite loop. The control will send us a change event and render, which will call controls.update.controls. update will send another change event.

We can solve this problem by calling requestAnimationFrame, render but we need to make sure we only request a new frame if it is not requested, we can keep a variable to keep track of whether we have requested a frame or not.


   let renderRequested = false;

   function render() {

       renderRequested = false;
       if (resizeRendererToDisplaySize(renderer)) {

           const canvas = renderer.domElement;

           camera.aspect = canvas.clientWidth / canvas.clientHeight;

           camera.updateProjectionMatrix();

       }

       renderer.render(scene, camera);

   }

   render();

   function requestRenderIfNotRequested() {

       if(! renderRequested) { renderRequested =true;

           requestAnimationFrame(render);
       }
   }

   controls.addEventListener('change', requestRenderIfNotRequested);

Copy the code

We can also use requestRenderIfNotRequested to adjust the size


   window.addEventListener('resize', requestRenderIfNotRequested);

Copy the code

It can be hard to tell the difference. Try clicking on the example below and using the arrow keys to move back and forth or drag to rotate. Then try clicking on the above example and doing the same, and you should be able to tell the difference. When you press the arrow key or drag, the top one catches and the bottom one slides.

Check the instance

We also added a simple dat.GUI GUI and made the changes render on demand.


   import * as THREE from './resources/three/r132/build/three.module.js';

   import {OrbitControls} from './resources/threejs/r132/examples/jsm/controls/OrbitControls.js';

   import {GUI} from '.. /3rdparty/dat.gui.module.js';

Copy the code

We can set the color and x ratio of each cube. To be able to set the color, we will create it using ColorGUIHelper.

First we need to create a GUI


   const gui = new GUI();

Copy the code

Then, for each cube, we will create a folder and add two controls, one for material. Color and one for cubo.scale.x.


   function makeInstance(geometry, color, x) {

       const material = new THREE.MeshPhongMaterial({color});
       const cube = new THREE.Mesh(geometry, material);
       scene.add(cube);
       cube.position.x = x;
       const folder = gui.addFolder(`Cube${x}`);
       folder.addColor(new ColorGUIHelper(material, 'color'), 'value')
       .name('color')
       .onChange(requestRenderIfNotRequested);
       folder.add(cube.scale, 'x'.1..1.5)
       .name('scale x')
       .onChange(requestRenderIfNotRequested);
       folder.open();
       return cube;
   }

Copy the code

You can see that the dat.GUI control above has an onChange method that you can pass a callback to call when the GUI changes a value. In our case, we only need to call in requestRenderIfNotRequested folder. Open the folder begin to expand.

Check the instance

I hope this gives you an idea of how to make three.js render on demand rather than continuously. Applications/pages that render three.js on demand are not as common as most pages that use Three.js, either games or 3D animation art, but examples of pages that render three.js on demand better could be said to be map viewers, 3D editors, 3D graphics generators, product catalogs, etc…

Translation: threejsfundamentals.org/threejs/les…

Write in the last

This article introduces Three. Js on demand loading related content, hope to help you.

This article is published from the cloud Map 3D big front end team, the article is not authorized to be reproduced in any form.