一个案例带你从零入门Three.js,深度好文!

简介

本教程无需任何Threejs知识!本教程以入门为主,带你快速了解Three.js开发。

基础3D案例

如图,我们创建一个基础3D场景,大致需要下面几步:

  • 项目创建
  • 创建3D场景Scene
  • 创建几何体Geometry模型
  • 创建虚拟相机Camera设置几何体观察角度
  • 渲染3D场景到DOM上

vue项目创建

依赖安装

我们使用vite + vue3进行项目搭建,安装threejs依赖

js 复制代码
项目搭建
npm install three

在componets中定义一个QuickStart.vue文件,用于写代码。

js 复制代码
<template>
  <div ref="threeContainer"></div>
</template>

<script setup>
import * as THREE from "three";
import { onMounted, ref } from "vue";
// 创建3D场景渲染的DOM引用容器
const threeContainer = ref(null);



</script>

<style scoped></style>

在App.vue中引入QuickStart组件

创建3D场景Scene

场景很好理解,就是展示3D模型的三维空间。(你可以想像,默认的场景,就是是一团虚无的黑色混沌世界)

js 复制代码
// 创建3D场景对象Scene
const scene = new THREE.Scene();

创建几何体Geometry模型

创建一个物体模型,分为如下几步:

  • 创建不同类型的几何体(长方体、圆柱体球体等)
  • 设置物体材质Material(物体的颜色、表面能不能反射光等)
  • 使用材质和几何体生成一个物体的网格模型mesh
  • 设置网格模型mesh在场景scene中的位置
  • 网格模型mesh添加到3D场景scene中

创建几何体

Three.js提供了各种各样的几何体API,用来表示三维物体的几何形状。

我们创建一个长方体,并设置长宽高为100

js 复制代码
//创建一个长方体几何对象Geometry
const geometry = new THREE.BoxGeometry(100, 100, 100); 

设置物体材质Material

如果你想定义物体的外观效果,就需要通过材质Material相关的API实现。threejs提供很多材质

不同材质渲染效果不同,我们使用最简单的网格基础材质 MeshBasicMaterial创建一个蓝色的材质效果

js 复制代码
//创建一个材质对象Material
const material = new THREE.MeshBasicMaterial({
    color: 'blue'
}); 

生成物体的网格模型mesh

有了几何体和物体的材质,我们就可以生长物体的网格模型mesh了

js 复制代码
// 两个参数分别为几何体geometry、材质material
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh

模型位置position

实际生活中,一个物体往往是有位置的,对于threejs而言也是一样的,你可以通过位置属性.position定义网格模型Mesh在三维场景Scene中的位置。

js 复制代码
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
//设置网格模型在三维空间中的位置坐标,默认是坐标原点
mesh.position.set(0,10,0);

将模型添加到3D场景scene中

js 复制代码
scene.add(mesh); 

使用虚拟相机观察模型

观察角度不同,物体展示给人的样子也不同。在3D建模中,我们使用相机来表示一个物体的观察角度。

其过程如下

  • 创建一个相机
  • 设置相机位置
  • 相机观察目标

创建一个相机

js 复制代码
// 实例化一个透视投影相机对象
const camera = new THREE.PerspectiveCamera();

设置相机位置.position

相机可以位于3D场景中的任意一个位置,因此我们需要基于坐标圆点设置

arduino 复制代码
//相机在Three.js三维坐标系中的位置
// 根据需要设置相机位置具体值
camera.position.set(200, 200, 200); 

相机观察目标.lookAt()

我们观察一个目标时,会注视物体的不同位置,看到的东西也是不一样的。我们可以直接观察模型的中心点

js 复制代码
camera.lookAt(mesh.position);//指向mesh对应的位置

渲染3D场景到DOM上

要将3D场景渲染到DOM上需要如下几步操作

创建渲染器对象

js 复制代码
// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();

设置渲染尺寸

js 复制代码
// 定义threejs输出画布的尺寸(单位:像素px)
const width = 800; //宽度
const height = 500; //高度
renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)

渲染

js 复制代码
renderer.render(scene, camera); //执行渲染操作

挂载

js 复制代码
onMounted(() => {
  threeContainer.value.appendChild(renderer.domElement);
});

完整代码

js 复制代码
<template>
  <div class="wrap" ref="threeContainer"></div>
</template>

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

const threeContainer = ref(null);

// 1、创建3D场景对象Scene
const scene = new THREE.Scene();

// 2、创建几何体Geometry模型
const geometry = new THREE.BoxGeometry(100, 100, 100);
const material = new THREE.MeshBasicMaterial({
  color: "blue", 
});
const mesh = new THREE.Mesh(geometry, material); 
scene.add(mesh);

// 3、使用虚拟相机观察模型
const camera = new THREE.PerspectiveCamera();
camera.position.set(200, 200, 200);
camera.lookAt(mesh.position); //坐标原点

// 4、渲染3D场景到DOM上
const width = 800; //宽度
const height = 500; //高度
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
renderer.render(scene, camera);
onMounted(() => {
  threeContainer.value.appendChild(renderer.domElement);
});
</script>

<style scoped></style>

三维坐标系

辅助观察坐标系

THREE.AxesHelper()的参数表示坐标系坐标轴线段尺寸大小,你可以根据需要改变尺寸

js 复制代码
// AxesHelper:辅助观察的坐标系
const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);

three.js坐标轴颜色红R 、绿G 、蓝B 分别对应坐标系的xyz 轴,对于three.js的3D坐标系默认y轴朝上

材质半透明设置

我们可以设置材质半透明,方便看到坐标系的坐标原点。

js 复制代码
const material = new THREE.MeshBasicMaterial({
    color: 0x0000ff, //设置材质颜色
    transparent:true,//开启透明
    opacity:0.5,//设置透明度
});

设置模型在坐标系中的位置或尺寸

设置长方体xyz不同方向尺寸

js 复制代码
// 设置几何体长宽高,也就是x、y、z三个方向的尺寸
//对比三个参数分别对应xyz轴哪个方向
new THREE.BoxGeometry(100, 60, 20);

改变位置

js 复制代码
// 设置模型mesh的xyz坐标
mesh.position.set(90,0,0);

改变相机参数

js 复制代码
camera.position.set(-200, 200, 200);
camera.lookAt(0, 0, 0); //坐标原点

现在我们观察的位置是(0,0,0),相机的位置位于(-200,200,200),如果我们把相机的位置改为(-200,0,0),此时看到的应该是模型的一个后视图

添加地面网格

js 复制代码
// 添加网格地面
const gridHelper = new THREE.GridHelper(200, 10);
scene.add(gridHelper);

动画

threejs中最简单的动画实现方式就是不同角度重复渲染场景。

js 复制代码
// 动画
renderer.setAnimationLoop(animation);
function animation(time) {
  mesh.rotation.x = time / 2000;
  mesh.rotation.y = time / 1000;
  renderer.render(scene, camera);
}

.setAnimationLoop ( callback : Function ) : undefined

callback --- 每个可用帧都会调用的函数。 如果传入'null',所有正在进行的动画都会停止。

结尾

通过本示例,相信你对threejs已经有了基础认识,接下来,请关注我,继续深入学习吧!

教程概览:

轨道控制器 场景及坐标轴

透视相机

纹理贴图与环境贴图

UV坐标

三维物体与三维向量

剩下的不展示了,太多了,点赞收藏,快来追更吧!

相关推荐
我要洋人死1 小时前
导航栏及下拉菜单的实现
前端·css·css3
科技探秘人1 小时前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人1 小时前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR1 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q2498596931 小时前
前端预览word、excel、ppt
前端·word·excel
小华同学ai1 小时前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
Gavin_9151 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼2 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
逐·風6 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#