Three.js 入门指南:让网页“立体”起来的秘密

21 阅读3分钟

前言

在上篇文章中,我们学习了如何去创建一个基础的 3D 内容,而在上篇文章中,我们可以看到我们构建的内容可以看作是一个静止不动的平面,没有 3D 物体的透视感。这节课我们便来学习如何让物体具有“立体感” 与 如何能够控制视角的移动。

光照(让物体有了立体感)

原理

在 3D 世界中,如果想要一个物体具有立体感,我们需要让这个物体的表面具有一定的明暗关系,这时我们便需要将物体的材质更换为具有反射的材质。然后通过一个光源对物体进行照射,从而使得物体表面具有一定的明暗变化,最终使得物体具有 "立体感" 。

材质的改变

在本节,我们通过将材质更改为 MeshLambertMaterial 使得物体表面的材质不再是光滑的表面,他会使得物体的表面具有反射的效果,从而使得不同的位置具有不同的明暗效果。

const material = new THREE.MeshLambertMaterial({
	color: 0x00ffff,
	side: THREE.DoubleSide, // 决定你的材质是单面还是双面
})

光照

在具有一个能够处理反射的物体后,还需要一个具有衰减的光源来照射物体。从而使得物体表面的亮度具有一定的衰减趋势,而通过点光源便能很好的满足我们的需求。

const light = new THREE.PointLight(0xffffff, 0.4)
light.position.set(500, 300, 200)
scene.add(light)

OrbitControls.js(开启旋转缩放等功能)

原理

在 3D 世界中,所谓的旋转与缩放等操作,实际上就是更改摄像机的位置信息。并且根据上一篇文章,我们得知,当我们想看到摄像机的内容时,我们需要重新渲染当前的视图。因此,我们需要对摄像机的信息进行监听,在其发生变化后重新进行渲染。

const controls = new THREE.OrbitControls(camera, render.domElement)
controls.addEventListener('change', () => {
	// 监听然后重新渲染
	render.render(scene, camera)
})

一些可能用到的 API

minDistance / maxDistance

用于限制可以移动的最大和最小距离

autoRotate

autoRotate 指的是自动旋转,但需要搭配 update 方法与 定时渲染方法 进行使用(这里下一篇文章会涉及到)

示例代码

  // 创建三维场景
  const scene = new THREE.Scene()

  // 创建一个正方形
  const geometry = new THREE.BoxGeometry(100, 100, 100)
  // 创建一个材质
  const material = new THREE.MeshLambertMaterial({
	color: 0x00ffff,
	side: THREE.DoubleSide, // 决定你的材质是单面还是双面
  })

  const axios = new THREE.AxesHelper(300)
  scene.add(axios)

  // 创建一个网格模型对象
  const mesh = new THREE.Mesh(geometry, material)
  // 将网格模型对象添加到三维场景中
  scene.add(mesh)

  // 创建光源
  const abbientLight = new THREE.AmbientLight(0xffffff, 0.5)
  scene.add(abbientLight)

  // 创建点光源
  const light = new THREE.PointLight(0xffffff, 0.4)
  light.position.set(500, 300, 200)
  scene.add(light)

  // 创建透视相机
  const width = 1500
  const height = 700
  const camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000)

  // 摄像机的起始位置
  camera.position.set(200, 200, 200)
  // 摄像机对准的位置
  camera.lookAt(0, 0, 0)

  // 创建渲染器
  const render = new THREE.WebGLRenderer()
  render.setSize(width, height)
  // 渲染出内容
  render.render(scene, camera)
  // 输出内容
  document.body.appendChild(render.domElement)

  const controls = new THREE.OrbitControls(camera, render.domElement)
  controls.addEventListener('change', () => {
	// 监听然后重新渲染
	render.render(scene, camera)
  })
下章预告

---《Three.js 入门指南:让 3D 场景“可交互”的魔法》