2019-05-08 | 学习笔记 | UNLOCK | 更新时间:NaN-NaN-NaN NaN:NaN

Three.js的学习笔记(一)

官网 https://threejs.org

Three.js是一个Javascript库,所以当你使用它创建一个WebGl应用的时候,你所需要的仅仅是一个文本编辑器和一个支持WebGl的浏览器,但是国内对于Three.js的文档并不是很齐全,官网自身的中文翻译仅仅只是标题。

文章中所展示的例子都是实际执行的代码,并没有展示各类API的详细信息

基本要素

在使用Threejs 来显示一样东西或者什么的时候,你需要scene (场景),camera (相机)和 renderer(渲染器)来布置一个舞台来进行展示或者表演,下面的例子就是一个基本的场景,展示一个“ 空 ”的场景

引入文件:three.min.js

  • 这是最基本的引入文件,Three.js要执行的必需文件
//创建一个场景
var scene = new THREE.Scene();

//创建一个摄像机 属性:(视野,宽高比,近剪裁平面和远剪裁平面)
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );

//创建渲染器实例 设置我们希望它渲染应用程序的大小,浏览器窗口的宽度和高度
var renderer = new THREE.WebGLRenderer({
    antialias:true, //开启抗锯齿效果
    alpha:true //允许透明
});
    renderer.setClearColor(0xffffff);//设置场景颜色
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

...

//渲染
renderer.render( scene, camera );

辅助对象

在开始开发的时候,你可能分不清XYZ轴的方向,光照的方向,阴影产生的方向,距离的多少等等,Three.js 当然提供了一些辅助对象,用于辅助开发,我在下例仅举几个简单例子,详细可以看后面的学习文章或者官方文档

用于区分XYZ 轴的简单对象

//辅助对象 三维箭头 红x 绿y 蓝z 
var axesHelper = new THREE.AxesHelper( 50 ); //50 为长度
    scene.add( axesHelper );

用于区分坐标的坐标格辅助对象

//坐标格辅助
var grid = new THREE.GridHelper(80, 20, 0x000000, 0x000000);
    grid.material.transparent = true;//允许透明
    grid.material.opacity = 0.3; //透明度
    grid.rotation.x = 0.5 * Math.PI;//x轴翻转90scene.add(grid);

光照和阴影

在Three中,光照是很重要的一部分,在Three.js所渲染的世界中是没有光,如果在世界中不添加光,那么到处都是一片黑色,极致的黑会导致你什么都看见,有光就会产生阴影(无影灯那种另说)。

//平行光
var light = new THREE.DirectionalLight( 0xffffff, 0.8 );
var lightC=40
    light.position.set( 20, 40, 20 );
    light.castShadow = true; //允许产生阴影
    light.shadow.camera.left = - lightC;
    light.shadow.camera.right = lightC;
    light.shadow.camera.top = lightC;
    light.shadow.camera.bottom = - lightC;
    light.shadow.camera.near = 10;
    light.shadow.camera.far = 180;
    light.shadow.bias = - 0.001;
    light.shadow.mapSize.width = 1512;
    light.shadow.mapSize.height = 1512;
    scene.add( light );

轨道控制相机

方便我们对模型进行360度的观察,官方提供的一个观察对象的相机,(当然,之前的我并没有注意到,结果自己写的一个,和官方的有点像,结果看到看到了官方的,总感觉自己白写了)基本可以说是完善的很丰富了,当然可能不是很符合我们的习惯,那么想改控制的方式,当然可以选择修改源码,Three.js的各类js并没有进行压缩,这给了我们很好的观察机会

引入文件:OrbitControls.js

//轨道控制相机
var controls = new THREE.OrbitControls( camera );
    camera.position.set( 0, 20, 10 );
    controls.enableDamping = true
    controls.minPolarAngle= Math.PI/8;
    controls.maxPolarAngle= Math.PI/3;
    controls.panSpeed=0.1
    controls.rotateSpeed=0.05
    controls.maxZoom=10
    controls.minDistance=50
    controls.maxDistance=80
    controls.dampingFactor=0.08
    controls.update();
    (function animate() {
      requestAnimationFrame( animate );
      controls.update();
      renderer.render( scene, camera );
    })()

插入模型及贴图

3D模型有很多种文件格式,每种格式都有不同的用途,各种功能和复杂程度,我们要根据载入模型的文件来选择需要的loaders,我使用的是OBJ的文件格式

引入文件:OBJLoaderjs & MTLLoader.js

...
var mtlLoader = new THREE.MTLLoader()
    mtlLoader.setPath( 'obj/' )
    mtlLoader.load( 'server.mtl',function ( materials ) {
      materials.preload();
      var objLoader=new THREE.OBJLoader()
          objLoader.setMaterials( materials )
          objLoader.setPath( 'obj/' )
          objLoader.load('server.obj',function(object){
            scene.add( object );
          },undefined,function(error){
            console.log(error)
          });
    });
...

设置动画及重绘

在three.js动画系统中,您可以为模型的各种属性设置动画: SkinnedMesh(蒙皮和装配模型)的骨骼,Geometry.morphTargets(变形目标), 不同的材料属性(颜色,不透明度,布尔运算),可见性和变换。动画属性可以淡入、淡出、交叉淡化和扭曲。

定时重绘

当我们需要一个简单的动画,定时就成了我们的选择,setInterval 或者 requestAnimationFrame 就能带给我们一个简单的动画,文档推荐 requestAnimationFrame:与 setInterval 相比,requestAnimationFrame 最大的优势是由系统来决定回调函数的执行时机

var animate = function () {
  requestAnimationFrame( animate );
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;
  renderer.render( scene, camera );
};
animate();

点击及交互

光线投射器(Raycaster),该类用来处理光线投射。光线投射主要用于物体选择、碰撞检测以及图像成像等方面

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onMouseClick( event ) {
  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
  mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
  mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
  render()
}
function render() {
  //通过摄像机和鼠标位置更新射线
  raycaster.setFromCamera( mouse, camera );
  // 计算物体和射线的焦点
  var intersects = raycaster.intersectObjects( scene.children );
  console.log(intersects)
  for ( var i = 0; i < intersects.length; i++ ) {
    intersects[ i ].object.material.color.set( 0xffff00 );
  }
  renderer.render( scene, camera );

}
window.addEventListener( 'click', onMouseClick, false );

兼容性检查

兼容性的问题当然有,即使这个问题变得越来越少,但某些设备或浏览器可能仍然不支持WebGL。以下方法允许您检查是否支持它并向用户显示消息(如果不支持)

引入文件: WebGL.js

  • 这是你执行WebGl的检测函数所需要的文件,当然你也可以选择不检测,选择权在你
<script>
if ( WEBGL.isWebGLAvailable() === false ){
  document.body.appendChild( WEBGL.getWebGLErrorMessage() );
}
//如果不支持会打印出信息
</script>

##注意事项

在three.js文档中,并未声明DOCTYPE,如遇到声明后,出现滚动条及canvas大小的样式问题,则需要在设置样式 canvas{ vertical-align:bottom }

工具推荐

Magicavoxel

Magicavoxel是一个由gltracy独立开发的轻量级体素编辑器,大小连1个G都没有的建模软件,基本功能齐全,操作简单,是不可多得的好软件,当然,因为大小的关系,你也不能要求过多