文章目录
1. 引言
工作原因,去年接触了WebGL的项目,明显的感受到了作为前端开发人员的乐趣。这种体验是后台管理系统不能比的。虽然我也开发过复杂的管理系统功能,但是三维场景的吸引力显然不在同一个维度。
因此,我想深入学习一下WebGL,从熟悉的框架Babylon.js入手,循序渐进,巩固已经了解的知识点,扩展知识面,做到精通Babylon.js。
在这个过程中,我会记录自己用到的每一个知识点,每个可能踩坑的地方。我尽量不使用AI生成的内容,以自己的语言表达,手敲每一个文字。
2. Babylon.js 的使用
2.1 Babylon.js广场
- 在学习和开发Babylon时,最重要的工具是Babylon.js Playground。
- Babylon.js操场是个非常好用的工具,对于新手非常友好。相当于提前为你集成好了Babylon.js的开发环境,只要输入Babylon.js框架相关的代码即可,并在右侧查看即时更新。
- 不仅如此,Babylon.js操场还有大量实际例子,可以通过关键字搜索相关的例子。比如哪个属性不太明白,直接搜索就能查到属性的用法。
2.2 Babylon.js 文档
- Babylon.js提供了丰富的API,能帮助开发人员尽可能轻松地实现自己想要的功能
- 并且,Babylon.js提供了功能强大的API学习网站,可以通过文档学习想知道的功能
- 直接访问官网:https://doc.babylonjs.com
- 左侧导航栏,选择API,即可查看开发文档
2.3 Babylon.js沙盒
- Babylon.js沙盒是一个功能强大的、基于web的3D资源查看器和调试工具,适用于使用Babylon.js的开发人员和设计师。支持用户通过直观的界面加载和检查3D模型、纹理、动画和材质。沙盒是测试和微调项目的重要工具。
- 地址:https://sandbox.babylonjs.com/
- 支持的文件格式:.gltf、.glb、.obj、.stl、.babylon
3. Web项目引入 Babylon.js
3.1 HTML项目引入
- 虽然可以通过CDN引入,但是不应该用于生产环境,CDN的目的是为学习。
- Download 下载Babylon.js在云端的模板文件。
- DownLoad 下载包含本地版本Babylon.max.js的模板文件
<script src="https://cdn.babylonjs.com/babylon.js"></script>
3.2 ES6/NPM引入
- 所有babylon ES6包都可以在npm作用域@babylonjs中找到。
- @babylonjs/core-巴比伦的核心。
- @babylonjs/材料-巴比伦支持的先进材料的集合。
- @babylonjs/loaders-巴比伦的所有官方加载器(OBJ、STL、glTF)。
- @babylonjs/post processes-巴比伦的后处理。
- @babylonjs/程序纹理-官方支持的程序纹理。
- @babylonjs/序列化器-场景/网格序列化器。
- @babylonjs/gui-Babylon.js图形用户界面模块。
- @babylonjs/viewer-独立的Babylon.js查看器。
- @babylonjs/inspector-用于可视化调试的Babylon.js检查器。
- @babylonjs/KTX2解码器-巴比伦的KTX2解码器模块。
安装Babylon.js
npm install @babylonjs/core
引入全部Babylon.js
import * as BABYLON from "@babylonjs/core/Legacy/legacy.js";
加载特定的类
import { Engine, Scene } from "@babylonjs/core";
4. 快速体验:Babylon.js 的“Hello World”
创建第一个三维场景
想象一下,站在一片空白的画布前,握着一支代码组成的笔。这支画笔可以在画布上绘制出任何3D 世界:雄伟的山脉、浩瀚的海洋、繁华的城市,甚至是充满幻想的外星景观。
在开始创作之前,需要了解一些基本概念和工具:
1、画布: 在 BabylonJS 中,这块画布就是 HTML5 Canvas 元素。它是 3D 场景的渲染目标,也是用户与 3D 世界交互的窗口。
2、引擎: BabylonJS 引擎就是画笔。提供了丰富的 API,涵盖了从创建场景、添加物体到应用
3、光源: 光照是 3D 世界中不可或缺的一部分。它不仅影响物体的外观,还决定了场景的氛围和情感基调。
4、相机: 相机决定了我们观察 3D 世界的方式。不同的相机类型和设置可以带来截然不同的视觉效果和用户体验。
5、物体: 几何体 和 网格 是构成 3D 世界的基本元素。从简单的立方体到复杂的人物模型,物体是 3D 场景中可见的实体。
6、颜料: 材质 和 纹理 就是颜料。它们赋予 3D 物体外观和质感,使其看起来更加真实和生动。无论是创建整个世界还是只是将一个模型放置在网页中,都需要一个场景来包含世界或模型,一个相机来查看它,一个灯光来照亮它,当然,还需要至少一个可视对象作为模型。
所有模型,无论是一个盒子还是一个复杂的角色,都是由三角形或小平面的网格组成的。
用一个HTML文件做例子,CDN引入Babylon.js。引入的js文件比较多,大多数都用不到,只是做个示范。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Babylon.js sample code</title>
<!-- Babylon.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://preview.babylonjs.com/ammo.js"></script>
<script src="https://preview.babylonjs.com/cannon.js"></script>
<script src="https://preview.babylonjs.com/Oimo.js"></script>
<script src="https://preview.babylonjs.com/earcut.min.js"></script>
<script src="https://preview.babylonjs.com/babylon.js"></script>
<script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
<script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
<script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
<script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
<script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
<style>
html,
body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#renderCanvas {
width: 100%;
height: 100%;
touch-action: none;
}
</style>
</head>
<body>
// 创建画布,作为三维场景的容器
<canvas id="renderCanvas"></canvas>
<script>
// 定位到容器
var canvas = document.getElementById("renderCanvas");
var startRenderLoop = function (engine, canvas) {
engine.runRenderLoop(function () {
if (sceneToRender && sceneToRender.activeCamera) {
sceneToRender.render();
}
});
}
var engine = null;
var scene = null;
var sceneToRender = null;
var createDefaultEngine = function () {
return new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true,
stencil: true,
disableWebGL2Support: false
});
};
const createScene = () => {
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 2.5, 3, new BABYLON
.Vector3(0, 0, 0));
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0));
const box = BABYLON.MeshBuilder.CreateBox("box", {});
return scene;
}
window.initFunction = async function () {
var asyncEngineCreation = async function () {
try {
return createDefaultEngine();
} catch (e) {
console.log(
"the available createEngine function failed. Creating the default engine instead"
);
return createDefaultEngine();
}
}
window.engine = await asyncEngineCreation();
if (!engine) throw 'engine should not be null.';
startRenderLoop(engine, canvas);
window.scene = createScene();
};
initFunction().then(() => {
sceneToRender = scene
});
// Resize
window.addEventListener("resize", function () {
engine.resize();
});
</script>
</body>
</html>
5. 变量解析
5.1 引擎
- 引擎变量是负责与WebGL、Audio等低级API接口的类。创建Babylon场景【将视觉效果渲染到屏幕的上下文】的构造函数需要引擎与这些低级API进行通信。这就是为什么在创建场景时需要引擎变量。
5.2 MeshBuilder
- BABYLON.MeshBuilder 创建的长方体的中心位于原点,需要三个参数。名称【字符串】、配置项【对象】、场景。这里将配置项设置为没有属性的空对象,该长方体的宽度、高度和深度会默认为单位大小。
const createScene = () => {
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 2.5, 3, new BABYLON.Vector3(0, 0, 0));
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0));
const box = BABYLON.MeshBuilder.CreateBox("box", {});
return scene;
}
5.3 引入场景或模型
- 参数:文件地址、文件名、目标场景、配置
BABYLON.ImportMeshAsync(文件地址 + 文件名, 场景, 配置);
5.4 操控引入的模型
- 为了对结果进行操作并操纵对象,ImportMeshAsync在Promise后面使用then方法调用一个带有Promise结果的函数。结果是一个对象,其中包含属性网格,属性网格包含所有加载的模型。可以使用这个数组或它们的名称来操纵每个网格。
BABYLON.ImportMeshAsync("/relative path/myFile").then((result) => {
result.meshes[1].position.x = 20;
const myMesh1 = scene.getMeshByName("myMesh_1");
myMesh1.rotation.y = Math.PI / 2;
});
7. 总结与下一章预告
7.1 必要元素
- 这一章介绍了一个三维场景的必要元素:画布、引擎、相机、灯光,后面会详细介绍这些要素
7.2 下一章预告
- 《创建你的第一个 3D 场景:立方体、球体与平面》:学习添加基本几何体、调整位置/旋转/缩放属性。