【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):坐标系理解时辅助坐标系的使用
134 0
|
25天前
|
JavaScript API 图形学
ThreeJS入门-创建一个正方体
这篇文章介绍了如何使用Three.js创建一个基本的正方体模型,并提供了实现这一功能的详细步骤和代码示例。
27 0
ThreeJS入门-创建一个正方体
|
3月前
|
API
【threejs教程】threejs中的边边角角:几何体详解
【8月更文挑战第6天】threejs中的几何体详解
73 4
【threejs教程】threejs中的边边角角:几何体详解
|
3月前
|
API
|
2月前
|
图形学 开发者
【独家揭秘】Unity游戏开发秘籍:从基础到进阶,掌握材质与纹理的艺术,打造超现实游戏视效的全过程剖析——案例教你如何让每一面墙都会“说话”
【8月更文挑战第31天】Unity 是全球领先的跨平台游戏开发引擎,以其高效性能和丰富的工具集著称,尤其在提升游戏视觉效果方面表现突出。本文通过具体案例分析,介绍如何利用 Unity 中的材质与纹理技术打造逼真且具艺术感的游戏世界。材质定义物体表面属性,如颜色、光滑度等;纹理则用于模拟真实细节。结合使用两者可显著增强场景真实感。以 FPS 游戏为例,通过调整材质参数和编写脚本动态改变属性,可实现自然视觉效果。此外,Unity 还提供了多种高级技术和优化方法供开发者探索。
50 0
|
3月前
|
编解码 JavaScript 前端开发
ThreeJs 基础学习
ThreeJs 基础学习
48 0
|
5月前
鬼刀画风扁平化粒子炫动引导页美化源码
鬼刀画风扁平化粒子炫动引导页美化源码
41 5
鬼刀画风扁平化粒子炫动引导页美化源码
|
5月前
|
Web App开发 JavaScript 前端开发
程序员必知:【three.js练习程序】创建地球贴图
程序员必知:【three.js练习程序】创建地球贴图
42 0
|
5月前
|
前端开发 定位技术 API
怎么用LarkMap完成地图需求
本文属于技术选型的参考性文章,主要以一个一个的案例分析,来带各位快速的了解到LarkMap能帮助我们完成哪些需求。希望阅读完之后您对LarkMap有一个大致的印象,若后续有地图需求的话,可以考虑使用LarkMap。
175 2
|
6月前
|
缓存 数据库 数据安全/隐私保护
我绘制文章插图的三个神级工具
我绘制文章插图的三个神级工具
105 0