three.js的使用

以创建一个立方体为例
image

安装

安装three:npm i three
image

使用

引用

引入three以及three中自带的相机控件OrbitControls用以操控相机:
image

初始化场景

scene:场景所有three事物均在其中。
camera:使用PerspectiveCamera透视相机,参数需注意调整否则会看不见物体与场景,参数依次为:fov视场,即可看到的角度范围,aspect长宽比,通常为窗口长宽比,near近面,基于相机位置开始渲染场景的位置一般较小默认0.1,far远面,基于相机位置结束渲染场景的位置,过大会影响渲染效率默认1000。
renderer:渲染器,用于生成canvas及设置其参数,需要将其appendChild至dom中指定元素。
image

天空盒子

创建天空盒子(一个包裹场景物体的立方体,可随鼠标拖动而变化角度),其中六张立方体贴图对应的顺序是右、左、上、下、前、后,图片需是特别制作的全景图,否者场景世界会出现明显的拼接边角:
image
也可直接使用一张贴图作为场景的背景,但使用此法场景不会随着鼠标变换角度与缩放:
image

相机控件

创建相机控件,其中需将相机与渲染的canvas元素添加到控件OrbitControls中,可通过控件控制拖拽、缩放、阻尼、偏角、自转(此种自转方式区别于模型自转,模型自转是通过控制物体mesh的rotation实现自转,该文章使用的是模型自转)等:
image

光源

创建光源,可设置环境光、点光源,最终显示出的光影效果是通过各种光效一起计算后渲染出来的:
image

立方体

创建的mesh(可理解为创建的物体)都是要通过add添加到场景中的,而mesh中有geometry(几何体)与material(材质),立方体的geometry可以利用three的BoxGeometry,而material可以使用MeshLambertMaterial材质,该材质对光照有反应,用于创建暗淡的不发光的物体,自身可设置颜色,自身颜色不受环境的影响。也可给材质设置纹理map(需导入图片作为纹理):
image

持续渲染

对场景与相机进行持续渲染,其中requestAnimationFrame为请求动画帧,以60hz刷新(但在高刷新屏中会频繁触发),用户切换标签时会暂停渲染,节省cpu开销。鼠标控件需要在渲染中调用update()更新:
image

完整代码

<template>
  <div class="three-div">
    <div id="container">
      <!--画布的容器-->
    </div>
  </div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; //鼠标控制
import cubeImg from "@/assets/img/cube.png";
import BgImg from "@/assets/img/bg.png";
import right from "@/assets/img/space/right.jpg";
import left from "@/assets/img/space/left.jpg";
import top from "@/assets/img/space/top.jpg";
import bottom from "@/assets/img/space/bottom.jpg";
import front from "@/assets/img/space/front.jpg";
import back from "@/assets/img/space/back.jpg";
export default {
  components: {},
  data() {
    return {
      scene: "", //场景
      camera: "", //相机
      renderer: "", //渲染器
      mouseControls: "", //轨道控制
      pointLight: "", //点光源
      ambientLight: "", //环境光
      cube: "", //立方体
      cubeImg: cubeImg, //立方体贴图
    };
  },
  mounted() {
    this.init();
  },
  methods: {
    //初始化场景
    init() {
      this.scene = new THREE.Scene(); //新建场景
      let width = window.innerWidth; //窗口宽度
      let height = window.innerHeight; //窗口高度
      let k = width / height; //窗口宽高比
      this.camera = new THREE.PerspectiveCamera(60, k, 0.1, 10); //透视相机
      this.camera.position.set(0, 0, 2.5); //设置相机位置
      //创建渲染器
      this.renderer = new THREE.WebGLRenderer({
        antialias: true, //抗锯齿
        alpha: true,
      });
      this.renderer.setSize(width, height); //设置渲染区域尺寸
      document
        .getElementById("container")
        .appendChild(this.renderer.domElement); //将画布添加到container中
      let axes = new THREE.AxesHelper(1); //坐标系(辅助开发)
      axes.rotation.x = 0.1;
      // this.scene.add(axes);
      this.createSkyBox();
      // this.createUniverse();
      this.createOrbitControls();
      this.createLight();
      this.createCube();
      this.repeatRender();
    },

    //创建天空盒子
    createSkyBox() {
      //加载天空盒子纹理
      let cubeTexture = new THREE.CubeTextureLoader().load(
        [right,left,top,bottom,front,back]
      );
      this.scene.background = cubeTexture; //设置场景背景
    },

    //创建宇宙背景
    createUniverse(){
      let texture = new THREE.TextureLoader().load(BgImg);//加载背景贴图
      this.scene.background = texture;//设置场景背景
    },

    //创建轨道控制
    createOrbitControls() {
      //没有缩放阻尼
      this.mouseControls = new OrbitControls(
        this.camera,
        this.renderer.domElement
      ); //创建控件对象
      this.mouseControls.enablePan = false; //右键平移拖拽
      this.mouseControls.enableZoom = true; //鼠标缩放
      this.mouseControls.minDistance = 2; //相机距离原点的距离范围
      this.mouseControls.maxDistance = 5;
      this.mouseControls.enableDamping = true; //滑动阻尼
      this.mouseControls.dampingFactor = 0.1; //(默认.25)
      this.mouseControls.maxPolarAngle = (Math.PI / 4) * 3; //y旋转角度范围
      this.mouseControls.minPolarAngle = Math.PI / 4;
        // this.mouseControls.autoRotate = true; //自转(相机)
        // this.mouseControls.autoRotateSpeed = 5; //自转速度
    },

    //创建光源
    createLight() {
      this.ambientLight = new THREE.AmbientLight(0x666666); //设置环境光
      this.scene.add(this.ambientLight); //将环境光添加到场景中
      this.pointLight = new THREE.PointLight(0xffffff, 1, 0);
      this.pointLight.position.set(200, 200, 200); //设置点光源位置
      this.scene.add(this.pointLight); //将点光源添加至场景
    },

    //创建立方体
    createCube() {
      let geometry = new THREE.BoxGeometry(1, 1, 1); //几何体
      //材质
      let material = new THREE.MeshLambertMaterial({
        map: new THREE.TextureLoader().load(this.cubeImg), //导入图片纹理
      });
      this.cube = new THREE.Mesh(geometry, material); //将几何体与材质添加到网格中
      this.cube.rotation.set(10, 10, 0);
      this.scene.add(this.cube); //将立方体网格添加到场景中
    },

    //重复渲染
    repeatRender() {
      //请求动画帧,屏幕每刷新一次调用一次,绑定屏幕刷新频率
      requestAnimationFrame(this.repeatRender);
      this.mouseControls.update(); //实时更新轨道控制
      this.cube.rotation.y += .01;//以y为轴心的旋转角度每帧自加0.01
      this.renderer.render(this.scene, this.camera); //将场景和相机进行渲染
    },
  },
};
</script>
<style scoped>
</style>

图片素材

天空盒子贴图

back.jpg:
image
bottom.jpg:
image
front.jpg:
image
left.jpg:
image
right.jpg:
image
top.jpg:
image

立方体贴图

cube.png:
image

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值