Three.js 中 PerspectiveCamera 的使用详解

person 少陵野老    watch_later 2024-10-17 21:08:45
visibility 64    class PerspectiveCamera     bookmark 专栏

PerspectiveCamera 是 Three.js 中最常用的摄像机之一,它使用透视投影来模拟人眼的视觉效果。透视摄像机通过设置视场角(FOV)、长宽比、近裁剪面、远裁剪面来决定场景中的物体如何被渲染。本文将详细介绍 PerspectiveCamera 的使用,涵盖其所有属性和方法,并结合实际示例代码帮助你掌握如何在项目中使用它。

1. 什么是 PerspectiveCamera

PerspectiveCamera 模拟人眼的透视效果,也就是离视点越远的物体看起来越小,近的物体看起来越大。这种摄像机广泛用于 3D 场景渲染和游戏中,能够让用户获得更真实的视觉体验。

1.1 PerspectiveCamera 的构造函数

const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  • fov:视场角(Field of View),即摄像机的可视角度,单位为度数,决定了可见区域的宽广度。
  • aspect:摄像机的长宽比,通常设置为 window.innerWidth / window.innerHeight,以匹配浏览器窗口的宽高比。
  • near:近裁剪面,任何距离小于此值的物体都不会被渲染。
  • far:远裁剪面,任何距离大于此值的物体都不会被渲染。

2. 基本使用

2.1 创建透视摄像机

要创建一个 PerspectiveCamera,我们需要指定视场角、长宽比、近裁剪面和远裁剪面。

const fov = 75; // 视场角
const aspect = window.innerWidth / window.innerHeight; // 长宽比
const near = 0.1; // 近裁剪面
const far = 1000; // 远裁剪面
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);

在上面的代码中,我们创建了一个视场角为 75 度,长宽比为窗口宽高比,近裁剪面为 0.1,远裁剪面为 1000 的透视摄像机。

2.2 设置摄像机位置

默认情况下,摄像机会位于原点 (0, 0, 0),我们通常需要将它移出原点以便能够看到场景中的物体。可以使用 camera.position.set(x, y, z) 来设置摄像机的位置。

camera.position.set(0, 0, 5); // 设置摄像机在 z 轴上距离场景 5 个单位的位置

2.3 将摄像机添加到场景中

PerspectiveCamera 本质上是 Three.js 的 Object3D,它可以像任何其他 3D 对象一样被添加到场景中。但是,通常不需要手动将摄像机添加到场景中,因为摄像机会自动应用于渲染器。

scene.add(camera); // 可选

2.4 渲染场景

通过 renderer.render(scene, camera) 方法,可以使用 PerspectiveCamera 渲染场景。

renderer.render(scene, camera);

3. 使用 PerspectiveCamera 创建完整示例

让我们通过一个完整的示例来了解如何使用 PerspectiveCamera。我们将在一个简单的 3D 场景中创建一个旋转的立方体,并使用透视摄像机来渲染场景。

// 初始化场景
const scene = new THREE.Scene();

// 创建透视摄像机
const fov = 75;
const aspect = window.innerWidth / window.innerHeight;
const near = 0.1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 5);

// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 创建一个立方体
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// 动画循环
function animate() {
  requestAnimationFrame(animate);

  // 旋转立方体
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;

  // 渲染场景
  renderer.render(scene, camera);
}

animate();

在这个示例中,我们创建了一个透视摄像机,设置其位置,并创建了一个简单的立方体。通过动画循环,立方体不断旋转,并使用透视摄像机渲染场景。

4. 动态调整 PerspectiveCamera 的参数

你可以在运行时动态调整 PerspectiveCamera 的参数,以实现一些特殊的视觉效果。

4.1 动态调整视场角

你可以通过修改摄像机的 fov 属性来动态调整视场角。例如,通过响应用户的滚轮事件来缩放场景:

window.addEventListener('wheel', (event) => {
  camera.fov += event.deltaY * 0.05; // 滚轮控制视场角
  camera.updateProjectionMatrix(); // 更新投影矩阵
});

4.2 调整长宽比

当窗口大小发生变化时,摄像机的长宽比也需要更新以匹配新的窗口尺寸。可以通过以下代码来监听窗口大小的变化,并动态调整摄像机的长宽比:

window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

5. 结合其他组件的使用

5.1 与轨道控制器结合

Three.js 提供了 OrbitControls,它允许用户通过鼠标拖拽、缩放来控制摄像机的视角。你可以将 OrbitControlsPerspectiveCamera 结合起来,创建更具交互性的 3D 场景。

首先,导入 OrbitControls

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

然后,在初始化摄像机之后,创建 OrbitControls 实例:

const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // 启用阻尼效果
controls.dampingFactor = 0.25; // 阻尼系数
controls.enableZoom = true; // 启用缩放

在动画循环中调用 controls.update(),以确保控制器的平滑操作:

function animate() {
  requestAnimationFrame(animate);
  controls.update(); // 更新控制器
  renderer.render(scene, camera);
}

通过 OrbitControls,用户可以交互式地缩放、旋转和拖拽摄像机视角。

5.2 与光源结合

你可以结合透视摄像机与光源,创建更为复杂的场景。以下是一个使用 DirectionalLight 的示例:

const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5, 5, 5);
scene.add(light);

// 创建带有材质和光照效果的立方体
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

在这个示例中,DirectionalLight 用于为场景提供照明,并且通过 MeshStandardMaterial 创建的立方体会受光源的影响。

6. PerspectiveCamera 的高级用法

6.1 使用 lookAt 方法

PerspectiveCamera 可以通过 lookAt 方法将视角锁定到场景中的某个点。这对于需要固定观察某一目标的场景非常有用。

camera.lookAt(new THREE.Vector3(0, 0, 0)); // 使摄像机始终注视场景中心

6.2 动态切换摄像机

在某些场景中,你可能需要在多个摄像机之间进行切换。你可以在渲染循环中动态切换不同的摄像机。

let usePerspective = true;
document.addEventListener('keydown', (event) => {
  if (event.code === 'KeyC') {
    usePerspective = !usePerspective;
  }
});

function animate() {
  requestAnimationFrame(animate);
  
  if (usePerspective) {
    renderer.render(scene, perspectiveCamera);
  } else {
    renderer.render(scene, orthographicCamera);
  }
}

在这个示例中,我们通过按

C 键动态切换不同的摄像机视角。

7. 总结

PerspectiveCamera 是 Three.js 中使用最广泛的摄像机类型之一。它通过模拟人眼的透视效果,为我们提供了逼真的 3D 场景渲染体验。在实际应用中,我们可以结合轨道控制器、光照等其他组件,实现更丰富的交互效果。

评论区
评论列表
menu