丰富你的第一个Three.js场景

来源:互联网 发布:multiselect.zh cn.js 编辑:程序博客网 时间:2024/05/22 03:16

上一篇文章中我们创建了我们的第一个Three.js场景,并在场景中加入了坐标系、平面、立方体和球体,在这篇文章中我们将进一步丰富我们的场景,向其中加入光源产生阴影、加入动画并添加控制器、最后加入两个在Three.js常用的插件。


我们采用的是CanvasRenderer渲染器,但在这篇文章之前发现它对聚光光源的支持上存在问题、同样的代码只是换了一个渲染器整个场景就变成黑色,可能是Three.js的一个小bug吧,而且它渲染出来的物体是存在很明显的线条,建议采用更为友好WebGl渲染器。


1、准备需要的Js文件

stats.js:https://github.com/mrdoob/three.js/tree/dev/examples/js/libs

dat.gui:https://github.com/mrdoob/three.js/tree/dev/examples/js/libs

2、向场景中加入聚光灯光源

上一节中我们为平面、立方体和球体都添加了表面材质MeshBasicMaterial材料,它是一种非光敏材料,渲染后物体的颜色始终为该材质的颜色,而不会由于光照产生明暗、阴影效果,本节中我们采用的是MeshPhongMaterial材质,没有光源的情况显示是黑色的,在光源下才会展现,即可以理解为天黑了看不见,Phong是镜面反射材料,类似于金属材质,关于Three.js的三种材质将会在后续中介绍。

    ......    var planeMaterial = new THREE.MeshPhongMaterial({color: 0xffffff});    ......    var cubeMaterial = new THREE.MeshPhongMaterial({color: 0xff0000});    ......    var sphereMateial = new THREE.MeshPhongMaterial({color: 0x7777ff});    ......

向场景中加入聚光灯光源SpotLight,类似于手电筒,存在一定的角度并朝固定的方向照射。

    var spotLight = new THREE.SpotLight(0xffffff);    spotLight.position.set(-40, 60, -10);    scene.add(spotLight);

3、为场景中物体添加阴影效果

由于阴影的渲染是要消耗大量资源的,所以Three.js默认是关闭阴影功能的,需要我们手动添加属性

(一)渲染器开启支持

    renderer.shadowMapEnabled = true;
Three.js版本比较多吧,代码中也没有明显的版本标识,最新的版本已经将阴影属性改为renderer.shadowMap.enable,但是最新的版本阴影效果存在特别明显的锯齿效果,所以我使用了老版本,后面应该会修复。

(二)光源开启支持

    spotLight.castShadow = true;

(三)接收平面开启支持

     plane.receiveShadow = true;

(四)物体开启支持

    cube.castShadow = true;    ......    sphere.castShadow = true;
此时你看到的场景是这样的:

3、为立方体cube加入动画

我们采用requestAnimationFrame进行动画渲染,在此之前一般都是采用定时器的方法进行HTML的动画控制,但是定时器不会根据浏览器实时渲染情况进行调节,而且定时器是一直存在的,requestAnimationFrame完美的解决了这两个问题,它是和浏览器当前绑定的,即只有在渲染完当前一帧才会去渲染下一帧,而且在HTML最小化的时候是不会继续执行的,基本用法如下:

function renderSence() {    // Control Cube    cube.rotation.x += 0.02;    cube.rotation.y += 0.02;    cube.rotation.z += 0.02;    requestAnimationFrame(renderSence);    renderer.render(scene, camera);    console.log("Here");}
为了方便动画渲染需要重新定义一个渲染函数renderSence,直接在自执行函数的最后调用该函数即可。requestAnimationFrame的使用可以抽象为递归函数,即在函数里面再次调用,在这里加入了Cube控制,每次渲染给立方体的角度添加0.02的角度,这样的效果就是立方体在场景中不停的旋转。为了查看requestAnimationFrame是否调用成功,可以在里面加入一段日志打印查看效果。

4、为球体加入动画

function renderSence() {    // Control Cube    cube.rotation.x += 0.02;    cube.rotation.y += 0.02;    cube.rotation.z += 0.02;    // Control Sphere    step += 0.04;    sphere.position.x = 20 + (10 * ( Math.cos(step) ));    sphere.position.y = 2 + (10 * Math.abs( Math.sin(step) ));    // Render With RequestAnimationFrame    requestAnimationFrame(renderSence);    renderer.render(scene, camera);    console.log("Here");}

此时重新打开你的场景,你会看到立方体在不停的旋转、球体在按照既定路线跳跃,场景已经开始丰富起来啦!

5、加入JavaScript性能监视器Stats.js

Stats包含两个参数,每秒渲染次数FPS及每次渲染所需内存,使用它可以实时监控你的Three.js项目的运行情况,使用也是非常简单,首先给它准备个容器盒子

        <div id="Stats-Output">        </div>
之后实例化一个对象并为它添加样式,最后在requestAnimationFrame中调用更新函数updata()。
   var stats = initStats();
......function initStats() {   var stats = new Stats();   stats.setMode(0);   stats.domElement.style.position = 'absolute';   stats.domElement.style.left = '0px';   stats.domElement.style.top = '0px';   document.getElementById("Stats-Output").appendChild(stats.domElement);   return stats;}
function renderSence() {  ......  stats.update();  ......}
此时可以看到上面动图中左上角的效果,点击可以查看每帧率内存占用情况。

6、添加动画控制器dat.gui.js,可以用来控制物体动画的变化值,即可以让立方体旋转变快变慢、球体运动速度加快减慢

var controls = new function () {    this.rotationSpeed = 0.02;    this.bouncingSpeed = 0.03;};var gui = new dat.GUI();gui.add(controls, 'rotationSpeed', 0, 0.5);gui.add(controls, 'bouncingSpeed', 0, 0.5);function renderSence() {    // Control Cube    cube.rotation.x += controls.rotationSpeed;    cube.rotation.y += controls.rotationSpeed;    cube.rotation.z += controls.rotationSpeed;    // Control Sphere    step += controls.bouncingSpeed;    sphere.position.x = 20 + (10 * ( Math.cos(step) ));    sphere.position.y = 2 + (10 * Math.abs( Math.sin(step) ));    // Render With RequestAnimationFrame    requestAnimationFrame(renderSence);    renderer.render(scene, camera);    stats.update();    console.log("Here");}
新建一个构造器函数controls,定义需要传递的参数rotationSpeed与bouncingSpeed,之后实例化dat.GUI对象,传递的参数分别为构造器函数、参数(对应构造器内部参数)、最小值、最大值,之后在requestAnimationFrame中将原来的静态变量改为controls的参数,这样就可以通过鼠标调节动画的属性啦!


后面我会持续更新有关Three.js的内容,如果觉得本文对您有帮助,请点击‘顶’支持一下

您的支持是我写作最大的动力,谢谢。


QQ:1193238879

微信:lizhaoting12