Three.JS学习 4:循环渲染与动画

来源:互联网 发布:程序员刚入职任务不会 编辑:程序博客网 时间:2024/05/16 05:32

本文学习内容来源:
http://www.hewebgl.com/article/getarticle/58

渲染

renderer.render(scence,camera);

当改变了物体的属性时,需要重新调用render()函数,浏览器才会自动刷新场景。
为了循环渲染,要使用requestAnimationFrame函数,传递一个callback参数。

function animate(){  render();  requestAnimationFrame(animate);}

移动摄像机让物体动起来

移动一个物体的源代码:

<!DOCTYPE html><html>    <head>        <meta charset="UTF-8">        <title>Three框架</title>        <script src="js/three.min.js"></script>        <style type="text/css">            div#canvas-frame {                border: none;                cursor: pointer;                width: 100%;                height: 600px;                background-color: #EEEEEE;            }        </style>        <script>            var renderer,width,height;            function initThree() {                width = document.getElementById('canvas-frame').clientWidth;                height = document.getElementById('canvas-frame').clientHeight;                renderer = new THREE.WebGLRenderer({                    antialias: true                });                renderer.setSize(width, height);                document.getElementById('canvas-frame').appendChild(renderer.domElement);                renderer.setClearColor(0xFFFFFF, 1.0);            }            var camera;            function initCamera() {                camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);                camera.position.x = 0;                camera.position.y = 0;                camera.position.z = 600;                camera.up.x = 0;                camera.up.y = 1;                camera.up.z = 0;                camera.lookAt({                    x: 0,                    y: 0,                    z: 0                });            }            var scene;            function initScene() {                scene = new THREE.Scene();            }            var light;            function initLight() {                light = new THREE.AmbientLight(0xFFFFFF);                light.position.set(100, 100, 200);                scene.add(light);                light = new THREE.PointLight(0x00FF00);                light.position.set(0, 0, 300);                scene.add(light);            }            function initObject() {                var geometry = new THREE.CylinderGeometry(100, 150, 400);                var material = new THREE.MeshLambertMaterial({ color: 0x33FF33 });                var mesh = new THREE.Mesh(geometry, material);                mesh.position = new THREE.Vector3(0, 0, 0);                scene.add(mesh);            }            function threeStart() {                initThree();                initCamera();                initScene();                initLight();                initObject();                animation();            }            function animation() {                camera.position.x = camera.position.x + 1;                if (camera.position.x > width-400) camera.position.x = 0;                renderer.render(scene, camera);                requestAnimationFrame(animation);            }        </script>    </head>    <body onload="threeStart();">        <div id="canvas-frame"></div>    </body></html>

这里写图片描述

CylinderGeometry函数说明

  • radiusTop: 柱体顶部半径
  • radiusBottom:柱体底部半径
  • height:柱体高度
  • radiusSegments:圆周分段,数字越高柱体越圆滑
  • heightSegments:高度分段,与上类似
  • openEnded:是否显示顶盖和底板
  • theraStart, thetaLength:暂不清楚

改变物体坐标,让物体动起来

<!DOCTYPE html><html>    <head>        <meta charset="UTF-8">        <title>Three框架</title>        <script src="js/three.min.js"></script>        <style type="text/css">            div#canvas-frame {                border: none;                cursor: pointer;                width: 100%;                height: 600px;                background-color: #EEEEEE;            }        </style>        <script>            var renderer,width,height;            function initThree() {                width = document.getElementById('canvas-frame').clientWidth;                height = document.getElementById('canvas-frame').clientHeight;                renderer = new THREE.WebGLRenderer({                    antialias: true                });                renderer.setSize(width, height);                document.getElementById('canvas-frame').appendChild(renderer.domElement);                renderer.setClearColor(0xFFFFFF, 1.0);            }            var camera;            function initCamera() {                camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);                camera.position.x = 0;                camera.position.y = 0;                camera.position.z = 600;                camera.up.x = 0;                camera.up.y = 1;                camera.up.z = 0;                camera.lookAt({                    x: 0,                    y: 0,                    z: 0                });            }            var scene;            function initScene() {                scene = new THREE.Scene();            }            var light;            function initLight() {                light = new THREE.AmbientLight(0xFF0000);                light.position.set(100, 100, 200);                scene.add(light);                light = new THREE.PointLight(0x00FF00);                light.position.set(0, 0, 300);                scene.add(light);            }            var mesh; //mesh就是要移动的物体            function initObject() {                var geometry = new THREE.CylinderGeometry(100, 150, 400);                var material = new THREE.MeshLambertMaterial({ color: 0xFFFFFF });                mesh = new THREE.Mesh(geometry, material);                mesh.position = new THREE.Vector3(0, 0, 0);                scene.add(mesh);            }            function threeStart() {                initThree();                initCamera();                initScene();                initLight();                initObject();                animation();            }            function animation() {                mesh.position.x -= 1;                console.log(mesh.position.x);                if (mesh.position.x < -(width - 400)) mesh.position.x = 0;                renderer.render(scene, camera);                requestAnimationFrame(animation);            }        </script>    </head>    <body onload="threeStart();">        <div id="canvas-frame"></div>    </body></html>

这里写图片描述

评估程序性能

帧数

定义:图形处理器每秒能刷新多少次
单位:fps(Frames Per Second)

当物体在快速运动时,当人眼所看到影像消失后,人眼仍能继续保留其影像1/24左右的图像,称为视觉暂留现象。一帧一帧的图像进入人脑,人脑将会将这些图像连接起来,形成动画。
帧数越高,画面感觉越流畅。大多数游戏FPS超过30.

添加性能监视器Stats

https://github.com/mrdoob/stats.js
可以看到Three.js的性能监视器。
性能监视器:

FPS监视器

这里写图片描述
FPS : 上一秒的帧数,越大越好,一般为60左右

点击它,会显示:

MS监视器

这里写图片描述

MS 表示渲染一帧需要的毫秒数,越小越好。

MB监视器

这里写图片描述
占用内存多少M字节。启动谷歌浏览器时,使用

--enable-precise-memory-info

CUSTOM监视器

这里写图片描述
支持用户自定义的panel

使用Stats

var stats = new Stats();stats.showPanel( 1 ); // 0: fps, 1: ms, 2: mb, 3+: customdocument.body.appendChild( stats.dom );function animate() {    stats.begin();    // monitored code goes here    stats.end();    requestAnimationFrame( animate );}requestAnimationFrame( animate );

完整示例代码:

<!DOCTYPE html><html>    <head>        <meta charset="UTF-8">        <title>Three框架</title>        <script src="js/three.min.js"></script>        <script src="js/stats.min.js"></script>        <style type="text/css">            div#canvas-frame {                border: none;                cursor: pointer;                width: 100%;                height: 600px;                background-color: #EEEEEE;            }        </style>        <script>            var renderer, width, height;            var stats;            function initThree() {                width = document.getElementById('canvas-frame').clientWidth;                height = document.getElementById('canvas-frame').clientHeight;                renderer = new THREE.WebGLRenderer({                    antialias: true                });                renderer.setSize(width, height);                document.getElementById('canvas-frame').appendChild(renderer.domElement);                renderer.setClearColor(0xFFFFFF, 1.0);                 stats = new Stats();                stats.showPanel(1); // 0: fps, 1: ms, 2: mb, 3+: custom                document.body.appendChild(stats.dom);            }            var camera;            function initCamera() {                camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);                camera.position.x = 0;                camera.position.y = 0;                camera.position.z = 600;                camera.up.x = 0;                camera.up.y = 1;                camera.up.z = 0;                camera.lookAt({                    x: 0,                    y: 0,                    z: 0                });            }            var scene;            function initScene() {                scene = new THREE.Scene();            }            var light;            function initLight() {                light = new THREE.AmbientLight(0xFF0000);                light.position.set(100, 100, 200);                scene.add(light);                light = new THREE.PointLight(0x00FF00);                light.position.set(0, 0, 300);                scene.add(light);            }            var mesh;            function initObject() {                var geometry = new THREE.CylinderGeometry(100, 150, 400);                var material = new THREE.MeshLambertMaterial({ color: 0xFFFFFF });                mesh = new THREE.Mesh(geometry, material);                mesh.position = new THREE.Vector3(0, 0, 0);                scene.add(mesh);            }            function threeStart() {                initThree();                initCamera();                initScene();                initLight();                initObject();                animation();            }            function animation() {                stats.begin();                mesh.position.x -= 1;                console.log(mesh.position.x);                if (mesh.position.x < -(width - 400)) mesh.position.x = 0;                renderer.render(scene, camera);                stats.end();                requestAnimationFrame(animation);            }        </script>    </head>    <body onload="threeStart();">        <div id="canvas-frame"></div>    </body></html>

结果:
这里写图片描述

上面代码里的stats.begin和stats.end可以再次封装:

            function animation() {                mesh.position.x -= 1;                console.log(mesh.position.x);                if (mesh.position.x < -(width - 400)) mesh.position.x = 0;                renderer.render(scene, camera);                requestAnimationFrame(animation);                stats.update();            }

stats.update封装了stats.begin/stats.end

使用Tween.js创建动画

https://github.com/sole 下载库文件
使用方法:

构建Tween对象并初始化

function initTween(){    new TWEEN.Tween(mesh.position).to( { x: -400 }, 3000 ).repeat( Infinity ).start();}

构造函数:要改变的值。
to():接受两个参数,1:集合,存放键值对,x表示mesh.position的x属性, 2:完成动画需要的时间
repeat():重复几次,Infinity是无穷次
start():开始动画

实现动画

function animation(){    renderer.render(scene, camera);    requestAnimationFrame(animation);    stats.update();    TWEEN.update();}

完整示例:

<!DOCTYPE html><html>    <head>        <meta charset="UTF-8">        <title>Three框架</title>        <script src="js/three.min.js"></script>        <script src="js/stats.min.js"></script>        <script src="js/Tween.js"></script>        <style type="text/css">            div#canvas-frame {                border: none;                cursor: pointer;                width: 100%;                height: 600px;                background-color: #EEEEEE;            }        </style>        <script>            var renderer, width, height;            var stats;            function initThree() {                width = document.getElementById('canvas-frame').clientWidth;                height = document.getElementById('canvas-frame').clientHeight;                renderer = new THREE.WebGLRenderer({                    antialias: true                });                renderer.setSize(width, height);                document.getElementById('canvas-frame').appendChild(renderer.domElement);                renderer.setClearColor(0xFFFFFF, 1.0);                 stats = new Stats();                stats.showPanel(1); // 0: fps, 1: ms, 2: mb, 3+: custom                document.body.appendChild(stats.dom);            }            var camera;            function initCamera() {                camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);                camera.position.x = 0;                camera.position.y = 0;                camera.position.z = 600;                camera.up.x = 0;                camera.up.y = 1;                camera.up.z = 0;                camera.lookAt({                    x: 0,                    y: 0,                    z: 0                });            }            var scene;            function initScene() {                scene = new THREE.Scene();            }            var light;            function initLight() {                light = new THREE.AmbientLight(0xFF0000);                light.position.set(100, 100, 200);                scene.add(light);                light = new THREE.PointLight(0x00FF00);                light.position.set(0, 0, 300);                scene.add(light);            }            var mesh;            function initObject() {                var geometry = new THREE.CylinderGeometry(100, 150, 400);                var material = new THREE.MeshLambertMaterial({ color: 0xFFFFFF });                mesh = new THREE.Mesh(geometry, material);                mesh.position = new THREE.Vector3(0, 0, 0);                scene.add(mesh);            }            function initTween() {                new TWEEN.Tween(mesh.position).to({ x: -400 }, 3000).repeat(Infinity).start();            }            function threeStart() {                initThree();                initCamera();                initScene();                initLight();                initObject();                initTween();                animation();            }            function animation() {                renderer.render(scene, camera);                requestAnimationFrame(animation);                stats.update();                TWEEN.update();            }        </script>    </head>    <body onload="threeStart();">        <div id="canvas-frame"></div>    </body></html>
1 0
原创粉丝点击