【ThreeJS Basics 1-6】Camera
文章目录
- Camera 相机
- PerspectiveCamera 透视相机
- 正交相机
- 用鼠标控制相机
- 大幅度转动(可以看到后面)
- 控制组件
- FlyControls 飞行组件控制
- FirstPersonControls 第一人称控制
- PointerLockControls 指针锁定控制
- OrbitControls 轨道控制
- TrackballControls 轨迹球控制
- TransformControls 变换控制组件
- 拖拽组件
- 尝试引入并使用控件:OrbitControls 轨道
- 导入
- DAMPING 阻尼
Camera 相机
以下是几种常见的相机简介
ArrayCamera
: 数组相机StereoCamera
:双眼相机,可以使用两个相机来渲染场景,类似 VR,以及双人成行的屏幕分开的双人游戏CubeCamera
:立方体相机,有 6 个相机,分别渲染 6 个面,ThreeJS 可以用它来渲染环境,贴图,反射,折射阴影OrthographicCamera
:正交相机,RTS 游戏,相对于透视相机(透视相机更接近人眼的观察效果)PerspectiveCamera
:透视相机
PerspectiveCamera 透视相机
参数如下图所示
第一个参数是视野:建议的值在 45~75
如果视野足够大的话,那么规则的立方体可能被挤压变形,类似这样的效果
第二个参数是:横纵比,一般是画布的长/宽
const sizes = {
width: 800,
height: 600
}
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100)
第三个和第四个参数 near
和 far
默认值是
1, 1000
,意味着:
任何比近处更近,或者比远处更远的物体,都不会显示出来
选择合适的取值范围,如果远端有山庄,山脉,云朵之类的,可以取合适的值来判断是否渲染它们。
正交相机
正交相机有六个参数,前四个是位置,左右上下,第五个和第六个跟透视相机的参数类似,远近的渲染
const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.1, 100)
上面的形状并不规则,因为渲染的比例不对,我们获取
const aspectRatio = sizes.width / sizes.height
// Camera
// const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
const camera = new THREE.OrthographicCamera(-1 * aspectRatio, 1 * aspectRatio, 1, -1, 0.1, 100)
- 正交相机不受透视影响,能保证物体形状不因深度而发生变化,适合 2D、UI、地图等场景。
- 乘以 aspectRatio 让视口匹配屏幕比例,确保物体不会在不同设备下发生拉伸变形。
- 如果你需要准确控制几何形状或在屏幕上保持形状固定,正交相机是更好的选择。
用鼠标控制相机
获取坐标位置,并处理坐标值的范围在 [-0.5, 0.5]
/**
* Cursor
*/
const cursor = {
x: 0,
y: 0,
}
window.addEventListener('mousemove', (event) => {
cursor.x = event.clientX / sizes.width - 0.5
cursor.y = event.clientY / sizes.height - 0.5
console.log('cursor:>>', cursor)
})
之后再 tick 函数里更改相机的位置
const tick = () => {
const elapsedTime = clock.getElapsedTime()
// Update objects
// mesh.rotation.y = elapsedTime
camera.position.x = cursor.x * 10
camera.position.y = cursor.y * 10
camera.lookAt(mesh.position )
// Render
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
但是这里会有奇怪的问题, 似乎 x 轴跟 y 轴的逻辑是反着的
所以改变一下 cursor.y 的值,整体取值负数,这样x,y轴都是反方向的了
或者 x 轴取负数,这样就是类似跟随鼠标的效果
但是这样有个问题:我看不到物体的后面,那么,如何才能看到后面呢?或者说让相机旋转起来
大幅度转动(可以看到后面)
const tick = () => {
const elapsedTime = clock.getElapsedTime()
// Update objects
// mesh.rotation.y = elapsedTime
camera.position.x = Math.sin(cursor.x * Math.PI * 2) * 3
camera.position.z = Math.cos(cursor.x * Math.PI * 2) * 3
camera.position.y = cursor.y * 5
camera.lookAt(mesh.position)
// Render
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
控制组件
FlyControls 飞行组件控制
演示地址点我: https://threejs.org/examples/#misc_controls_fly
FirstPersonControls 第一人称控制
https://threejs.org/examples/#webgl_geometry_terrain
PointerLockControls 指针锁定控制
https://threejs.org/examples/#misc_controls_pointerlock
OrbitControls 轨道控制
https://threejs.org/examples/#misc_controls_orbit
TrackballControls 轨迹球控制
https://threejs.org/examples/#misc_controls_trackball
TransformControls 变换控制组件
https://threejs.org/examples/#misc_controls_transform
拖拽组件
https://threejs.org/examples/#misc_controls_drag
尝试引入并使用控件:OrbitControls 轨道
导入
OrbitControls
它不在 THREE
这个变量中,需要手动的导入
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
const controls = new OrbitControls(camera, canvas)
两句话,就可以有下图的使用效果了
DAMPING 阻尼
拖拽的时候有些生涩,加入阻尼之后,会有一定的加速度
但是会有些奇怪,因为需要再每一帧上更新控件才能正常的显现,在 tick 函数中添加更新 controls.update()