三要素之间关系:
有了虚拟场景Scene,相机录像Camera,在相机小屏幕上看到的Renderer
Scene当前空间 Mesh人在场景 Camera相机录像 Renderer显示器上
首先先描述下Scene:
这个场景为三要素之一,一切需要展示的东西都需要添加到Scene里面,也就是画布,你需要在页面展示的东西都需要add到Scene中,
在场景里面我们可以添加 Mesh网格模型、光源等
Mesh网格模型组成需要两部分 需要几何体Geometry 和对应的材质模型Material
1、如何创建Scene、camera 、renderer 三要素并渲染:
javascript
<!DOCTYPE html>
<html>
<head>
<title>three.js</title>
<meta charset="utf-8">
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="container"></div>
<!-- 类似于创建 并设置别名 -->
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"
}
}
</script>
<!-- 导入包名 -->
<script type="module">
import * as THREE from 'three';
// 创建一个新的场景对象
const scene = new THREE.Scene();
// 创建一个透视相机,参数分别为视野角度、宽高比、近平面和远平面
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 创建一个WebGL渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器的大小,使其充满整个窗口
renderer.setSize(window.innerWidth, window.innerHeight);
// 将渲染器的DOM元素添加到文档的body中
document.body.appendChild(renderer.domElement);
</script>
</body>
</html>
现在建立了场景、相机和渲染器;但是页面还是不能正常渲染的~
Threejs提供了正投影相机OrthographicCamera (opens new window)和透视投影相机PerspectiveCamera
OrthographicCamera:适用于:CAD 图纸、工程图、UI 设计、2D 游戏等场景,这些场景通常需要保持物体的比例和形状。
PerspectiveCamera:适用于:3D 游戏、虚拟现实、建筑设计等场景,这些场景通常需要模拟真实世界的视觉效果。
透视投影相机PerspectiveCamera:
透视投影相机的四个参数fov, aspect, near, far构成一个四棱台3D空间,被称为视锥体,只有视锥体之内的物体,才会渲染出来,视锥体范围之外的物体不会显示在Canvas画布上。
javascript
PerspectiveCamera( fov, aspect, near, far )
第一个参数是视野角度(FOV)。视野角度就是无论在什么时候,你所能在显示器上看到的场景的范围,它的单位是角度(与弧度区分开)。默认值:50
第二个参数是长宽比(aspect ratio)。 也就是你用一个物体的宽除以它的高的值。比如说,当你在一个宽屏电视上播放老电影时,可以看到图像仿佛是被压扁的。默认值:1
最后两个参数是近截面(near)和远截面(far)。 当物体某些部分比摄像机的远截面远或者比近截面近的时候,该这些部分将不会被渲染到场景中。或许现在你不用担心这个值的影响,但未来为了获得更好的渲染性能,你将可以在你的应用程序里去设置它。near默认值:0.1;far默认值:2000
创建正方体到场景中
javascript
// 创建一个网格模型
const geometry = new THREE.BoxGeometry(1, 1, 1); // 创建一个立方体几何体
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); // 创建一个材质对象
const mesh = new THREE.Mesh(geometry, material); // 创建一个网格模型对象
scene.add(mesh); // 将网格模型对象添加到场景中
这个时候Scene里面已经有了一个Mesh网格模型,也就是一个人进入到了想要拍摄的场景之中。默认在原点坐标
我们也可以设置这个人站在哪里:
javascript
// 创建一个网格模型
const geometry = new THREE.BoxGeometry(1, 1, 1); // 创建一个立方体几何体
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); // 创建一个材质对象
const mesh = new THREE.Mesh(geometry, material); // 创建一个网格模型对象
mesh.position.set(1,1,1,) // 设置网格模型对象的位置
scene.add(mesh); // 将网格模型对象添加到场景中
这个时候 我们 场景Scene准备好了,场景里面要拍摄的人Mesh也准备好了,相机camera也准备好了,这个时候我们需要相机放到一个可以拍摄到咱们物体的一个位置position,然后让相机看向哪里呢?
相机对象Camera具有位置属性.position,通过位置属性.position可以设置相机的位置。
javascript
// 创建一个透视相机,参数分别为视野角度、宽高比、近平面和远平面
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
//相机在Three.js三维坐标系中的位置
// 根据需要设置相机位置具体值
camera.position.set(5, 5, 5);
相机已经放到了xyz都为5的位置,默认看向xyz都为000的位置,现在我们想让它看向人也就是网格模型的位置
javascript
// 创建一个透视相机,参数分别为视野角度、宽高比、近平面和远平面
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
//相机在Three.js三维坐标系中的位置
// 根据需要设置相机位置具体值
camera.position.set(5, 5, 5);
// 设置相机方向(指向的场景对象)
camera.lookAt(mesh.position);
这个时候 页面还是不展示嘻嘻 不慌~
渲染场景
这是因为我们还没有对它进行真正的渲染。为此,我们需要使用一个被叫做"渲染循环"(render loop)或者"动画循环"(animate loop)的东西。
javascript
/**
* 动画函数
* 该函数通过不断地请求下一帧来实现动画效果
* 它在每一帧中调用渲染器来重新渲染场景和相机
*/
function animate() {
// 请求下一帧动画
requestAnimationFrame(animate);
// 使用当前场景和相机进行渲染
renderer.render(scene, camera);
}
// 调用animate函数开始动画
animate();
这下就相当于一直在录像了~
看下页面:
我们添加一个坐标系,这样就可以更好的看出所在的位置:
辅助观察坐标系同样的添加到场景中
javascript
// 创建辅助观察坐标系
const asesHelper = new THREE.AxesHelper(200);
scene.add(asesHelper);
three.js坐标轴颜色红R、绿G、蓝B分别对应坐标系的x、y、z轴,对于three.js的3D坐标系默认y轴朝上
我们可以让Z轴朝上
javascript
// 默认是 0 1 0
camera.up.x = 0;
camera.up.y = 0;
camera.up.z = 1;
这个时候我们想让他跟随鼠标移动,可拖动旋转我们使用
javascript
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const controls = new OrbitControls(camera, renderer.domElement)
function animate() {
controls.update();
// 请求下一帧动画
requestAnimationFrame(animate);
// 使用当前场景和相机进行渲染
renderer.render(scene, camera);
}
这时候我们就可以随意的拖动
我们可以设置这个人Mesh网格模型翻跟头,比如我们让他跟随z轴渲染,只需要在循环动画中增加旋转即可
javascript
function animate() {
// 跟随Z轴旋转
mesh.rotation.z += 0.01;
controls.update();
// 请求下一帧动画
requestAnimationFrame(animate);
// 使用当前场景和相机进行渲染
renderer.render(scene, camera);
}
好了,到目前位置,做了哪些?
- 创建场景
- 在场景中增加Mesh模型,模型由几何体和它对应的材质组成,设置了它的定位位置
- 增加camera相机录像,它的四个参数的含义,位置position,看向何方lookAt
- 渲染器renderer
- 增加辅助坐标系,默认Y朝上
- 增加控制器
- 增加动画围绕z轴旋转