简介
本系列教程需要具备threejs的基础入门知识,了场景、几何体、相机等基础概念。
学习本教程之前,建议学习笔者的【场景及坐标轴】的基础知识。
使用前置知识,可以很快的开发一个3D页面。
其核心代码如下:
js
<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场景的渲染中使用得最普遍的投影模式。
我们创建项目的时候,采用的就是透视相机
js
// 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画布上。
使用官方编辑器学习透视相机
要想深入学习透视相机,我们可以借助官方提供的编辑器。
编辑器在线地址:threejs.org/editor/
创建物体和透视相机
透视相机的移动与旋转
透视相机与普通相机的视角切换
透视相机的参数调整
不同参数对透视相机位置的影响
代码示例
首先,我们关闭场景的自动旋转,方便观察。
PerspectiveCamera增加初始参数
js
// 3、使用虚拟相机观察模型
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
视野角度fov对视角的影响
js
<template>
<div class="wrap" ref="threeContainer"></div>
<button @click="changeCameraAdd">+</button>
<button>相机fov</button>
<button @click="changeCameraDe">-</button>
</template>
updateProjectionMatrix()方法来更新投影矩阵,以确保场景在新的fov参数下正确渲染
截面near、far对视角的影响
近远截面及fov构成视椎体,当远近界面位置不恰当时,物体可能位于视椎体之外,渲染不出来。
js
<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>
js
function nearAdd() {
camera.near += 10;
camera.updateProjectionMatrix();
}
function nearDe() {
camera.near -= 10;
camera.updateProjectionMatrix();
}
相机位置对视角的影响
js
<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>
js
function cameraYAdd() {
camera.position.x += 10;
controls.update();
}
function cameraXdd() {
camera.position.z += 10;
controls.update();
}
物体位置对视角的影响
js
<template>
<div class="wrap" ref="threeContainer"></div>
<button @click="meshAdd">Y轴+</button>
<button>物体位置</button>
<button @click="meshDe">Y轴-</button>
</template>
arduino
function meshAdd() {
mesh.position.y += 10;
}
function meshDe() {
mesh.position.y -= 10;
}