threejs系列:相机与投影 📷

写在最前

three.js 摄像机是用于控制三维场景视角的对象,用于控制相机的位置、方向、视野和其他属性。

PerspectiveCamera 透视投影相机

视锥体

fov:垂直视野角度,fov越小,物体越大,反之亦然。

很好理解,眯起眼睛看物体,物体会整个呈现在视野中,所以就会显得很大。

aspect: 视锥体长宽比,呈现在屏幕的宽高比。

如全屏则使用window的宽高比,如不全屏则使用Canvas(renderer.domElement)的宽高比。

far、near:可观测的最远与最近的距离。

相关

投影

投影是什么?投影是3维物体投射到2D平面的过程。生活中的物体都是3维的,而相机拍出的照片是二维的,这中间必然是受到某种"介质"的影响,而这个"介质"就是算法。

不同算法可以有不同的叫法。

透视投影

近大远小,物体的位置需受与照相机的距离影响。

正交投影

物体位置不受与照相机距离影响。

原理

在WebGL中并没有摄像机的概念,只是通过把场景中的所有物体往相反方向移动的方式来模拟出摄像机。

怎么理解呢,就像是当你坐火车看向窗外时,你会感觉树在往后移动。

相关常用 API

lookAt

Object3D<Event>.lookAt(vector: THREE.Vector3): void

参数为一个3维向量,向量可以代表物体位置,调用方法设置相机朝向。

不要好奇为什么相机可以调用Object3D的方法,因为万物皆是Object3D,后面会将这个基类

getWorldDirection

Camera.getWorldDirection(target: THREE.Vector3): THREE.Vector3

返回当前摄像机所正视的世界空间方向的Vector3对象,俯视时z为负数

updateProjectionMatrix

更新摄像机投影矩阵,当far、near、aspect、fov等修改时需执行,常用于自适应屏幕

setViewOffset

设置相机偏移,用途常用于:多显示器拼接画面

动手实践

  1. 跟随运动

假如我们拥有一个物体随机移动,我们需要镜头始终瞄准物体。

js 复制代码
<template>
    <div ref="dom"></div>
</template>
<script lang="ts" setup>
import * as THREE from "three";
import { Ref, onMounted, ref } from "vue"

let { PerspectiveCamera, WebGLRenderer, Scene } = THREE;
let camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
let renderer = new WebGLRenderer();
let scene = new Scene();
let dom = ref(null);
let angle = 0;

let cube = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({ color: 0x000000 }))
scene.add(cube);
cube.position.y = 1;


let plane = new THREE.Mesh(new THREE.BoxGeometry(70, 70, 0.5), new THREE.MeshBasicMaterial({ color: 0x9D9D9D }))
plane.position.z = 0;
plane.rotation.x = -Math.PI / 2;
scene.add(plane)

camera.position.set(20, 20, -20);
camera.lookAt(cube.position);
renderer.setSize(window.innerWidth, window.innerHeight);

let animate = () => {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
    angle += 3
    cubeAnimate();

    camera.lookAt(cube.position);
}

let cubeAnimate = () => {
    cube.position.z = Math.sin(Math.PI / 180 * angle) * 3;
    cube.position.x = Math.cos(Math.PI / 180 * angle) * 3;
}

onMounted(() => {
    if (dom.value) {
        dom.value.appendChild(renderer.domElement);
        animate();
    }
})

</script>
  1. 屏幕自适应
js 复制代码
let setSceneAdapt = () => {
    let width = window.innerWidth, height = window.innerHeight;
    camera.aspect = width / height;
    camera.updateProjectionMatrix()
    renderer.setSize(width, height);

    renderer.setPixelRatio(window.devicePixelRatio)
}

window.addEventListener("resize", setSceneAdapt)
相关推荐
崔庆才丨静觅6 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅7 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅7 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅8 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊8 小时前
jwt介绍
前端
爱敲代码的小鱼8 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax