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

本文学习内容来源:
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+: custom
document.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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程圈子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值