threeJs基础 | 8月更文挑战

674 阅读5分钟

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'报错

image.png

初始化一个demo

  1. 创建一个场景(场景是所有物体的容器,只有一个)
const scene = new THERR.Scene()
  1. 照相机(定义了三维空间到二维屏幕的投影方式:正交投影和透视投影)

image.png

(a):透视投影;(b):正交投影

const camera = new THREE.PerspectiveCamera(fov, aspect, near, far)

image.png

  • fov是视景体竖直方向上的张角
  • aspect等于width/height,是照相机水平方向和竖直方向长度的比值,通常设为canvas的横纵比例
  • near照相机到视景体最近的距离,为正值。
  • far照相机到视景体最远的距离,为正值。
  1. 渲染器(将相机拍摄出的画面在浏览器中呈现出来) (渲染器决定了渲染的结果应该画在页面的什么元素上面,并且以怎样的方式来绘制)
  • 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文件其他的文件需要外部函数支持
  • 材质(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插件,实现场景用鼠标交互

(后续会持续更新.....)