简介
Three.js是用JavaScript编写的第三方库,用于实现3D功能,基于WebGL进行封装。
一个3D模型的建立主要由以下几个部分组成(基本版):
* 创建场景scene--相机camera--渲染器renderer--(灯光light);
* 创建模型(geometry+material+mesh)或导入模型gltf/glb;
* 添加相机控件controls--动画渲染循环animate;* 其他动画操作,可学习gasp动画库。
一、引入threeJS
// 引入three.js---npm install three@0.157.0 -S
import * as THREE from "three";
二、场景、相机、渲染器
1、创建3D场景对象Scene
const scene = new THREE.Scene();
2、创建透视投影相机对象
// const camera = new THREE.PerspectiveCamera(); //正投影相机是OrthographicCamera // 定义threejs输出Canvas画布的尺寸(单位:像素px) const width = window.innerWidth; //宽度 const height = window.innerHeight; //高度 // (fov,aspect,near,far),30:视场角度, width / height:Canvas画布, 1:近裁截面, 3000:远裁截面 const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000); //相机在Three.js三维坐标系中的位置---根据需要设置相机位置具体值 camera.position.set(292, 223, 185); //相机观察目标指向Threejs 3D空间中某个位置 camera.lookAt(0, 0, 0); //坐标原点---camera.lookAt(mesh.position);指向mesh对应的位置
3、创建webGL渲染器对象
//属性:antialias是否抗锯齿 const renderer = new THREE.WebGLRenderer(); //设置three.js渲染区域的尺寸(像素px) renderer.setSize(width, height); //WebGLRenderer执行渲染方法生成canvas画布,并把相机拍照的场景在画布上呈现 renderer.render(scene, camera); // console.log("threeJS", THREE.Scene); //测试场景 // 获得生成的canvas画布(domElement就是生成的那张照片==canvas画布==html元素) document.body.appendChild(renderer.domElement); // 将Canvas画布插入到任意HTML元素中 // document.getElementById('app').appendChild(renderer.domElement);
三、灯光及阴影
灯光:
1、PointLight:点光源,类似于灯泡,向四周发射光线的发光点。
2、SpotLight:聚光源,沿着特定方向逐渐发散,照射范围在三维空间中构成一个圆锥体。
3、DirectionalLight:平行光,沿着特定方向发射。
4、AmbientLight:环境光,没有特定方向,只是整体改变场景的光照明暗,无法投射阴影,均匀照射对物体明暗对比无法呈现。
5、HemisphereLight:半球光,可以很好地表现天空和地面颜色照射到物体上时的效果,不能投射阴影,对物体明暗对比比较明显。
以点光源举例:
const pointLight = new THREE.PointLight(0xffffff, 1.0); pointLight.intensity = 1.0; //光照强度 // 设置光源衰减,默认2.0 pointLight.decay = 0.0; //设置光源不随距离衰减 //点光源位置 pointLight.position.set(400, 0, 0); //点光源放在x轴上 scene.add(pointLight); //点光源添加到场景中// 点光源辅助观察--创建一个虚拟的球形网 Mesh的辅助对象来可视化模拟光线 const pointLightHelper = new THREE.PointLightHelper(pointLight, 50); scene.add(pointLightHelper);
阴影:
阴影的开启需要全方位的开启,渲染器及光源开启阴影,模型要接受阴影,模型需开启阴影,地面接收阴影。
// 首先渲染器开启阴影 renderer.shadowMap.enabled = true; renderer.shadowMapEnabled = true;// 光源开启阴影 directionalLight.castShadow = true; directionalLight.shadow.mapSize = new Vector2(1024, 1024);// 地板接受阴影开启 floor.receiveShadow = true;// 模型Mesh开启阴影 // 物体需要开启“引起阴影”和“接收阴影”: gltf.scene.traverse(obj => {if(obj.isMesh) {obj.castShadow = true;obj.receiveShadow = true;} })
四、模型
一个3d模型是由物体形状及材质组成的网格模型。
通常模型可进行自己搭建及导入模型两个途径:
1、模型搭建
① Geometry 形状
Geometry 通过存储模型用到的点集和点间关系(哪些点构成一个三角形)来描述物体形状。
② Material 材质
Material 其实是物体表面除了形状以外所有可视属性的集合,例如色彩、纹理、光滑度、透明度、反射率、折射率、发光度。③ Mesh 模型
Mesh 用三角形组成的网格来描述三维模型,随着三角形数量的增加,它的表面越来越平滑/准确。
Geometry在threejs中有提供诸如 长方体、圆柱、圆锥等基础形状,更为复杂的形状需自行构建,通常可用以下形状组成:
④ Point 点
Point 在三维空间中的某一个点可以用一个坐标点来表示,点的集合,可以由一组顶点坐标组成。
⑤ Line 线
Line 既可以直接定义线条材质,也可以通过定义两个坐标点,来构造一条线。
⑥ Curve 曲线
Curve 平滑的路径或形状,可用来创建诸如圆弧、椭圆等形状。
//创建一个长方体几何对象Geometry const geometry = new THREE.BoxGeometry(100, 100, 100); //创建一个材质对象Material---MeshBasicMaterial不受光照影响,MeshLambertMaterial受光照影响 const material = new THREE.MeshBasicMaterial({collor: 0xff0000, //0xff0000设置材质颜色为红色transparent: true, //开启透明opacity: 0.5, //设置透明度 }); // 两个参数分别为几何体geometry、材质material const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh //设置网格模型在三维空间中的位置坐标,默认是坐标原点 mesh.position.set(0, 10, 0); // 将网格模型添加到三维场景 scene.add(mesh);/点、线、曲线创建举例 const point1 = new THREE.Vector3(4,8,9); const line = new THREE.Line( geometry, material, THREE.LinePieces ); const curve= new THREE.EllipseCurve(0, 0, 100, 50); //椭圆中心坐标以及x和y方向半径
2、模型导入
通常是使用gltf或glb格式的模型文件,可参考3D模型库:https://sketchfab.com。
//创建GLTFLoader实例 const loader = new GLTFLoader(); //加载gltf、glb模型 loader.load("bydSA3/scene.gltf", (gltf) => {//模型加载成功后的回调函数scene.add(gltf.scene); //将模型添加到场景中},(xhr) => {//加载过程中的回调函数console.log((xhr.loaded / xhr.total)*100+"% loaded");},(error) => {//加载出错的回调函数console.error("An error happened", error);} );
五、相机控件
相机控件可实现鼠标的左键旋转,滑动键缩放,右键平移
也可利用相机控件实现模型自转:
//定义旋转缩放平移相机控件 const controls = new OrbitControls(camera, renderer.domElement); controls.autoRotate = false; //在animate方法中更新OrbitControls controls.update();controls.autoRotate = true; //模型自转
六、动画渲染
动画渲染需要对场景进行绘制的循环,而其他很多操作都是使用动画库tween.js,gasp库等
// 动画循环 const animate = () => {//对场景进行绘制的循环requestAnimationFrame(animate);……renderer.render(scene, camera); }; animate();
动画库使用举例:
import TweenLite from "gsap"; // 参数:动画目标、动作时间、起始状态(已省略)、终点状态 TweenLite.to(component1.position, 1.5, {y: 1.5,ease: Power4.easeOut, });
X、资源教程
1、Three.js中文网教程:http://www.webgl3d.cn/
2、Three.js教j程(api文档):https://threejs.org/docs/
3、web GL中文网:http://www.hewebgl.com/