【threejs教程】终于搞明白了!原来threejs中的透视相机这么简单!

简介: 【8月更文挑战第5天】深入学习threejs中的透视相机!

简介

本系列教程需要具备threejs的基础入门知识,了场景、几何体、相机等基础概念。
学习本教程之前,建议学习【场景及坐标轴】的基础知识。

使用前置知识,可以很快的开发一个3D页面。
GIF 2023-11-17 14-48-50.gif
其核心代码如下:

<template>
  <div class="wrap" ref="threeContainer"></div>
</template>

<script setup>
import * as THREE from "three";
import {
   
    onMounted, ref } from "vue";
import {
   
    OrbitControls } from "three/addons/controls/OrbitControls.js";
// import { CubeTextureLoader } from "three/examples/jsm/loaders/CubeTextureLoader.js";

const threeContainer = ref(null);

// 1、创建3D场景对象Scene
const scene = new THREE.Scene();
// 添加背景颜色
scene.background = new THREE.CubeTextureLoader().setPath("/sky/").load(["posx.jpg", "negx.jpg", "posy.jpg", "negy.jpg", "posz.jpg", "negz.jpg"]);

// 添加网格地面
const gridHelper = new THREE.GridHelper(200, 10);
scene.add(gridHelper);

// 添加三维坐标轴
const axesHelper = new THREE.AxesHelper(80);
axesHelper.position.y = 20;
scene.add(axesHelper);

// 2、创建几何体Geometry模型
const geometry = new THREE.BoxGeometry(20, 20, 20);

const material = new THREE.MeshBasicMaterial({
   
   
  color: "blue",
});
const mesh = new THREE.Mesh(geometry, material);
// 设置模型mesh的xyz坐标
mesh.position.set(0, 40, 0);
scene.add(mesh);

// 3、使用虚拟相机观察模型
const camera = new THREE.PerspectiveCamera();
camera.position.set(0, 50, 200);
camera.lookAt(0, 0, 20); //坐标原点

// 4、渲染3D场景到DOM上
const width = 800; //宽度
const height = 500; //高度
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
renderer.setAnimationLoop(animation);
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 添加阻尼
controls.enableDamping = true;
controls.dampingFactor = 0.01;
// 开启自动旋转
controls.autoRotate = true;
// 设置自动旋转速度
controls.autoRotateSpeed = 5;

function animation() {
   
   
  mesh.rotation.x += 0.05;
  mesh.rotation.y += 0.05;
  controls.update();
  renderer.render(scene, camera);
}

onMounted(() => {
   
   
  threeContainer.value.appendChild(renderer.domElement);
});
</script>

<style scoped></style>

透视相机

在Three.js中,透视相机(PerspectiveCamera)是用来模拟人眼所看到的景象,它是3D场景的渲染中使用得最普遍的投影模式。
我们创建项目的时候,采用的就是透视相机

// 3、使用虚拟相机观察模型
const camera = new THREE.PerspectiveCamera();
camera.position.set(0, 50, 200);
camera.lookAt(0, 0, 20); //坐标原点

要想深入了解透视相机的使用方法,我们需要先学习一些基本的3D知识

PerspectiveCamera简介

语法结构:PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )

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

透视投影相机的四个参数fov, aspect, near, far构成一个四棱台3D空间,被称为视锥体,只有视锥体之内的物体,才会渲染出来,视锥体范围之外的物体不会显示在Canvas画布上。

使用官方编辑器学习透视相机

要想深入学习透视相机,我们可以借助官方提供的编辑器。
编辑器在线地址:https://threejs.org/editor/
创建物体和透视相机
GIF 2023-11-17 15-33-30.gif
透视相机的移动与旋转
GIF 2023-11-17 15-36-15.gif
透视相机与普通相机的视角切换
GIF 2023-11-17 15-37-28.gif
透视相机的参数调整
GIF 2023-11-17 15-38-31.gif

不同参数对透视相机位置的影响

GIF 2023-11-17 15-54-13.gif

代码示例

首先,我们关闭场景的自动旋转,方便观察。
GIF 2023-11-17 16-08-58.gif

PerspectiveCamera增加初始参数

// 3、使用虚拟相机观察模型
const camera = new THREE.PerspectiveCamera(
  75, 
  window.innerWidth / window.innerHeight, 
  0.1, 
  1000
);

GIF 2023-11-17 16-12-41.gif

视野角度fov对视角的影响

<template>
  <div class="wrap" ref="threeContainer"></div>
  <button @click="changeCameraAdd">+</button>
  <button>相机fov</button>
  <button @click="changeCameraDe">-</button>
</template>

GIF 2023-11-17 16-19-37.gif

updateProjectionMatrix()方法来更新投影矩阵,以确保场景在新的fov参数下正确渲染

截面near、far对视角的影响

近远截面及fov构成视椎体,当远近界面位置不恰当时,物体可能位于视椎体之外,渲染不出来。

<template>
  <div class="wrap" ref="threeContainer"></div>
  <button @click="changeCameraAdd">+</button>
  <button>相机fov</button>
  <button @click="changeCameraDe">-</button>
  <button @click="nearAdd">+</button>
  <button>近界面near</button>
  <button @click="nearDe">-</button>
</template>
function nearAdd() {
   
   
  camera.near += 10;
  camera.updateProjectionMatrix();
}
function nearDe() {
   
   
  camera.near -= 10;
  camera.updateProjectionMatrix();
}

GIF 2023-11-17 16-33-00.gif

相机位置对视角的影响

<template>
  <div class="wrap" ref="threeContainer"></div>
  <button @click="changeCameraAdd">+</button>
  <button>相机fov</button>
  <button @click="changeCameraDe">-</button>
  <button @click="cameraYAdd">Y轴+</button>
  <button>相机位置</button>
  <button @click="cameraXdd">Z轴+</button>
</template>
function cameraYAdd() {
   
   
  camera.position.x += 10;
  controls.update();
}
function cameraXdd() {
   
   
  camera.position.z += 10;
  controls.update();
}

GIF 2023-11-17 16-40-34.gif

物体位置对视角的影响

<template>
  <div class="wrap" ref="threeContainer"></div>
  <button @click="meshAdd">Y轴+</button>
  <button>物体位置</button>
  <button @click="meshDe">Y轴-</button>
</template>
function meshAdd() {
   
   
  mesh.position.y += 10;
}
function meshDe() {
   
   
  mesh.position.y -= 10;
}

GIF 2023-11-17 16-45-26.gif

相关文章
Threejs入门进阶实战案例(5):坐标系理解时辅助坐标系的使用
Threejs入门进阶实战案例(5):坐标系理解时辅助坐标系的使用
165 0
|
4月前
|
JavaScript API 图形学
ThreeJS入门-创建一个正方体
这篇文章介绍了如何使用Three.js创建一个基本的正方体模型,并提供了实现这一功能的详细步骤和代码示例。
70 0
ThreeJS入门-创建一个正方体
|
6月前
|
图形学
小功能⭐️Unity获取场景中所有物体
小功能⭐️Unity获取场景中所有物体
小功能⭐️Unity获取场景中所有物体
|
6月前
|
编解码 JavaScript 前端开发
ThreeJs 基础学习
ThreeJs 基础学习
76 0
|
8月前
|
Web App开发 JavaScript 前端开发
程序员必知:【three.js练习程序】创建地球贴图
程序员必知:【three.js练习程序】创建地球贴图
67 0
|
JavaScript 前端开发
threejs实战_理解光源
threejs实战_理解光源
166 0
threejs实战_理解光源
|
存储 异构计算
threejs实战_3d纹理
threejs加载3d纹理
219 0
threejs实战_3d纹理
|
前端开发 JavaScript
threejs实战_canvans纹理
threejs加载canvas纹理
169 0
|
存储 缓存 JavaScript
用three.js搞3个炫酷粒子出场
出场就要帅气!动画要酷!点进来就看粒子玩出新花样!让你拥有炫酷的粒子出场方式,一闪一闪亮晶晶好像许多的星星!!!
|
前端开发
前端知识案例学习15-实现3d得旋转
前端知识案例学习15-实现3d得旋转
100 0
前端知识案例学习15-实现3d得旋转