共计 2472 个字符,预计需要花费 7 分钟才能阅读完成。
举荐:将 NSDT 场景编辑器退出你 3D 工具链
https://ted.sinoccdc.cn/
其余工具系列:NSDT 简石数字孪生
基于 WebGL 技术开发在线游戏、商品展现、室内漫游往往都会波及到动画,初步理解 three.js 能够做什么,深刻解说 three.js 动画之前,本节课先制作一个简略的立方体旋转动画。本节课是在 1.1 节 第一个 3D 场景已绘制好的立方体代码根底上进行更改。
周期性渲染
在 1.1 节中解说过,每执行一次渲染器对象 WebGLRenderer 的渲染办法.render(),浏览器就会渲染出一帧图像并显示在 Web 页面上,这就是说你依照肯定的周期不停地调用渲染办法.render()就能够不停地生成新的图像笼罩原来的图像。这也就是说只有一边旋转立方体,一边执行渲染办法.render()从新渲染,就能够实现立方体的旋转成果。
为了实现周期性渲染能够通过浏览器全局对象 window 对象的一个办法 setInterval(), 能够通过 window 对象调用该办法 window.setInterval(),也能够间接以函数模式调用 setInterval()。
setInterval()是一个周期性函数,就像一个定时器,每隔多少毫秒 ms 执行一次某个函数。
// 距离 20ms 周期性调用函数 fun
setInterval(“render()”,20)
为了实现立方体旋转动画成果,间接应用上面的代码代替 1.1 节中代码 renderer.render(scene,camera); 即可。
// 渲染函数
function render() {
renderer.render(scene,camera);// 执行渲染操作
mesh.rotateY(0.01);// 每次绕 y 轴旋转 0.01 弧度
}
// 距离 20ms 周期性调用函数 fun,20ms 也就是刷新频率是 50FPS(1s/20ms),每秒渲染 50 次
setInterval(“render()”,20);
下面代码定义了一个渲染函数 render(),函数中定义了三个语句,通过 setInterval(“render()”,20); 能够实现 m 每距离 20 毫秒调用一次函数 render(),每次调用渲染函数的时候,执行 renderer.render(scene,camera); 渲染出一帧图像,执行 mesh.rotateY(0.01); 语句使立方体网格模型绕 y 轴旋转 0.01 弧度。
渲染频率
调用渲染办法.render()进行渲染的渲染频率不能太低,比方执行 setInterval(“render()”,200); 距离 200 毫秒调用渲染函数渲染一次,相当于每秒渲染 5 次,你会感觉到比拟卡顿。渲染频率除了不能太低,也不能太高,太高的话计算机的硬件资源跟不上,函数 setInterval()设定的渲染形式也未必可能失常实现。个别调用渲染办法.render()进行渲染的渲染频率管制在每秒 30~60 次,人的视觉效果都很失常,也能够兼顾渲染性能。
// 设置调用 render 函数的周期为 200ms,刷新频率相当于 5 你能显著的感触到卡顿
setInterval(“render()”,200);
函数 requestAnimationFrame()
后面解说 threejs 动画成果,应用了 setInterval()函数,理论开发中,为了更好的利用浏览器渲染,能够应用函数 requestAnimationFrame()代替 setInterval()函数,requestAnimationFrame()和 setInterval()一样都是浏览器 window 对象的办法。
requestAnimationFrame()参数是将要被调用函数的函数名,requestAnimationFrame()调用一个函数不是立刻调用而是向浏览器发动一个执行某函数的申请,什么时候会执行由浏览器决定,个别默认放弃 60FPS 的频率,大概每 16.7ms 调用一次 requestAnimationFrame()办法指定的函数,60FPS 是现实的状况下,如果渲染的场景比较复杂或者说硬件性能无限可能会低于这个频率。能够查看文章《requestAnimationFrame()》理解更多 requestAnimationFrame()函数的常识。
function render() {
renderer.render(scene,camera);// 执行渲染操作
mesh.rotateY(0.01);// 每次绕 y 轴旋转 0.01 弧度
requestAnimationFrame(render);// 申请再次执行渲染函数 render
}
render();
平均旋转
在理论执行程序的时候,可能 requestAnimationFrame(render)申请的函数并不一定能依照现实的 60FPS 频率执行,两次执行渲染函数的工夫距离也不肯定雷同,如果执行旋转命令的 rotateY 的工夫距离不同,旋转静止就不平均,为了解决这个问题须要记录两次执行绘制函数的工夫距离。
应用上面的渲染函数替换原来的渲染函数即可,rotateY()的参数是 0.001t,也意味着两次调用渲染函数执行渲染操作的距离 t 毫秒工夫内,立方体旋转了 0.001 t 弧度,很显然立方体的角速度是 0.001 弧度每毫秒(0.0001 rad/ms = 1 rad/s = 180 度 /s)。CPU 和 GPU 执行一条指令工夫是纳秒 ns 级,相比毫秒 ms 低了 6 个数量级,所以个别不必思考渲染函数中几个计时语句占用的工夫,除非你编写的是要准确到纳秒 ns 的级别的规范时钟程序。
let T0 = new Date();// 上次工夫
function render() {
let T1 = new Date();// 本次工夫
let t = T1-T0;// 时间差
T0 = T1;// 把本次工夫赋值给上次工夫
requestAnimationFrame(render);
renderer.render(scene,camera);// 执行渲染操作
mesh.rotateY(0.001*t);// 旋转角速度 0.001 弧度每毫秒
}
render();