转自webgl中文网:http://www.hewebgl.com/article/getarticle/58
4、物体运动后,怎么评估程序的性能
关于性能:测试一个程序,性能上是否有瓶颈,在3D世界里,经常使用帧数的概念,首先我们来定义一下帧数的意义。
帧数:图形处理器每秒钟能够刷新几次,通常用fps(Frames Per Second)来表示。如下是每秒钟59次刷新的应用:
当物体在快速运动时,当人眼所看到的影像消失后,人眼仍能继续保留其影像1/24秒左右的图像,这种现象被称为视觉暂留现象。是人眼具有的一种性质。人眼观看物体时,成像于视网膜上,并由视神经输入人脑,感觉到物体的像。一帧一帧的图像进入人脑,人脑就会将这些图像给连接起来,形成动画。
毫无疑问,帧数越高,画面的感觉就会越好。所以大多数游戏都会有超过30的FPS。为了监视FPS,看看你的程序哪里占用了很多的CPU时间,就需要学习一下性能监视器。
1、性能监视器Stats
在Three.js中,性能由一个性能监视器来管理,它的介绍在https://github.com/mrdoob/stats.js 可以看到。性能监视器的截图如下所示:
其中FPS表示:上一秒的帧数,这个值越大越好,一般都为60左右。点击上面的图,就会变成下面的另一个视图。
MS表示渲染一帧需要的毫秒数,这个数字是越小越好。再次点击又可以回到FPS视图中。
2、性能监视器Stats的使用
在Three.js中,性能监视器被封装在一个类中,这个类叫做Stats,下面是一段伪代码,表示Stats的使用。
var stats = new Stats();
stats.setMode(1); // 0: fps, 1: ms
// 将stats的界面对应左上角
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild( stats.domElement );
setInterval( function () {
stats.begin();
// 你的每一帧的代码
stats.end();
}, 1000 / 60 );
你现在可以自己写一段代码,来验证一下,你的程序的帧数了。
Stats到底做了什么事情呢?我们来分析一下。
1、setMode函数
参数为0的时候,表示显示的是FPS界面,参数为1的时候,表示显示的是MS界面。
2、stats的domElement
stats的domElement表示绘制的目的地(DOM),波形图就绘制在这上面。
3、stats的begin函数
begin,在你要测试的代码前面调用begin函数,在你代码执行完后调用end()函数,这样就能够统计出这段代码执行的平均帧数了。
5、性能测试实例
好了,有了上面关于Stats类的基础知识后,我们来讲一个使用这个类的实例。
Stats的begin和end 函数本质上是在统计代码执行的时间和帧数,然后用公式fps=帧数/时间 ,就能够得到FPS。Stats的这个功能,被封装成了一个更好的函数update,只需要在渲染循环中调用就可以了。请看下面的代码[初级教程\chapter3\3-3.html],这份代码是在3-2.html的基础上,加上了stats统计得到的。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Three框架</title>
<script src="js/Three.js"></script>
<script src="js/Stats.js"></script>
<style type="text/css">
div#canvas-frame {
border: none;
cursor: pointer;
width: 100%;
height: 600px;
background-color: #EEEEEE;
}
</style>
<script>
var renderer;
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.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById('canvas-frame').appendChild(stats.domElement);
}
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 cube;
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()
{
//renderer.clear();
//camera.position.x =camera.position.x +1;
mesh.position.x-=1;
renderer.render(scene, camera);
requestAnimationFrame(animation);
stats.update();
}
</script>
</head>
<body onload="threeStart();">
<div id="canvas-frame"></div>
</body>
</html>
代码的运行效果如下图所示,左上部,就是显示的帧计数器。
以上代码一共只有几个步骤:
1、new 一个stats对象,代码如下
stats = new Stats();
2、将这个对象加入到html网页中去,代码如下
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
3、调用stats.update()函数来统计时间和帧数。代码如下
stats.update();
好了,这节课就讲到这里了,我们讲了重要的游戏循环和性能测试的方法。当帧数较低的时候,你就要注意了,可能是你的代码性能太低了造成的。一般情况下,帧数都可以跑到60的。