原文: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的资料请关注脚本之家其它相关文章!
您可能感兴趣的文章: