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)
相关推荐
枷锁—sha1 分钟前
【DVWA系列】——CSRF——Medium详细教程
android·服务器·前端·web安全·网络安全·csrf
枷锁—sha2 分钟前
跨站请求伪造漏洞(CSRF)详解
运维·服务器·前端·web安全·网络安全·csrf
群联云防护小杜18 分钟前
深度隐匿源IP:高防+群联AI云防护防绕过实战
运维·服务器·前端·网络·人工智能·网络协议·tcp/ip
汉得数字平台36 分钟前
【鲲苍提效】全面洞察用户体验,助力打造高性能前端应用
前端·前端监控
花海如潮淹43 分钟前
前端性能追踪工具:用户体验的毫秒战争
前端·笔记·ux
_丿丨丨_6 小时前
XSS(跨站脚本攻击)
前端·网络·xss
天天进步20156 小时前
前端安全指南:防御XSS与CSRF攻击
前端·安全·xss
拾光拾趣录8 小时前
括号生成算法
前端·算法
拾光拾趣录9 小时前
requestIdleCallback:让你的网页如丝般顺滑
前端·性能优化
前端 贾公子9 小时前
vue-cli 模式下安装 uni-ui
前端·javascript·windows