Threejs在vue中使用(场景、相机、渲染器、gltf模型添加、环境贴图等)

本文介绍了如何在Vue项目中使用Three.js创建3D场景、设置相机、渲染器、添加gltf模型和环境贴图,以及实现交互功能。内容涵盖了Three.js的安装、场景、相机类型、光照、渲染过程、模型导入和环境映射,还讨论了解决模型显示为黑色的问题。

前言

Three.js ( Javascript 3D library ) 是基于原生WebGL封装运行的三维引擎,WebGL可以看成是浏览器给我们提供的接口,在JavaScript中可以直接用这些API进行3D图形的绘制;而Three.js它封装了诸如场景、灯光、阴影、材质、贴图、空间运算等一系列功能,让你不必要再从底层WebGL开始写起。 Three.js是通过对WebGL接口的封装与简化而形成的一个易用的图形库。
Three.js开发3D应用,通常包括渲染器(Renderer)、场景(Scene)、照相机(Camera),以及在场景中创建的物体,光照等。

一、threejs的安装

1、NPM的安装

   npm install --save three

2、组件内使用

import * as THREE from "three";

二、场景

1、场景(scene)介绍

它相当于一个容器,在3d场景中要展现的所有物体、灯光、摄像机等都必须添加到这个容器里面。

2、创建场景对象Scene

Var scene = new THREE.Scene();

3、设置场景的背景色

scene.background = new THREE.Color("#F7F7F7");

三、相机

在threejs中提供了一系列的相机,其中最常用到的是 PerspectiveCamera(透视相机) 和 OrthographicCamera(正交投影相机),它们之间的区别在于透视相机在观察场景中的物体时,呈现出来的物体近大远小,最接近自然的视图。正交投影相机无论从哪个角度观察物体,大小都是一样的。

1、PerspectiveCamera创建, 确定视野范围

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

参数说明:
fov: 视场;垂直方向的观察角度,也就是眼睛上下俯视的观察角度。
aspect: (长宽比)是照相机水平方向和竖直方向长度的比值。
near: (近面距离)相机到视景体最近的距离。
far: (远面距离)相机到视景体最远的距离。

2、确定相机的位置

this.camera.position.set(0, 10, 20);

3、操作相机

在很多场景下,我们需要移动相机来观察物体的各个角度,这时需要相机操作控件来控制相机的位置。常用的控制器有:OrbitControls(轨道控制器)、TrackballControls(轨迹球控制器)

OrbitControls:可以使用鼠标控制场景中的对象围绕场景中心旋转和平移
TrackballControls:可以使用鼠标(或控制球)来轻松移动、平移和缩放场景
Pointerlockcontrols:第一人称控制器,以第一人称视角观察室内场景

1)添加控制器

controls = new OrbitControls(camera, canvas);

2)设置控制器聚焦点

 controls.target.set(0, 5, 0);

四、光照

在场景中,如果没有光源,那所有的物体都将看不见。最常用的几种光源是AmbientLight、PointLight、SpotLight、DirectionalLight。
AmbientLight:环境光;全局均匀地照亮场景中的所有对象。
PointLight:点光源;从空间中的一点向所有方向发射光线。
SpotLight:聚光源;投射出的是类似圆锥形的光线。
DirectionalLight:平行光;比如太阳光。
例:

 {
    const color = 0xf1f1f1;  //光的颜色
    const intensity = 1;    //光的强度
    const light = new THREE.DirectionalLight(color, intensity);
    light.castShadow = true;  //开启castShadow生成动态的投影
    light.position.set(10, 300, 20);//设置灯光的位置
    this.scene.add(light);//将灯光添加到场景中
  }

五、渲染器

渲染器决定了渲染的结果应该画在页面的什么元素上面,首先在需要渲染的位置添加页面元素

 <canvas id="con"></canvas>

1、渲染器创建
WebGLRenderer:WebGL渲染器使用WebGL来绘制场景(如果设备支持),使用WebGL能够利用GPU硬件加速从而提高渲染性能。

  const canvas = document.querySelector("#con");
  var renderer = new THREE.WebGLRenderer({
           canvas,
           antialias: true,  //默认为false。是否开启反锯齿
           alpha: true,      //默认为false。是否可以设置背景色透明
       });

2、开始渲染

  this.renderer.render(scene, camera);

scene:前面定义的场景。
camera:前面定义的相。

3、domElement属性-canvas对象

  const canvas = this.renderer.domElement;

4、循环渲染

  requestAnimationFrame(this.render);

requestAnimationFrame(render):这个函数就是让浏览器去执行一次参数中的函数,这样通过上面render中调用requestAnimationFrame()函数,requestAnimationFrame()函数又让rander()再执行一次,就形成了循环渲染。

六、模型添加

3D模型的格式有很多种类可供选择,但每一种格式都具有不同的目的、用途以及复杂性,常用的模型有obj、gltf等等;

OBJ:是一种文本格式存储的模型文件格式,只能存储静态模型;
gltf: 以JSON(.gltf)或二进制(.glb)格式提供模型数据;glTF资源可以传递一个或多个场景,包括网格,材质,纹理,外观等等。

1、引入gltf模型加载器

import GLTFLoader from "three/examples/js/loaders/GLTFLoader";

2、实例化加载器并添加到场景中

const gltfLoader = new GLTFLoader();  //实例化加载器
       gltfLoader.load("../../../../static/gltf/zoom/waibucj.gltf", gltf => {
       const root = gltf.scene;    
       root.castShadow = true;    //  投影
       root.traverse(
       function(child) {
            if (child.isMesh) {
//设置mesh的一些属性
                child.material.metalness = 0.8;  //金属度 
                child.material.roughness = 0.3;  //粗糙度
              }
            },
            undefined,
            function(error) {
              console.error(error);
             }
);
       this.scene.add(root); //将该模型添加到场景中
      });
    }

七、环境贴图

在threejs中环境贴图就是利用三维来模拟周边的环境,它通过HDR图像来实现;

1、引入RGBELoader加载器

   import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";

2、如何加载hdr环境贴图

      //加载hdr
      {
        var that = this;
         // 使用hdr作为背景色
        var pmremGenerator = new THREE.PMREMGenerator(this.renderer);
        pmremGenerator.compileEquirectangularShader();//阴影
        new RGBELoader()
          .setDataType(THREE.UnsignedByteType)
          .load("../../../../static/gltf/env4.hdr", texture => {
            const envMap = pmremGenerator.fromEquirectangular(texture).texture;
            this.scene.environment = envMap;  // 给场景添加环境光效果
            //this.scene.background = envMap;// 给场景添加背景图
            pmremGenerator.dispose();
          });
      }

八、交互

在物联网项目中,所有三维物体与鼠标交互样式采用的是动态收缩变化的点,此方法弊端是有多少个交互位置就需要创建多少个动态点;

1、动态点实现方式

要实现效果图
在这里插入图片描述

a) 创建一个三维物体对象

 this.obj = new THREE.Object3D();

b) 创建两个圆的物体
1)外部透明的圆

  const geometry = new THREE.CylinderGeometry(8, 8, 0.2, 40, 40); //形状
        const material = new THREE.MeshPhongMaterial({
          color: 0x01cd88,   //物体颜色
          opacity: 0.15,     //物体透明度
          transparent: true
        });    //物体材质
        const cube = new THREE.Mesh(geometry, material);  //创建网格物体

2)内部的圆

        const geometry1 = new THREE.CylinderGeometry(4, 4, 1, 40, 40);
        const material1 = new THREE.MeshPhongMaterial({
          color: 0x01cd88
        });
        const cube1 = new THREE.Mesh(geometry1, material1);

3)将内部和外部圆组合在一起,添加到第一步创建的三维物体对象,并设置位置添加到场景

    this.obj.add(cube);
    this.obj.add(cube1);
    this.obj.position.set(-220, 192, 121); //设置物体位置
    this.scene.add(this.obj);   //添加到场景中

4)动画效果添加(此方法执行放在render方法中,它才会一直被执行)
//气泡框动画

    BubbleAnimation: function() {
      var rot = 0;
      if (this.mark == 1) {
        const speed = 1 - 1 * 0.1;
        rot = 0.006 * speed;
        if (this.obj.scale.x <= 1) {
          this.mark = 0;
        }
        this.obj.scale.x -= rot;
        this.obj.scale.y -= rot;
      } else {
        const speed = 1 + 1 * 0.1;
        rot = 0.006 * speed;
        if (this.obj.scale.x > 1.4) {
          this.mark = 1;
        }
        this.obj.scale.x += rot;
        this.obj.scale.y += rot;
      }
      this.obj.lookAt(this.camera.position);//使物体始终朝向摄像机
    }

九、遇到过问题

问题一:模型加载到场景中是黑色的
解决办法:
1)检查是否是模型本身导出问题。可用在线查看器查看导出的模型(https://gltf-viewer.donmccurdy.com/
2)添加环境贴图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值