Three.js相机Camera控件知识梳理

原文:https://juejin.cn/post/7231089453695238204?searchId=20241217193043D32C9115C2057FE3AD64

1. 相机类型

Three.js 主要提供了两种类型的相机:正交相机(OrthographicCamera)和透视相机(PerspectiveCamera)。

1.1 正交相机

正交相机(OrthographicCamera)使用正交投影进行渲染。在正交投影中,物体的大小不会随着距离的增加而减小,这意味着所有物体在渲染时保持相同的尺寸,不受距离的影响。这种相机在制作 2D 游戏和 CAD 工具等应用中非常有用。

创建正交相机的代码如下:

|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 | const camera = ``new THREE.OrthographicCamera(left, right, top, bottom, near, far); // 正投影相机案例 const width = window.innerWidth; ``//canvas画布宽度 const height = window.innerHeight; ``//canvas画布高度 const k = width / height; ``//canvas画布宽高比 const s = 600;``//控制left, right, top, bottom范围大小 const camera = ``new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 8000); |

参数(属性) 含义
left 渲染空间的左边界
right 渲染空间的右边界
top 渲染空间的上边界
bottom 渲染空间的下边界
near near属性表示的是从距离相机多远的位置开始渲染,一般情况会设置一个很小的值。 默认值0.1
far far属性表示的是距离相机多远的位置截止渲染,如果设置的值偏小小,会有部分场景看不到。 默认值2000

1.2 透视相机

透视相机(PerspectiveCamera)使用透视投影进行渲染。在透视投影中,物体的大小会随着距离的增加而减小,这使得远离相机的物体看起来更小,符合现实世界中的透视效果。这种相机在制作 3D 游戏和仿真应用中非常常见。

创建透视相机的代码如下:

|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 | const camera = ``new THREE.PerspectiveCamera(fov, aspect, near, far); //透视相机案例 // width和height用来设置Three.js输出的Canvas画布尺寸(像素px) const width = 800; ``//宽度 const height = 500; ``//高度 // 30:视场角度, width / height:Canvas画布宽高比, 1:近裁截面, 3000:远裁截面 const camera = ``new THREE.PerspectiveCamera(30, width / height, 1, 3000); |

参数 含义
fov 相机视锥体竖直方向视野角度
aspect 相机视锥体水平方向和竖直方向长度比,一般设置为Canvas画布宽高比width / height
near 相机视锥体近裁截面相对相机距离
far 相机视锥体远裁截面相对相机距离,far-near构成了视锥体高度方向

2. 相机属性

Three.js 中的相机具有一些基本属性,这些属性决定了相机的视角和视野。

2.1 视角(FOV)

仅透视相机具有视角属性(FOV)。视角表示相机的垂直视野范围,单位为度。较大的视角值会导致更大的视野,但可能会产生畸变。较小的视角值则会产生更窄的视野和更低的畸变。

2.2 宽高比(Aspect)

仅透视相机具有宽高比属性。宽高比表示相机水平视野范围与垂直视野范围的比值。通常,宽高比应该与渲染目标(如 Canvas 或 WebGLRenderTarget)的宽高比相同,以避免图像被拉伸或压缩。

2.3 近裁剪面(Near)和远裁剪面(Far)

近裁剪面和远裁剪面定义了相机的渲染范围。位于近裁剪面之前的物体和位于远裁剪面之后的物体都不会被渲染。为了提高渲染性能,通常应该尽量将近裁剪面和远裁剪面之间的距离设置得较小。

3. 不同方向的投影视图

3.1 x轴方向观察

|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 | // 通过UI按钮改变相机观察角度 document.getElementById(``'x'``).addEventListener(``'click'``, ``function () { ``camera.position.set(500, 0, 0); ``//x轴方向观察 ``camera.lookAt(0, 0, 0); ``//重新计算相机视线方向 }) |

3.2 y轴方向观察

|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 | // 通过UI按钮改变相机观察角度 document.getElementById(``'y'``).addEventListener(``'click'``, ``function () { ``camera.position.set(0, 500, 0); ``//y轴方向观察 ``camera.lookAt(0, 0, 0); ``//重新计算相机视线方向 }) |

3.3 z轴方向观察z轴方向观察

|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 | // 通过UI按钮改变相机观察角度 document.getElementById(``'z'``).addEventListener(``'click'``, ``function () { ``camera.position.set(0, 0, 500); ``//z轴方向观察 ``camera.lookAt(0, 0, 0); ``//重新计算相机视线方向 }) |

4. 相机动画(.position和.lookAt())

通过相机对象Camera.position属性和.lookAt()方法,可实现一段相机动画。

4.1 相机运动动画

改变相机的位置.position,三维场景在canvas画布上呈现不同的效果,如果连续改变相机的位置.position,就可以获得一个动画效果。

课件案例源码是一个工厂模型,相机在空中俯视工厂,如果在渲染循环中不停地改变相机位置,这时候产生的视觉效果,就好比你在天上运动,看地面的效果。

|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 | // 渲染循环 function render() { ``camera.position.z -= 0.3;``//相机直线运动动画 ``renderer.render(scene, camera); ``requestAnimationFrame(render); } render(); |

4.2 相机圆周运动相机圆周运动

在渲染循环中,改变相机位置,在XOZ平面上绕着y轴圆周运动。

|----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 | // 渲染循环 let angle = 0; ``//用于圆周运动计算的角度值 const R = 100; ``//相机圆周运动的半径 function render() { ``angle += 0.01; ``// 相机y坐标不变,在XOZ平面上做圆周运动 ``camera.position.x = R * Math.cos(angle); ``camera.position.z = R * Math.sin(angle); ``renderer.render(scene, camera); ``requestAnimationFrame(render); } render(); |

4.3 执行lookAt()计算相机视线方向

改变.position属性后,如果不执行.lookAt()方法,相机的观察方向默认不变。

如果你希望相机圆周运动的同时,改变相机视线方向,保持相机镜头始终指向坐标原点或其它位置,需要每次改变.position属性后,重新执行一遍.lookAt()方法

|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 | function render() { ``angle += 0.01; ``camera.position.x = R * Math.cos(angle); ``camera.position.z = R * Math.sin(angle); ``// .position改变,重新执行lookAt(0,0,0)计算相机视线方向 ``camera.lookAt(0,0,0); ``requestAnimationFrame(render); } render(); |

5. 相机控件OrbitControls

通常需要为用户提供一种直观的方式来浏览和操作场景。OrbitControls 是 Three.js 提供的一种常用的相机控制器,允许用户通过鼠标或触摸屏操作来旋转、平移和缩放场景。

5.1 OrbitControls使用

  • 旋转:拖动鼠标左键
  • 缩放:滚动鼠标中键
  • 平移:拖动鼠标右键

OrbitControls本质上就是改变相机的参数,比如相机的位置属性,改变相机位置也可以改变相机拍照场景中模型的角度,实现模型的360度旋转预览效果,改变透视投影相机距离模型的距离,就可以改变相机能看到的视野范围。

|----------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | // 引入轨道控制器扩展库OrbitControls.js import { OrbitControls } from ``'three/addons/controls/OrbitControls.js'``; // 设置相机控件轨道控制器OrbitControls const controls = ``new OrbitControls(camera, renderer.domElement); // 如果OrbitControls改变了相机参数,重新调用渲染器渲染三维场景 controls.addEventListener(``'change'``, ``function () { ``renderer.render(scene, camera); ``//执行渲染操作 ``console.log(``'camera.position'``,camera.position); });``//监听鼠标、键盘事件 //相关限制方法: controls.enablePan = ``false``; ``//禁止平移 controls.enableZoom = ``false``;``//禁止缩放 controls.enableRotate = ``false``; ``//禁止旋转 // 缩放范围 controls.minZoom = 0.5; controls.maxZoom = 2; // 上下旋转范围 controls.minPolarAngle = 0; controls.maxPolarAngle = Math.PI/2; // 左右旋转范围 controls.minAzimuthAngle = -Math.PI/2; controls.maxAzimuthAngle = Math.PI/2; //更新方法 function animate() { ``requestAnimationFrame(animate); ``// 更新控制器 ``controls.update(); ``// 渲染场景 ``renderer.render(scene, camera); } |

6. 相机控件MapControls

在某些 Three.js 应用中,例如地图、地形或者 GIS 类型的项目,需要为用户提供一种直观且符合习惯的方式来浏览和操作场景。MapControls 是一个类似于 Google Maps 风格的相机控制器,允许用户通过鼠标和触摸屏操作来平移、缩放和旋转场景。

6.1 MapControls使用

  • 平移:鼠标左键拖动
  • 旋转:鼠标右键拖动
  • 缩放:鼠标中键滚动

MapControls本质上就是改变相机的参数,比如相机的位置属性、相机目标观察点。

|-------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | // 引入相机控件`MapControls``` `import { MapControls } from 'three/addons/controls/OrbitControls.js';` `const controls = new MapControls(camera, renderer.domElement); controls.addEventListener('change', function` `() {` ` // 鼠标右键旋转时候,查看.position变化 // 鼠标左键拖动的时候,查看.position、.target的位置会变化` ` console.log('camera.position',camera.position); console.log('controls.target',controls.target);` `});` `//相关限制方法:` `controls.enablePan = false; //禁止平移 controls.enableZoom = false;//禁止缩放` `controls.enableRotate = false; //禁止旋转 //相机位置与观察目标点最小值 controls.minDistance = 200; //相机位置与观察目标点最大值 controls.maxDistance = 500; // 上下旋转范围 controls.minPolarAngle = 0; controls.maxPolarAngle = Math.PI/2; // 左右旋转范围 controls.minAzimuthAngle = -Math.PI/2; controls.maxAzimuthAngle = Math.PI/2; //更新方法 function animate() { requestAnimationFrame(animate);` ` // 更新控制器 controls.update();` ` // 渲染场景 ``renderer.render(scene, camera); }` |

7. 窗口变化的自适应渲染

在开发 Three.js 项目时,我们需要考虑到不同的设备和屏幕尺寸。当用户调整浏览器窗口大小时,我们希望场景能够自适应地进行调整,以保持正确的比例和尺寸。

要实现自适应渲染,我们需要在浏览器窗口大小发生变化时更新相机和渲染器的设置。首先,我们需要为 window 对象添加一个 resize 事件监听器:

|---|----------------------------------------------------------|
| 1 | window.addEventListener(``'resize'``, onWindowResize); |

接下来,我们定义 onWindowResize 函数。在这个函数中,我们需要完成以下任务:

  • 更新相机的宽高比(aspect)。
  • 更新相机的投影矩阵。
  • 更新渲染器的大小。

7.1 正投影相机OrthographicCamera自适应渲染

|-------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // onresize 事件会在窗口被调整大小时发生 function onWindowResize(){ ``// 重置渲染器输出画布canvas尺寸 ``renderer.setSize(window.innerWidth,window.innerHeight); ``// 重置相机投影的相关参数 ``k = window.innerWidth/window.innerHeight;``//窗口宽高比 ``camera.left = -s*k; ``camera.right = s*k; ``camera.top = s; ``camera.bottom = -s; ``// 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix ``// 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源) ``// 如果相机的一些属性发生了变化,需要执行updateProjectionMatrix ()方法更新相机的投影矩阵 ``camera.updateProjectionMatrix (); }; |

7.2 透视投影相机PerspectiveCamera自适应渲染

|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 | // onresize 事件会在窗口被调整大小时发生 function onWindowResize(){ ``// 重置渲染器输出画布canvas尺寸 ``renderer.setSize(window.innerWidth,window.innerHeight); ``// 全屏情况下:设置观察范围长宽比aspect为窗口宽高比 ``camera.aspect = window.innerWidth/window.innerHeight; ``// 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix ``// 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源) ``// 如果相机的一些属性发生了变化,需要执行updateProjectionMatrix ()方法更新相机的投影矩阵 ``camera.updateProjectionMatrix (); }; |

以上就是Three.js相机Camera的详细内容,更多关于Three.js相机Camera的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:

相关推荐
Debroon1 小时前
M3D: 基于多模态大模型的新型3D医学影像分析框架,将3D医学图像分析从“看图片“提升到“理解空间“的层次,支持检索、报告生成、问答、定位和分割等8类任务
3d
CASAIM7 小时前
模具制造之三维扫描和逆向建模
目标检测·3d·汽车·制造
工业3D_大熊18 小时前
HOOPS Communicator功能剖析:3D Web模型树交互的实用指南!
linux·windows·macos·3d·docker·c#·.net
番茄电脑全能王1 天前
电脑玩《刺客信条》时中,遇到找不到d3dx9_42.dll的问题是什么原因?缺失d3dx9_42.dll应该怎么解决呢?下面一起来看看吧!
3d
关山月1 天前
9个学习着色器的GLSL示例
前端·three.js
程序员_三木1 天前
Three.js资源-贴图材质网站推荐
javascript·webgl·three.js·材质·贴图
战场小包1 天前
小米su7 or 保时捷怎么选?使用 Three 实现 3D 汽车展示平台比比看
前端·vue.js·3d·aigc
www_3dyz_com1 天前
VR展厅模板在各种平台上运行效果如何?
3d·vr·虚拟现实
MossGrower2 天前
37. Three.js案例-绘制部分球体
3d图形·webgl·three.js·球体几何体