【Threejs】入门到并没放弃
前言:
一阶段的任务完成后,有幸被安排来调研
3D
相关内容,提到3D
那就不能不提threejs
,此篇文章就从最基础的示例入手,来完成基础的入门动作,如果需要完整代码,可以私信我。
-
既然我们要使用
Threejs
,那我们就需要它到底是啥 ??? -
它和
WebGL
、OpenGL
有啥区别 ??? -
为什么我们要用
Threejs
,而不用WebGL
来开发 ??? -
更或者我们能直接用
OpenGL
来开发web
页面吗 ???
概念介绍:
Threejs
是什么:
Three.js 是一个纯
JavaScript
实现的,是一个用于创建和呈现实时3D
渲染库,它是一个基于WebGL
的封装,为开发者提供了一套易于使用的API,使得在网页上实现复杂的3D可视化变得更加简单和高效。 github地址,截止当前:github
上的start
94 k
,fork
34.9 k
。
WebGL
是什么:
WebGL(Web Graphics Library)
是一种基于JavaScript
的图形库,用于在网页上通过浏览器进行硬件加速的2D
和3D
图形渲染。WebGL
可以直接访问计算机的图形硬件,通过GPU
(图形处理单元)实现高性能的图形渲染。
Threejs
和WebGL
区别如下:
- 抽象层级不同:
Three.js
是建立在WebGL
之上的一个抽象层,提供了更高级别的API
,使得使用者更轻松地创建和操作3D
场景。WebGL
则是直接操作GPU
的底层API
。 - 复杂度:使用
Three.js
相对于直接使用WebGL
,可以更快速地创建复杂的3D
交互效果。Three.js
封装了很多底层细节,提供了更简单的使用接口,减少了一些重复的工作和处理细节。 - 兼容性:
Three.js
会自动处理浏览器兼容性和底层WebGL
的复杂性,这样您不需要担心不同浏览器之间的差异。而直接使用WebGL
则需要您自己处理浏览器兼容性问题。
总结来说,
Three.js
是一个建立在WebGL
之上的高级库,为开发者提供了更方便的工具和接口来创建Web
上的3D
图形。WebGL
则是原生的、复杂的JavascripAPI
,直接操作GPU
实现高性能的图形渲染。
OpenGL
是什么:
OpenGL(Open Graphics Library)
是一个跨平台的、用于渲染2D
和3D
图形的图形库。它提供了一套用于绘制复杂图形的函数和接口,以及用于管理图形资源和状态的机制。它是一个底层的图形库,可以直接与计算机的图形硬件进行交互,提供高性能的图形渲染能力。它可以用于开发应用程序,包括游戏、虚拟现实、科学可视化、CAD
(计算机辅助设计)以及其他需要实时图形渲染的领域。可以在多个操作系统和硬件平台上使用,例如Windows 、macOS、Linux
和移动设备等。它可以与多种编程语言(C++、Python、Java
等)进行集成,方便开发。
WebGL
和OpenGL
的区别如下:
技术 | 应用平台 | 程序语言 | 硬件访问 | |
---|---|---|---|---|
WebGL | web 网页 | 主要依赖于 JavaScript | 通过浏览器来间接实现硬件加速 | |
OpenGL | Windows 、macOS、Linux 和移动设备等可 | 可以使用多种编程语言进行开发,例如 C++、Python、Java 等 | 直接访问计算机的图形硬件 |
总结:
Threejs
就是封装好的WebGL
,WebGL
就是前端界的 OpenGL
,OpenGL
是应用于桌面端的WebGL
。
Threejs
整体大概结构
下面是基于自己当前的研究出一张结构图,我们可以看到要得到一个完整的场景,需要的元素还是蛮多的。
- 场景(
Scene
):场景属于threejs
中最基础的组件,其他物体、灯光、摄像机都依托场景为基础 - 渲染器(
Renderer
):负责将camera
看到的内容通过绘制给到canvas
- 相机(
Camera
): 负责当眼睛,通过设置在不同角度,看到不同内容 - 物体(
Mesh
):可见物体,例如:猫、狗、山、树、花、草等
threejs
第一个场景
毕竟站在岸上学不会游泳,下面我就创建一个项目来尝试一下:
当前项目使用的是
parcel
来辅助开发,parcel
是一个轻量级的、零配置的打包工具,且支持热替换。
初始化package.json
npm init -y
安装打包工具parcel
npm install --save-dev parcel
配置项目启动和打包命令:
"scripts": {
"dev": "parcel src/index.html",
"build": "parcel build src/index.html"
}
新建src/index.html
引入threejs
文件
<script type="module" src="./src/main.js"></script>
这里的type
必须是 module
type="module"
下面是完整示例:
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Three.js入门</title>
</head>
<body>
<script src="./script.js" type="module"></script>
</body>
</html
新建src/script.js
并启动项目
import * as THREE from "three";
console.log(THREE); // 验证是否正确添加到项目中
万事俱备,正式开搞!!!
在后面的示例中,只修改
js
中的代码,html
不改
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
console.log(THREE);
// 初始化渲染器, antialias 是用于设置抗锯齿
const renderer = new THREE.WebGLRenderer({ antialias: true });
// 将渲染器的像素比设置为与设备像素比相同的值,以匹配设备的分辨率,并提供更好的显示效果。
renderer.pixelRatio = window.devicePixelRatio;
//设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl 渲染的canvas 内容添加到body
document.body.append(renderer.domElement);
// 创建场景
const scene = new THREE.Scene();
// 添加相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(5, 5, 10);
camera.lookAt(0, 0, 0);
// 添加坐标轴
const axis = new THREE.AxesHelper(5);
scene.add(axis);
// 添加立方体
const geometry = new THREE.BoxGeometry(4, 4, 4); // 立方体
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); // 材质
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// 添加控制器(放大、缩小、旋转)
const controls = new OrbitControls(camera, renderer.domElement);
controls.update();
function animate() {
renderer.render(scene, camera);
}
// 监听鼠标移动事件
window.addEventListener('mousemove', () => {
animate();
});
// 渲染
renderer.render(scene, camera);
页面展示:
当前页面添加了一个最简单的
box
的基础几何图形,坐标轴,并添加了控制器工具,支持放大缩小,旋转。至此,我们已经开启threejs
的大门,是不是感觉也挺简单的,哈哈哈,自己动手试试吧。
参考文档:你的第一个 three.js 场景:你好,立方体!:
让物体动起来
在上面的例子里,我们已经知道怎么在页面里添加物体,并设置相机位置和控制器等功能,现在我们就尝试让物体运动起来。
核心的方法就是这个方法
requestAnimationFrame
,这个方法告诉浏览器您希望在下一次绘制帧之前执行某些操作,当前是在渲染下一帧时候就回调用render
函数,从而改变cube
的位置,这样我们视觉看起来就是每帧都在运动。
requestAnimationFrame(render())
完整代码如下:
import * as THREE from 'three';
// 导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机位置
camera.position.set(0, 0, 10);
scene.add(camera);
// 添加物体
// 创建几何体
const cubeGeometry = new THREE.BoxGeometry();
const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
// 根据几何体和材质创建物体
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// 设置物体旋转 X Y Z Math.PI= 180' Math.PI / 4 =45',最后一个参数可以设置旋转的先后顺序
cube.rotation.set(Math.PI / 4, 0, 0, 'XYZ');
// 设置物体缩放
cube.scale.set(1, 2, 3);
// 将几何体添加到场景中
scene.add(cube);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
//设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl 渲染的canvas 内容添加到body
document.body.appendChild(renderer.domElement);
//使用渲染器通过相机将场景渲染进来
renderer.render(scene, camera);
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
function render() {
// 自动移动位置
cube.position.x += 0.01;
cube.rotation.x += 0.01;
if (cube.position.x > 5) {
cube.position.x = 0;
}
renderer.render(scene, camera);
//渲染下一帧时候就回调用render函数
requestAnimationFrame(render);
}
render();
页面展现:
当前模型在每一帧的运动过程中,改变着
position
和rotation
,以X
轴为中心坐标顺时针旋转,位置也同样以X
轴的定位向右移动
给场景添加模型
在web
前端且非专业的领域中,glb
、gltf
、fbx
三种格式更为常用
核心代码:
这里就贴一下核心代码,其他的代码就需要宝子们自己填空喽,其实和上面示例差不多
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader';
....
// 加载模型
const loader = new GLTFLoader();
const fbxloader = new FBXLoader();
// 载入桌子 - gltf 文件 - 静态模型
loader.load('./model/SimpleSkinning.gltf', (gltf) => {
gltf.scene.scale.set(8, 1, 3);
gltf.scene.position.x = -5;
gltf.scene.position.y = 5;
gltf.scene.position.z = 1;
scene.add(gltf.scene);
});
// 载入模拟人 - glb 文件 - 静态模型
loader.load('./model/girl.glb', (gltf) => {
gltf.scene.scale.set(7, 7, 7);
gltf.scene.position.x = 5;
gltf.scene.position.y = 2;
gltf.scene.position.z = 10;
scene.add(gltf.scene);
});
// 载入动漫女孩 - 带动作
fbxloader.load('./model/Hip Hop Dancing-withskin.fbx', (object) => {
object.scale.set(10, 10, 10);
object.position.set(1, 0, 20);
scene.add(object);
mixer = new THREE.AnimationMixer(object);
const action = mixer.clipAction(object.animations[0]);
action.play();
animate();
});
// 执行动作
function animate() {
requestAnimationFrame(animate);
const mixerUpdateDelta = clock.getDelta();
mixer.update(mixerUpdateDelta);
renderer.render(scene, camera);
}
页面展现:
总结:
至此我们已经完成了
threejs
的入门操作,可以自己建一个简单的场景,可以自己添加模型,设置模型移动,后面就需要再多的去了解threejs
还有哪些功能,毕竟我们也才知道这冰山一角,设置不同灯光、不同模型的加载、如何创建模型、怎么添加动作、如何让导出的文件更小这些问题,我们还不知道,距离真正的使用它完成项目,还有十万八千里,但它也确实是有趣的,所以那就继续研究下去吧!!!
参考资料:
-
threejs - 文档地址 (官网的文档当前只有英文)
-
社区中文文档 (虽不全,也可以作为参考)
-
B站:老陈打码
相关链接:
喜欢就加个关注吧!
转载自:https://juejin.cn/post/7268539219161169979