three.js学习

核心概念

1、创建3D场景

1.1 三维场景Scene

可以把三维场景Scene对象理解为虚拟的3D场景,用来表示模拟生活中的真实三维场景,或者说三维世界。

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

// 给三维场景添加物体
// 定义一个几何体 定义长宽高
const geometry = new THREE.BoxGeometry(100, 100, 100)

// 创建一个材质对象
const meterial = new THREE.MeshBasicMaterial({ color: 0xff0000 })

// 创建一个网格模型对象:表示生活中的物体
const mesh = new THREE.Mesh(geometry, meterial)
mesh.position.set(0, 10, 0)

// 将网格模型添加到场景中
scene.add(mesh)

几何体

材质

1.2 虚拟相机 Camera

js 复制代码
  const width = 800
  const height = 800
 // 创建一个透视投影相机对象
  const camera = new THREE.PerspectiveCamera(50, width / height, 0.1, 3000)
  // 设置相机位置
  camera.position.set(300, 300, 300)
  // 设置相机的视线
  camera.lookAt(0, 0, 0)
  // camera.lookAt(mesh.position)

1.3 渲染器

js 复制代码
 // 创建一个WebGL渲染器
  const renderer = new THREE.WebGLRenderer()
  // 设置渲染区域尺寸
  renderer.setSize(width, height) 
  // 执行渲染操作
  renderer.render(scene, camera)
  // 把渲染结果展示在canvas画布上
  canvasContainer.value.appendChild(renderer.domElement);

2、Three.js三维坐标系

2.1 辅助观察坐标系

js 复制代码
 // 辅助坐标系  参数150表示坐标系大小,可以根据场景大小去设置
  const axesHelper = new THREE.AxesHelper(150)
  // 将坐标系添加到场景中
  scene.add(axesHelper)
js 复制代码
const meterial = new THREE.MeshBasicMaterial({ 
    color: 0x0000ff,
    transparent: true,
    opacity: 0.5
})

图黄色部分才是可视范围

3、光源对物体表面影响

基础网格材质MeshBasicMaterial不会受到光照影响。

js 复制代码
// MeshBasicMaterial不会受到光照影响
const material = new THREE.MeshBasicMaterial():

漫反射网格材质MeshLambertMaterial会受到光照影响,该材质也可以称为Lambert网格材质,音译为兰伯特网格材质。

js 复制代码
// MeshLambertMaterial会受到光照影响
const meterial = new THREE.MeshLambertMaterial()

3.1 光源介绍

点光源

点光源沿着某个点向四周发射

js 复制代码
// 创建一个点光源 
// 第一个参数表示光源颜色,第二个参数表示光源强度
const light = new THREE.PointLight(0xffffff, 1)
// 设置光源衰减率 衰减率为0表示光源不衰减
light.decay = 0
// 设置光源位置
light.position.set(400, 200, 300)
// 将光源添加到场景中
scene.add(light)

效果图

环境光

环境光AmbientLight没有特定方向,只是整体改变场景的光照明暗

js 复制代码
// 环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4)
scene.add(ambientLight)

效果图

平行光
js 复制代码
// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1)
// 设置光源位置
directionalLight.position.set(200, 200,200)
// 将光源添加到场景中
scene.add(directionalLight)

效果图

点光源辅助观察

js 复制代码
// 点光源辅助对象
const pointLightHelper = new THREE.PointLightHelper(light, 10)
scene.add(pointLightHelper)

效果图

4、相机控件轨道控制器OrbitControls

npm安装控件库

js 复制代码
npm install three @types/three

引入vue中

js 复制代码
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

代码中使用

js 复制代码
// 创建相机控件对象
const controls = new OrbitControls(camera, renderer.domElement);
// 启用控件阻尼(惯性效果)
controls.enableDamping = true; 
// 设置阻尼系数
controls.dampingFactor = 0.05;

 // 动画循环
const animate = () => {
// 调用渲染器的render方法,执行渲染操作
requestAnimationFrame(animate);
// 每次调用requestAnimationFrame方法时,都会更新相机的位置
// 必须调用,否则阻尼无效
controls.update(); 
renderer.render(scene, camera);
};
animate();

5、动画渲染循环

threejs可以借助HTML5的API请求动画帧window.requestAnimationFrame 实现动画渲染。

js 复制代码
// 周期性执行 默认每秒执行60次 可实现动画效果
const render = ()=>{
    mesh.rotateY(0.01)
    // 结合OrbitControls使用
    controls.update();
    // 周期性执行渲染操作 更新canvas到画布上的内容
    renderer.render(scene, camera);
    requestAnimationFrame(render)
}
render()

6、canvas画布宽高动态变化

js 复制代码
  const width = window.innerWidth
  const height = window.innerHeight
  
 // 窗口大小调整
  window.addEventListener("resize", onWindowResize);
  
 // 窗口大小调整时更新相机和渲染器
function onWindowResize() {
  // 更新相机的宽高比
  camera.aspect = window.innerWidth / window.innerHeight;
  // 更新相机的投影矩阵
  camera.updateProjectionMatrix();
  // 更新渲染器的尺寸
  renderer.setSize(window.innerWidth, window.innerHeight);
}

7、WebGL渲染器基础设置(锯齿模糊、背景颜色)

渲染器锯齿属性

js 复制代码
renderer = new THREE.WebGLRenderer({
    // 边界更平滑
    antialias: true,
})

设备像素比

js 复制代码
// 通用设置
  // 告诉three.js你的屏幕设备像素比window.devicePixelRatio
  renderer.setPixelRatio(window.devicePixelRatio)

设置背景色

js 复制代码
renderer.setClearColor(0x444444, 1)

8、gui.js库(可视化改变三维场景)

vue3中安装gui库

js 复制代码
npm install lil-gui

导入并且使用

js 复制代码
import GUI from "lil-gui"; // 导入 lil-gui

let gui = null

// 定义可调试的参数对象
const params = {
  x: 30,
  meshColor: '#00ffff',
  meshRotationSpeed: 0.01,
  lightIntensity: 1,
  resetScene: () => {
    mesh.rotation.set(0, 0, 0)
    mesh.material.color.set(params.meshColor)
  },
  materialType: 'MeshStandardMaterial',
}

// 10. 初始化 GUI
  initGUI();
  
const initGUI = () => {
  gui = new GUI({ title: "调试面板", width: 300 });
  
  // 添加x轴位置
  gui.add(mesh.position, "x", 0, 100)
    .name("x轴")
    .onChange((value) => {
      mesh.position.x = value;
    })

  // 添加颜色控制器
  gui.addColor(params, "meshColor")
    .name("立方体颜色")
    .onChange((value) => {
      mesh.material.color.set(value);
    });

  // 添加旋转速度滑块
  gui.add(params, "meshRotationSpeed", 0, 0.1, 0.001)
    .name("旋转速度");

  // 添加光照强度滑块
  gui.add(params, "lightIntensity", 0, 2, 0.1)
    .name("光照强度")
    .onChange((value) => {
      scene.children.forEach((child) => {
        if (child instanceof THREE.Light) {
          child.intensity = value;
        }
      });
    });

  // 添加重置按钮
  gui.add(params, "resetScene").name("重置场景");
};

效果图

gui.js库(下拉菜单、单选框)

下拉菜单

js 复制代码
// 下拉菜单

const params = {
  materialType: "MeshStandardMaterial", // 默认选项
  // ...其他参数
};
  
gui
.add(params, 'materialType', [
  'MeshBasicMaterial',
  'MeshStandardMaterial',
  'MeshPhongMaterial',
])
.name('材质类型')
.onChange((value) => {
  // 根据选项切换材质
  switch (value) {
    case 'MeshBasicMaterial':
      mesh.material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
      break
    case 'MeshStandardMaterial':
      mesh.material = new THREE.MeshStandardMaterial({ color: 0x00ff00 })
      break
    case 'MeshPhongMaterial':
      mesh.material = new THREE.MeshPhongMaterial({ color: 0x00ff00 })
      break
  }
})

单选框

js 复制代码
const params = {
  bool:true
  // ...其他参数
}

const render = () => {
    if(params.bool)mesh.rotateY(0.01)
    // ...其他内容
 }
 
gui.add(params,'bool').name('是否旋转')
效果图

gui分组

js 复制代码
const gui = new GUI({ title: '调试面板', width: 300 })

const matForder = gui.addFolder('材质')

const lightForder = gui.addFolder('光照')

const otherForder = gui.addFolder('其他')

9、查询案例和文档(辅助开发)

相关推荐
斯普信专业组3 小时前
2025 最好的Coze入门到精通教程(下)
前端·javascript·ui
德育处主任3 小时前
p5.js 圆弧的用法
前端·javascript·canvas
Arvin6274 小时前
Nginx IP授权页面实现步骤
服务器·前端·nginx
xw56 小时前
Trae安装指定版本的插件
前端·trae
默默地离开6 小时前
前端开发中的 Mock 实践与接口联调技巧
前端·后端·设计模式
南岸月明6 小时前
做副业,稳住心态,不靠鸡汤!我的实操经验之路
前端
嘗_6 小时前
暑期前端训练day7——有关vue-diff算法的思考
前端·vue.js·算法
MediaTea6 小时前
Python 库手册:html.parser HTML 解析模块
开发语言·前端·python·html
杨荧6 小时前
基于爬虫技术的电影数据可视化系统 Python+Django+Vue.js
开发语言·前端·vue.js·后端·爬虫·python·信息可视化
BD_Marathon7 小时前
IDEA中创建Maven Web项目
前端·maven·intellij-idea