The development of online games, product displays, and indoor roaming based on WebGL technology often involves animation.
1. Periodic rendering
In order to achieve periodic rendering, you can use a method setInterval()
of the browser global object window
object. You can call this method window.setInterval()
setInterval()
directly in function form. setInterval()
is a periodic function, like a timer, that executes a function every few milliseconds.
// Call function fun periodically at 20ms intervals setInterval("render()",20)
In order to achieve the cube rotation animation effect, look at the following code
function render(){ renderer.render(scene,camera);//Perform rendering operation mesh.rotateY(0.01);//Rotate 0.01 radians around the y-axis each time } setInterval("render()",20);
The above code defines a rendering function render()
. Three statements are defined in the function, which can be implemented through setInterval("render()",20);
The function render()
is called every 20 milliseconds. Each time the rendering function is called, execute renderer.render(scene,camera);
to render a frame of image and execute The mesh.rotateY(0.01);
statement rotates the cubic mesh model around the y-axis by 0.01 radians.
2. Rendering frequency
The rendering frequency of calling the rendering method .render()
cannot be too low, for example, setInterval("render()",200);
calls rendering every 200 milliseconds. The function is rendered once, which is equivalent to rendering 5 times per second, and it will feel laggy. The rendering frequency should not be too low, nor should it be too high. If it is too high, the computer's hardware resources cannot keep up, and the rendering method set by the function setInterval()
may not be able to be implemented normally. Generally, the rendering frequency of calling the rendering method .render()
for rendering is controlled at 30 to 60 times per second. The human visual effect is normal and the rendering performance can also be taken into consideration.
//Set the period for calling the render function to 200ms, and the refresh frequency is equal to 5. You can clearly feel the lag. setInterval("render()",200);
3. Function requestAnimationFrame()
The requestAnimationFrame()
parameter is the function name of the function to be called. requestAnimationFrame()
Calling a function does not call it immediately but initiates a request to the browser to execute a certain function. What? The execution time is determined by the browser. Generally, the frequency of 60FPS is maintained by default. The function specified by the requestAnimationFrame()
method is called approximately every 16.7ms. 60FPS is ideal. If the rendered scene is more complex or It is said that the hardware performance is limited and may be lower than this frequency.
function render() { renderer.render(scene,camera);//Perform rendering operation mesh.rotateY(0.01);//Rotate 0.01 radians around the y-axis each time requestAnimationFrame(render);//Request to execute the rendering function render again } render();
4. Uniform rotation
When actually executing the program, the function requested by requestAnimationFrame(render)
may not be executed at the ideal 60FPS frequency, and the time interval between two executions of the rendering function may not be the same. If the rotation command is executed The time interval of rotateY
is different, and the rotation motion is uneven. In order to solve this problem, it is necessary to record the time interval between executing the drawing function twice.
Just use the following rendering function to replace the original rendering function. The parameter of rotateY()
is 0.001*t
, which also means the interval between two calls to the rendering function to perform the rendering operation. In t
milliseconds, the cube rotates 0.001*t
radians. Obviously, the angular velocity of the cube is 0.001
radians per millisecond (0.0001 rad/ms = 1 rad/s = 180 degrees/s). The time it takes for CPU and GPU to execute an instruction is nanoseconds ns, which is 6 orders of magnitude lower than milliseconds ms. Therefore, it is generally not necessary to consider the time occupied by several timing statements in the rendering function unless you write something that is accurate to nanoseconds ns. Level standard clock program.
let T0 = new Date();//Last time function render() { let T1 = new Date();//This time let t = T1-T0;//time difference T0 = T1;//Assign this time to the last time requestAnimationFrame(render); renderer.render(scene,camera);//Perform rendering operation mesh.rotateY(0.001*t);//Rotation angular speed 0.001 radians per millisecond } render();
5. Complete example
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>The first ThreeJS</title> <!--Introducing three.js three-dimensional engine--> <!-- <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script> --> <script src="../js/three.js"></script> <script src="../js/OrbitControls.js"></script> </head> <style> body { margin: 0; overflow: hidden /*Hide body window area scroll bar*/ ; } </style> <body> <script> //Create scene object var scene = new THREE.Scene(); //Create grid model var geometry = new THREE.BoxGeometry(50, 100, 100);//Create a cubic geometry object // var geometry = new THREE.SphereGeometry(60, 40, 40); var material = new THREE.MeshLambertMaterial({ color: 0x0000ff }) //Create material object Material var mesh = new THREE.Mesh(geometry, material); //Mesh object model scene.add(mesh);//Add the mesh model to the scene //Light source settings: point light source var point = new THREE.PointLight(0xffffff); point.position.set(400, 200, 300); //Point light source position scene.add(point); //Add point light source to the scene //Ambient light var ambient = new THREE.AmbientLight(0x444444); scene.add(ambient); //Add ambient light to the scene //Camera settings var width = window.innerWidth; //Create width var height = window.innerHeight;//Window height var k = width / height;//window aspect ratio var s = 200; //Three-dimensional scene display range control coefficient. The larger the coefficient, the greater the display range. var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000); //Create camera object camera.position.set(250, 300, 200); //Set camera position camera.lookAt(scene.position); //Set the camera direction (pointing scene object) var renderer = new THREE.WebGLRenderer();//Create renderer object renderer.setSize(width, height); //Set the rendering area size renderer.setClearColor(0xb9d3ff, 1);//Set the background color document.body.appendChild(renderer.domElement);//Insert canvas object into body element // renderer.render(scene, camera);//Perform the rendering operation and specify the scene and camera as parameters // function render(){ // renderer.render(scene,camera);//Perform rendering operation //mesh.rotateY(0.01);//Rotate 0.01 radians around the y-axis each time // requestAnimationFrame(render);//Request to execute the rendering function render again // } // render(); // let T0 = new Date();//Last time // function render() { // let T1 = new Date();//This time // let t = T1-T0; // time difference // T0 = T1; // Assign this time to the last time // requestAnimationFrame(render); // renderer.render(scene,camera);//Perform rendering operation //mesh.rotateY(0.001*t);//Rotation angular speed 0.001 radians per millisecond // } // render(); function render() { renderer.render(scene, camera);//Perform rendering operation //mesh.rotateY(0.01);//Rotate 0.01 radians around the y-axis each time requestAnimationFrame(render);//Request to execute the rendering function render again } render(); var controls = new THREE.OrbitControls(camera, renderer.domElement);//Create a control object // The render function has been executed periodically through requestAnimationFrame(render);, there is no need to execute the render function by listening to mouse events. // controls.addEventListener('change', render) </script> </body> </html>