threeJs
简介:threeJs是WebGl的JavaScript 3D库,对webGl的接口进行了非常好的封装
官方文档:threejs.org/ 中文文档:techbrood.com/threejs/doc…
引入threeJs
// 使用cnpm安装,(我使用的fd创建的项目,使用npm安装启动报错)
cnpm install three
// 引入
import * as THERR from 'three';
- 使用
import THERR from 'three'报错
初始化一个demo
- 创建一个场景(场景是所有物体的容器,只有一个)
const scene = new THERR.Scene()
- 照相机(定义了三维空间到二维屏幕的投影方式:正交投影和透视投影)
(a):透视投影;(b):正交投影
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far)
- fov是视景体竖直方向上的张角
- aspect等于width/height,是照相机水平方向和竖直方向长度的比值,通常设为canvas的横纵比例
- near照相机到视景体最近的距离,为正值。
- far照相机到视景体最远的距离,为正值。
- 渲染器(将相机拍摄出的画面在浏览器中呈现出来) (渲染器决定了渲染的结果应该画在页面的什么元素上面,并且以怎样的方式来绘制)
- webGLRenderer
- canvasRenderer
- SVGRenderer
通常使用webGl渲染,创建渲染器之后,需要调用render方法将场景和相机结合然后渲染出来
const renderer = new THERR.WebGLRenderer({
alpha: true, // 默认情况下为黑色场景,此处设置为透明
antialias: true // 抗锯齿
});
renderer.render(scene, camera);
// 设置渲染器的高宽
renderer.setSize(window.innerWidth, window.innerHeight);
至此,绘制的前期工作就可以了,下面就开始画画了
3d世界实际上是有无数的点组成的,两个点组成一条线,三个不在一条直线上的点组成面,很多面就组成了各种各样的物体
3D世界的内容
- 几何图形(Geometries)
- three提供了很多固定的形状,BoxGeometry(长方体)、SphereGeometry(球体)等等
- SphereGeometry(radius(球体半径), widthSegments(水平分分割面数,最小为3), heightSegments(垂直分割面数,最小值为2), phiStart(水平起始角度), phiLength(水平扫描角度大小), thetaStart(垂直起始角度), thetaLength(垂直扫描角度大小))
- 可以导入模型(.dae,.obj, .mtl,.fbx,.sea,.vmd,.vpd, .js, .json);除了.js和.json文件其他的文件需要外部函数支持
- three提供了很多固定的形状,BoxGeometry(长方体)、SphereGeometry(球体)等等
- 材质(Materials)
- MeshBasicMaterial(对光照无感,给几何体一种简单的颜色或显示线框)
- MeshLambertMaterial(对光照有反应,无光源则不会显示,用于创建暗淡的不发光的物体)
- MeshPhongMaterial(对光照有反应,无光源不会显示,用于创建金属类米昂凉的物体)
tips:创建材质时使用的颜色是十六进制的前面要加(0x)
new THREE MeshBasicMaterial({color: 0xfca745})
- 灯光(Lights)
- AmbientLight(环境光,它的颜色会添加到整个场景和所有对象的当前颜色上)
- PointLight(点光源,这种光源放出的光线来自同一点,且辐射方向四面八方,如蜡烛发出的光)
- DirectionalLight(方向光,也称作无限光,这种光源发出的光线可以看做是平行的,如太阳光)
- SpotLight(聚光灯,光源的光线从一个椎体中射出,在被照射的物体上产生聚光的效果,如手电筒发出的光)
- 阴影
- 能形成阴影的光源只有DirectionalLight(方向光)和SpotLight(聚光灯)
- 能表现阴影效果的材质只有LambertMaterial和PhongMaterial
- 将渲染器的shadowMapEnabled属性设置为true(告诉渲染器可以渲染阴影)
- 将物体及光源的castShadow属性设置为true(告诉物体及光源可以透射阴影)
- 将接收该阴影的物体的receiveShadow属性设置为true(告诉物体可以接收其他物体的阴影)
- mesh(网格模型)
- 将材质包裹在图形上
- 接收两个参数( geometry, material)
- geometry是一个几何模型
- material是材质,可以是数组类型,有多少个面就可以给多少种材质
当我们创建了图形,创建了材质、(灯光、阴影非必须),使用mesh构建模型就可以渲染出来了
创建一个五颜六色的正方体
// 创建一个立方体
creatCube() {
// 创建一个长宽高都为1个单位(相对于照相机看物体的单位)的立方体
const geometry = new THREE.BoxGeometry(10, 10, 10);
// 创建材质,对光照无感
const materialArr = [];
materialArr.push(new THREE.MeshBasicMaterial({color: 0xfca745}));
materialArr.push(new THREE.MeshBasicMaterial({color: 0xfc4545}));
materialArr.push(new THREE.MeshBasicMaterial({color: 0xffd500}));
materialArr.push(new THREE.MeshBasicMaterial({color: 0x28ff00}));
materialArr.push(new THREE.MeshBasicMaterial({color: 0x002bff}));
materialArr.push(new THREE.MeshBasicMaterial({color: 0xbd00ff}));
// 创建一个立方体网格(mesh),将材质包裹在立方体上
this.cube = new THREE.Mesh(geometry, materialArr);
this.scene.add(this.cube);
}
Textures(纹理)
- 贴合于物体表面,一般是2D图片
创建一个带纹理(图片)需要光的球体
// 创建一个需要光的球体
creatSphere() {
// 分割面越多越圆
const geometry = new THREE.SphereGeometry(5, 32, 32);
// 加载一张图片
const load = new THREE.TextureLoader();
const tureImg = load.load('static/js/2.jpg');
// 创建材质,需要光照
const material = new THREE.MeshLambertMaterial({map:tureImg});
// 重复平铺
tureImg.wrapS = THREE.RepeatWrapping;
tureImg.wrapT = THREE.RepeatWrapping;
tureImg.repeat.set(2, 2);
this.sphere = new THREE.Mesh(geometry, material);
this.sphere.position.x = 0;
this.sphere.position.y = 10;
this.sphere.position.z = 10;
this.scene.add(this.sphere);
},
// 添加光源
initLight() {
// 创建一个环境光
const ambiLight = new THREE.AmbientLight(0x333333);
this.scene.add(ambiLight);
// 平行光 DirectionalLight (光源颜色的RGB数值, 光源强度数值)
// 创建一个光照,从一个特定的方向,而不是从一个特定的位置。这个光看起来就像光源位于无限远处,因此它产生的光线都是平行的
const direLight = new THREE.DirectionalLight(0xffffff, 1.0);
// 设置光源的位置
direLight.position.set(100, 300, 100);
this.scene.add(direLight);
}
Controls(控制器)
- 需要使用OrbitControls.js插件,实现场景用鼠标交互
(后续会持续更新.....)