【前端】threeJS学习(长期更新)

简介 

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/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值