4.2透视相机参数 4.2 Three.js 透视相机参数详解与实践 透视相机(PerspectiveCamera)是 Three.js 中最常用的相机类型,它模拟人眼观察世界的方式,产生近大远小的透视效果。理解透视相机的参数对于创建逼真的 3D 场景至关重要。 4.2.1 透视相机的构造函数 fov (number): 视角(Field of View)。相机视锥体垂直方向上的张角,用角度表示(单位为度)。常用的值是 45-75 度。 aspect (number): 长宽比(Aspect Ratio)。相机视锥体的宽度和高度的比率。通常设置为 canvas 的宽度除以高度。 near (number): 近裁剪面(Near Clipping Plane)。相机到近裁剪面的距离。
透视相机(PerspectiveCamera)是 Three.js 中最常用的相机类型,它模拟人眼观察世界的方式,产生近大远小的透视效果。理解透视相机的参数对于创建逼真的 3D 场景至关重要。
THREE.PerspectiveCamera(fov, aspect, near, far)
fov (number): 视角(Field of View)。相机视锥体垂直方向上的张角,用角度表示(单位为度)。常用的值是 45-75 度。
aspect (number): 长宽比(Aspect Ratio)。相机视锥体的宽度和高度的比率。通常设置为 canvas 的宽度除以高度。
near (number): 近裁剪面(Near Clipping Plane)。相机到近裁剪面的距离。在此平面之前的物体将不会被渲染。
far (number): 远裁剪面(Far Clipping Plane)。相机到远裁剪面的距离。在此平面之后的物体将不会被渲染。
让我们逐一深入了解这些参数:
fov 决定了你看到的场景的“广度”。
更大的 fov: 产生更广阔的视野,场景中的物体会显得更小,透视变形更明显,类似于广角镜头。
更小的 fov: 产生更窄的视野,场景中的物体会显得更大,透视变形更小,类似于长焦镜头。
代码示例:调整 fov
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); // 初始 fov 为 75 // 调整 fov 的函数 function updateCameraFOV(newFOV) { camera.fov = newFOV; camera.updateProjectionMatrix(); // 更新投影矩阵 } // 示例:将 fov 设置为 45 度 updateCameraFOV(45);
aspect 必须与你的渲染 canvas 的长宽比匹配。如果 canvas 的尺寸改变,你必须更新相机的 aspect 属性,并调用 updateProjectionMatrix() 方法。
代码示例:更新 aspect
function onWindowResize() { const newWidth = window.innerWidth; const newHeight = window.innerHeight; camera.aspect = newWidth / newHeight; camera.updateProjectionMatrix(); // 更新投影矩阵 renderer.setSize(newWidth, newHeight); // 更新渲染器尺寸 } window.addEventListener('resize', onWindowResize, false); // 监听窗口 resize 事件
near 和 far 定义了相机可以看到的深度范围。
near: 越小,越靠近相机,但如果太小,可能会导致物体被裁剪掉。
far: 越大,能看到的场景越远,但过大的 far 值会降低深度缓冲区的精度,导致 z-fighting (深度冲突)。
Z-fighting:当两个或多个面非常接近时,深度缓冲区可能无法正确区分哪个面在前,导致渲染结果出现闪烁或图案。
代码示例:调整 near 和 far
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); // 初始 near 为 0.1, far 为 1000 // 调整 near 和 far 的函数 function updateCameraClippingPlanes(newNear, newFar) { camera.near = newNear; camera.far = newFar; camera.updateProjectionMatrix(); // 更新投影矩阵 } // 示例:将 near 设置为 0.5, far 设置为 500 updateCameraClippingPlanes(0.5, 500);
最佳实践:
尽量保持 near 值接近于 0,但不要设置为 0,因为这会导致除零错误。
根据场景的大小调整 far 值,不要设置得过大。
如果出现 z-fighting,尝试减小 far 值或增加深度缓冲区的精度(在渲染器中设置)。
updateProjectionMatrix() 方法每次更改 fov、aspect、near 或 far 属性后,都需要调用 updateProjectionMatrix() 方法来更新相机的投影矩阵。投影矩阵负责将 3D 场景中的坐标转换为 2D 屏幕坐标。
<!DOCTYPE html> <html> <head> <title>Three.js 透视相机</title> <style> body { margin: 0; } canvas { display: block; } </style> </head> <body> <script src="https://cdn.jsdelivr.net/npm/three@0.155.0/build/three.min.js"></script> <script> // 初始化场景,相机和渲染器 const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); 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); camera.position.z = 5; // 动画循环 function animate() { requestAnimationFrame(animate); cube.rotation.x += 0.01; cube.rotation.y += 0.01; renderer.render(scene, camera); } // 窗口resize事件处理 function onWindowResize() { const newWidth = window.innerWidth; const newHeight = window.innerHeight; camera.aspect = newWidth / newHeight; camera.updateProjectionMatrix(); renderer.setSize(newWidth, newHeight); } window.addEventListener('resize', onWindowResize, false); animate(); </script> </body> </html>
这个例子创建了一个简单的场景,包含一个旋转的绿色立方体。 它还包括窗口大小调整的处理程序,以确保长宽比始终正确。
为了更方便地调整相机参数,可以使用 GUI 库,例如 dat.GUI。
import * as dat from 'dat.gui'; const gui = new dat.GUI(); const cameraParams = { fov: 75, near: 0.1, far: 1000 }; gui.add(cameraParams, 'fov', 1, 179).onChange(function(value) { camera.fov = value; camera.updateProjectionMatrix(); }); gui.add(cameraParams, 'near', 0.01, 1).onChange(function(value) { camera.near = value; camera.updateProjectionMatrix(); }); gui.add(cameraParams, 'far', 100, 2000).onChange(function(value) { camera.far = value; camera.updateProjectionMatrix(); });
这段代码使用 dat.GUI 创建了一个界面,可以实时调整相机的 fov、near 和 far 参数。
透视相机是 Three.js 中构建 3D 场景的基础。 理解 fov、aspect、near 和 far 参数对于创建逼真的、视觉上令人愉悦的体验至关重要。 通过调整这些参数,可以控制场景的视角、深度范围和透视效果。记住,canvas 尺寸改变时更新 aspect,并且在参数改变后调用 updateProjectionMatrix()。 通过不断实践和实验,你将能够充分利用透视相机的功能,创造出令人惊叹的 3D 世界。