vue3使用three.js引入3D模型文件

一、引入threejs依赖包

1. 终端安装three依赖包

npm i three -S

2. 组件引入threejs

import * as THREE from 'three';

二、创建threejs容器

<template>

  <div>

    <canvas id="three"></canvas>

  </div>

</template>

三、创建threejs应用场景

三要素:scene,render,carmea

1.创建scene

const scene = new THREE.Scene();

scene可以理解为我们将要渲染的环境、背景

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

2. 获取threejs的容器(render)

const threeDemo = document.getElementById("three");

创建WebGLRenderer,将容器配置参数传入

const renderer = new THREE.WebGLRenderer({canvas: threeDemo, antialias: true});

3.创建threejs的相机(carmea)

常用两种相机实例:

        PerspectiveCamera(透视摄像机): 模拟人眼所看到的景象,物体的大小会受远近距离的影响,它是3D场景的渲染中使用得最普遍的投影模式。

OrthographicCamera(正交投影摄像机): 不具有透视效果,即物体的大小不受远近距离的影响;

  const camera = new THREE.PerspectiveCamera(
    30, 
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  )

PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )具有四个参数:

  • fov — 摄像机视锥体垂直视野角度。可以理解为人类的视野广度。
  • aspect — 摄像机视锥体横纵比。渲染结果的横向尺寸和纵向尺寸的比值,这里使用的是 浏览器窗口的宽高比。
  • near — 摄像机视锥体近端面。一切比近面更近的事物将不被渲染。
  • far — 摄像机视锥体远端面。一切比远面更远的事物将不被渲染,但是设置过大可能会影响性能。

生成的camera默认是放在中心点(0,0,0)的,但这是待会模型要放的位置,因此,我们把摄像机挪个位置:

camera.position.z = 10

4. Three.js 需要一个动画循环函数,Three.js 的每一帧都会执行这个函数。

function annimate(scene, renderer, camera) {
  renderer.render(scene, camera);
  requestAnimationFrame(annimate);
}

现在生成了一个灰色背景没有任何物体的threejs场景,vue代码:

<template>
  <div>
    <canvas id="three"></canvas>
  </div>
</template>

<script setup>
import * as THREE from 'three';
import { onMounted } from "vue";

function initThree() {
  const scene = new THREE.Scene();
  scene.background = new THREE.Color("#eee");

  const threeDemo = document.getElementById("three");
  const renderer = new THREE.WebGLRenderer({canvas: threeDemo, antialias: true});
  const camera = new THREE.PerspectiveCamera(
    30, 
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  )
  camera.position.z = 10;

  function annimate() {
    renderer.render(scene, camera);
    requestAnimationFrame(annimate);
  }
  annimate()
};



onMounted(() => {
  initThree();
})
</script>

<style scoped lang="less">
#three {
  width: 100vw;
  height: 100vh;
  position: absolute;
  top: 0;
  left: 0;
}
</style>

四、引入3D模型

1. 引入threejs加载3d模型的js文件
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";

可根据不同的3D模型文件格式引入不同的加载文件

  • fbx - import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
  • obj - import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
  • collada - import { ColladaLoader } from "three/examples/jsm/loaders/ColladaLoader";

  • gltf - import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";

2. 获取3D模型文件

获取sketchfab3D模型文件链接icon-default.png?t=N7T8https://sketchfab.com/

下载好后,解压,放进项目文件的public目录。

3. 声明一个加载器,加载我们下载的模型,并把它添加到场景中
  const gltfLoader = new GLTFLoader();
  gltfLoader.load("/seraphine/scene.gltf", (gltf) => {
    let model = gltf.scene;
    scene.add(model);
  })

场景里有了模糊的黑色的小人,这是因为我们还没有给她添加纹理。

4. 使用threejs给3d模型添加纹理
  gltfLoader.load("/seraphine/scene.gltf", (gltf) => {
    let model = gltf.scene;
    // 添加以下代码
    // 遍历模型
    model.traverse((obj) => {
      // 将图片作为纹理加载
      let imgTexture = new THREE.TextureLoader().load("/seraphine/textures/Mat_cwfyfr1_userboy17.bmp_diffuse.png");
      // 调整纹理图的方向
      imgTexture.flipY = false;
      // 将纹理图生成材质
      const material = new THREE.MeshBasicMaterial({
        map: imgTexture,
      })
      obj.material = material;
    })

    scene.add(model);
  })

此时,小人就带了颜色了

模糊原因:原因是设备的物理像素分辨率与CSS像素分辨率的比值的问题,我们的canvas绘制出来后图片因为高清屏设备的影响,导致图片变大,然而我们在浏览器的渲染窗口并没有变大,因此图片会挤压缩放使得canvas画布会变得模糊。

修改它我们要用到devicePixelRatio这个属性(此属性返回当前显示设备的物理像素分辨率与CSS像素分辨率的比值。该值也可以被解释为像素大小的比例:即一个CSS像素的大小相对于一个物理像素的大小的比值。)

添加函数:

  function resizeDevicePixel(renderer) {
    const canvas = renderer.domElement
        let width = window.innerWidth
        let height = window.innerHeight
        let devicePixelWidth = canvas.width / window.devicePixelRatio
        let devicePixelHeight = canvas.height / window.devicePixelRatio

        const needResize = devicePixelWidth !== width || devicePixelHeight !== height
        if (needResize) {
          renderer.setSize(width, height, false)
        }
        return needResize
  }

在animate函数内调用它:

  function annimate() {
    renderer.render(scene, camera);
    requestAnimationFrame(annimate);

    // 添加以下代码
    if(resizeDevicePixel(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }
  }

5. 添加轨道控制器 让模型动起来

引入轨道控制器

import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

创建轨道控制变量

 const controls = new OrbitControls(camera, renderer.domElement);

在annimate函数调用(要写在最前面)

    controls.update()

现在拉近可以看见近脸

五、添加光与影子

先加个地板,Three.js里物体(一般叫网格Mesh)由两部分构成,一是它的形状,二是它的材质,我们给地板创建它们:

  let floorGeometry = new THREE.PlaneGeometry(3000, 3000)
  let floorMaterial = new THREE.MeshPhongMaterial({ color: "#7e7ab0" })

平面几何体,PlaneGeometry(width : Float, height : Float, widthSegments : Integer, heightSegments : Integer)

  • width — 平面沿着X轴的宽度。默认值是1。
  • height — 平面沿着Y轴的高度。默认值是1。
  • widthSegments — (可选)平面的宽度分段数,默认值是1。
  • heightSegments — (可选)平面的高度分段数,默认值是1。

Phong网格材质(MeshPhongMaterial):是一种用于具有镜面高光的光泽表面的材质。

生成Mesh,并添加到场景中:

  let floorMesh = new THREE.Mesh(floorGeometry, floorMaterial);
  floorMesh.rotation.x = -0.5 * Math.PI;
  floorMesh.receiveShadow = true;
  floorMesh.position.y = -0.001;
  scene.add(floorMesh);

现在还是黑的,还需要加光

添加平行光:

  const dirLight = new THREE.DirectionalLight(0xffffff, 0.6)
  //光源等位置
  dirLight.position.set(-10, 8, -5)
  //可以产生阴影
  dirLight.castShadow = true
  dirLight.shadow.mapSize = new THREE.Vector2(1024, 1024)
  scene.add(dirLight)

平行光一般用来模拟太阳光,DirectionalLight( color : Integer, intensity : Float )

  • color - (可选参数) 16进制表示光的颜色。 缺省值为 0xffffff (白色)。
  • intensity - (可选参数) 光照的强度。缺省值为1。

添加半球光光源:

  const hemLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6)
  hemLight.position.set(0, 48, 0)
  scene.add(hemLight)

半球光光源直接放置于场景之上,光照颜色从天空光线颜色渐变到地面光线颜色。

  • skyColor - (可选参数) 天空中发出光线的颜色。 缺省值 0xffffff。
  • groundColor - (可选参数) 地面发出光线的颜色。 缺省值 0xffffff。
  • intensity - (可选参数) 光照强度。 缺省值 1。

想要产生影子,还需要在renderer下添加:

  const renderer = new THREE.WebGLRenderer({ canvas: threeDemo, antialias: true });
  // ++++++
  renderer.shadowMap.enabled = true;

以及:

    model.traverse((obj) => {
      // 将图片作为纹理加载
      let imgTexture = new THREE.TextureLoader().load("/seraphine/textures/Mat_cwfyfr1_userboy17.bmp_diffuse.png");
      // 调整纹理图的方向
      imgTexture.flipY = false;
      // 将纹理图生成材质
      const material = new THREE.MeshBasicMaterial({
        map: imgTexture,
      })
      obj.material = material;

      //加这句,让模型等每个部分都能产生阴影
      if (obj.isMesh) {
        obj.castShadow = true
        obj.receiveShadow = true
      }
    })

给场景添加雾化效果:

  const scene = new THREE.Scene();
  scene.background = new THREE.Color("#eee");
  // +++++
  scene.fog = new THREE.Fog('#eee', 20, 100)

最终效果:

  • 15
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 在Vue中加载3D模型需要使用Three.js库。首先,需要在Vue项目中安装Three.js库。然后,可以使用Three.js提供的Loader加载3D模型文件,例如OBJ、FBX、GLTF等格式。加载完成后,可以将模型添加到场景中进行渲染。具体的实现可以参考Three.js的官方文档和示例代码。 ### 回答2: 使用vue实现three.js3D模型加载需要以下步骤: 1. 安装three.js库 在vue项目中使用three.js需要先安装three.js库。可以通过npm安装: ```npm install three --save``` 安装后,可以通过需要使用three.js的组件中引入库: ```import * as THREE from 'three'``` 2. 创建场景、相机、渲染器 在vue组件内部需要先创建基本的场景、相机和渲染器组件: ```javascript mounted() { //创建场景 this.scene = new THREE.Scene(); //创建相机 this.camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000); //创建渲染器 this.renderer = new THREE.WebGLRenderer({ antialias: true }); this.renderer.setSize(window.innerWidth, window.innerHeight); this.renderer.setClearColor('#F5F5F5', 1.0); //将渲染器添加到页面中 this.$refs.box.appendChild(this.renderer.domElement); } ``` 其中,mounted()生命周期函数是在vue组件加载完毕后需要去执行的函数。 3. 加载模型 加载模型需要借助于GLTFLoader库,可以通过npm安装依赖: ```npm install three-gltf-loader --save``` 加载gltf格式的模型需要加载器: ```javascript import { GLTFLoader } from 'three-gltf-loader'; mounted() { //创建GLTFloader对象 this.loader = new GLTFLoader(); //加载模型 this.loader.load(url, object => { this.scene.add(object.scene); this.animate(); }); } ``` 其中,url是需要加载的模型地址,object是加载完成后的对象。 4. 更新场景 ```javascript methods: { animate() { this.renderer.render(this.scene, this.camera); //转动,可以忽略 window.requestAnimationFrame(this.animate); this.scene.rotation.y += 0.01; } } ``` 其中,animate()方法是更新场景的方法。在该方法中需要更新场景的内容,并进行渲染。 5. 完整代码展示 ```javascript <template> <div ref="box"></div> </template> <script> import * as THREE from 'three'; import { GLTFLoader } from 'three-gltf-loader'; export default { data() { return { scene: null, camera: null, renderer: null, loader: null } }, mounted() { //创建场景 this.scene = new THREE.Scene(); //创建相机 this.camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000); //创建渲染器 this.renderer = new THREE.WebGLRenderer({ antialias: true }); this.renderer.setSize(window.innerWidth, window.innerHeight); this.renderer.setClearColor('#F5F5F5', 1.0); //将渲染器添加到页面中 this.$refs.box.appendChild(this.renderer.domElement); //创建GLTFloader对象 this.loader = new GLTFLoader(); //加载模型 this.loader.load(url, object => { this.scene.add(object.scene); this.animate(); }); }, methods: { animate() { this.renderer.render(this.scene, this.camera); //转动,可以忽略 window.requestAnimationFrame(this.animate); this.scene.rotation.y += 0.01; } } } </script> ``` 这就是vuethree.js加载3D模型的完整教程,希望对你有所帮助。 ### 回答3: Vue是一种流行的JavaScript框架,而three.js是一个强大的WebGL库,用于创建和呈现3D图形。将Vuethree.js结合使用,可以在Vue应用程序中轻松加载和处理3D模型。 要在Vue中加载3D模型,首先需要安装three.js库。可以使用npm或yarn等包管理工具安装它。然后在Vue应用程序中导入该库并创建一个Scene对象。场景是three.js中用于呈现所有3D对象的容器。 然后需要定义一个渲染器,将场景渲染到屏幕上。在Vue中,可以在组件的mounted钩子函数中定义渲染器。需要将渲染器的DOM元素设置为Vue组件的$el属性。 现在就可以加载3D模型了。可以使用three.js中的Loader方法加载3D模型文件three.js支持多种3D模型格式,如OBJ、STL和GLTF。加载完成后,将3D对象添加到场景中即可。 由于Vue具有响应式数据绑定的特性,可以在Vue组件中轻松地控制3D模型的属性,比如位置、旋转和缩放。只需在Vue组件中定义数据模型,并在模板中使用数据绑定即可。 在Vue使用three.js创建3D场景需要一些基本的知识,但很容易上手。可以使用Vuethree.js创建漂亮的3D场景和模型,从而增强Vue应用程序的用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值