likes
comments
collection
share

ThreeJS之GLB 预览

作者站长头像
站长
· 阅读数 6

主要介绍了预览 3D 文件的插件,如 vue-model-viewer、vue-3d-model、@google/model-viewer;也介绍了 three.js 的基础使用及配置,例如场景、相机、渲染器、轨道控制器、灯光等等

第三方插件

找到了如下第三方插件,用起来挺方便的,支持多种 3D 文件格式,包括 glb、gltf 等

但是不支持vue2.x,只支持vue3.x版

  1. vue-model-viewer:提供了一个 Vue 组件,使在 Vue 项目中集成和使用更加方便;支持多种 3D 文件格式,包括 glb、gltf 等
  2. vue-3d-model:简单易用,适合快速集成 3D 模型预览功能;支持多种 3D 文件格式
  3. @google/model-viewer:提供了丰富的交互和功能,如 AR 支持、动画、交互等。

正方体预览(three.js)

有一个红色的正方体 Box.glb 文件,

GLTF 在线编辑器中预览效果如下所示:

ThreeJS之GLB 预览

项目之前用的是vue2.x版本,没法用上面的第三方工具,用three.js渲染展示

使用 three.js 预览,代码如下所示:

<template>
  <div ref="container" style="width: 400px; height: 300px;"></div>
</template>

<script lang="ts">
// 导入three.js
import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 导入gltf加载器
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";

// 使用的是vue2.6.11版本
@Component
export default class bookUpload extends Vue {
  mounted() {
    this.initScene();
  }

  initScene() {
    // 创建场景
    const scene = new THREE.Scene();
    // 创建相机
    const camera = new THREE.PerspectiveCamera(75, 400 / 300, 0.1, 1000);
    // 创建渲染器
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(400, 300);
    // 获取渲染元素
    const container = this.$refs.container as HTMLElement;
    container.appendChild(renderer.domElement);

    // 添加光源
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
    scene.add(ambientLight);
    const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); // 方向光颜色和强度
    directionalLight.position.set(1, 1, 1); // 光源位置
    scene.add(directionalLight);

    // 创建控制器
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true; // 允许阻尼效果,使动画更平滑
    controls.dampingFactor = 0.05; // 阻尼系数
    controls.rotateSpeed = 0.1; // 旋转速度

    // 加载3D模型
    const loader = new GLTFLoader();
    loader.load("/Box.glb", (gltf) => {
      console.log("gltf.scene", gltf.scene);
      scene.add(gltf.scene);
    });

    // 设置相机在 z 轴上的位置
    camera.position.z = 5;

    const animate = () => {
      requestAnimationFrame(animate);
      controls.update(); // 更新控制器状态
      renderer.render(scene, camera);
    };

    animate();
  }
}
</script>

预览效果如下图所示:

ThreeJS之GLB 预览

3. 3D 图形预览(three.js)

// 初始化
this.$nextTick(() => {
  this.list.forEach((item) => {
    this.initScene(item);
  });
});

// 渲染3D
initScene(item) {
  // 1. 创建场景
  const scene = new THREE.Scene();
  // 设置背景色
  scene.background = new THREE.Color(0xffffff);
  // 设置背景图片(CubeTexture立方纹理 创建一个由6张图片所组成的纹理对象 左右上下前后)
  // 设置背景图片(没生效,估计地址配置的不对 /public/img)
  // scene.background = new THREE.CubeTextureLoader()
  //     .setPath("/img/")
  //     .load(["1.png", "2.png", "3.png", "4.png", "5.png", "6.png"]);
  // 添加雾(配置的7,视角远一点 可以看到效果)
  const fog = new THREE.Fog(0xcccccc, 0, 7);
  scene.fog = fog;

  // 2. 创建相机
  // PerspectiveCamera透视相机,模拟人眼看到的景象,是3D场景中使用最普遍的投影模式
  const camera = new THREE.PerspectiveCamera(75, 300 / 300, 0.1, 1000);
  camera.position.z = 3; // 设置相机在 z 轴上的位置
  camera.position.y = 1;

  // (1)创建立方体
  const box = new THREE.BoxGeometry();
  // 创建材质(MeshBasicMaterial基础网格材质 不受光照影响)
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });

  // 创建网格
  const cube = new THREE.Mesh(box, material);
  cube.position.set(1, 1, 0);
  scene.add(cube);

  // 3. 创建渲染器
  const renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(300, 300); // 设置大小
  renderer.setClearColor(0xffffff, 0); // 设置背景颜色 默认黑色
  renderer.shadowMap.enabled = true; // 添加阴影的渲染

  // 获取渲染元素
  const container = document.getElementById(item.id) as HTMLElement;
  container.appendChild(renderer.domElement);

  // 添加网格地面
  const gridHelper = new THREE.GridHelper(10, 10);
  scene.add(gridHelper);

  // 添加坐标轴
  const axesHelper = new THREE.AxesHelper(5);
  scene.add(axesHelper);

  // 添加环境光
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
  scene.add(ambientLight);

  // 添加平行光(需要设置位置)
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); // 光颜色和强度
  directionalLight.position.set(1, 1, 1); // 光源位置
  scene.add(directionalLight);
  // 添加灯光辅助
  scene.add(new THREE.PointLightHelper(pointLight, 100));

  // 添加点光源(看投影效果)
  const pointLight = new THREE.PointLight(0xffffff, 1);
  pointLight.power = 500; // 设置亮度
  pointLight.castShadow = true;
  pointLight.position.set(2, 2, 2);
  scene.add(pointLight);

  // 4. 创建轨道控制器(调整相机位置,即视角位置)
  const controls = new OrbitControls(camera, renderer.domElement);
  // 监听控制器改变事件
  // controls.addEventListener("change", () => {
  //   console.log("change");
  // });
  controls.enableDamping = true; // 允许阻尼效果,使动画更平滑
  controls.dampingFactor = 0.05; // 阻尼系数
  controls.rotateSpeed = 0.1; // 旋转速度
  controls.autoRotate = true; // 自动旋转
  controls.autoRotateSpeed = 0.5; // 自动旋转速度

  // (2)加载3D模型
  // 创建GLTF实例
  const loader = new GLTFLoader();
  // 加载模型
  loader.load(
    item.nftFileUrl,
    (glb) => {
      console.log("glb.scene", glb.scene);
      // 遍历模型中的物体
      glb.scene.traverse((child) => {
        child.castShadow = true; // 设置物体投影
        child.receiveShadow = true; // 设置物体接收阴影
      })
      // 添加到场景
      scene.add(glb.scene);
    }
  );

  // 5. 动起来
  const animate = () => {
    requestAnimationFrame(animate);
    controls.update(); // 更新控制器状态
    cube.rotation.x += 0.01; // 让立方体旋转起来
    renderer.render(scene, camera); // 重新渲染
  };

  animate();
}

注意:通过 GLTFLoader 加载模型后,是一片黑色的,首先考虑灯光问题,需要添加灯光。AmbientLight 为环境光;DirectionalLight 为平行光;PointLight为点光源

ThreeJS之GLB 预览

ThreeJS之GLB 预览

  • 官方文档:Three.js
  • Blender是一款免费开源三维图形图像软件,提供从建模、动画、材质、渲染、到音频处理、视频剪辑等一系列动画短片制作解决方案。