大白话react第十八章React 与 WebGL 项目的高级拓展与优化
大白话react第十八章React 与 WebGL 项目的高级拓展与优化
1. 实现 3D 模型的导入与动画
在之前的基础上,我们可以导入更复杂的 3D 模型,并且让这些模型动起来,就像在游戏里看到的角色和场景一样。这里我们使用 GLTF
格式的模型,它是一种常用的 3D 模型格式,并且 three.js 提供了很好的支持。
// 引入 React 的 useEffect 和 useRef 钩子
import React, { useEffect, useRef } from'react';
// 引入 three.js 用于创建 3D 场景
import * as THREE from 'three';
// 引入 GLTFLoader 用于加载 GLTF 格式的 3D 模型
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';const ModelAnimationComponent = () => {// 创建一个 ref 用于引用存放 3D 场景的 DOM 元素const containerRef = useRef(null);useEffect(() => {// 创建 three.js 的场景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 元素添加到 ref 对应的 DOM 元素中containerRef.current.appendChild(renderer.domElement);// 创建一个环境光,让场景整体更亮const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);scene.add(ambientLight);// 创建一个点光源,让物体有明暗对比const pointLight = new THREE.PointLight(0xffffff, 1);pointLight.position.set(2, 5, 2);scene.add(pointLight);// 创建一个 GLTF 加载器const loader = new GLTFLoader();// 加载 GLTF 格式的 3D 模型loader.load('path/to/your/model.gltf', (gltf) => {// 获取加载的模型const model = gltf.scene;// 将模型添加到场景中scene.add(model);// 如果模型有动画if (gltf.animations.length > 0) {// 创建一个动画混合器,用于管理动画const mixer = new THREE.AnimationMixer(model);// 获取第一个动画const action = mixer.clipAction(gltf.animations[0]);// 播放动画action.play();// 定义渲染函数const animate = () => {// 请求下一帧动画requestAnimationFrame(animate);// 更新动画混合器mixer.update(0.01);// 渲染场景renderer.render(scene, camera);};// 开始动画循环animate();}});// 设置相机位置camera.position.z = 5;// 组件卸载时清理资源return () => {containerRef.current.removeChild(renderer.domElement);};}, []);return (// 创建一个 div 用于存放 3D 场景<div ref={containerRef} />);
};export default ModelAnimationComponent;
2. 实现多场景切换
在一些大型的 3D 应用中,可能需要多个不同的场景,并且能够在这些场景之间自由切换。我们可以通过管理多个场景对象,根据用户的操作来显示不同的场景。
// 引入 React 的 useEffect、useRef 和 useState 钩子
import React, { useEffect, useRef, useState } from'react';
// 引入 three.js 用于创建 3D 场景
import * as THREE from 'three';const MultiSceneComponent = () => {// 创建一个 ref 用于引用存放 3D 场景的 DOM 元素const containerRef = useRef(null);// 创建一个状态来存储当前显示的场景索引const [currentSceneIndex, setCurrentSceneIndex] = useState(0);useEffect(() => {// 创建两个 three.js 的场景const scenes = [new THREE.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 元素添加到 ref 对应的 DOM 元素中containerRef.current.appendChild(renderer.domElement);// 为第一个场景添加一个立方体const cubeGeometry = new THREE.BoxGeometry(2, 2, 2);const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);scenes[0].add(cube);// 为第二个场景添加一个球体const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);scenes[1].add(sphere);// 设置相机位置camera.position.z = 5;// 定义渲染函数const animate = () => {// 请求下一帧动画requestAnimationFrame(animate);// 获取当前要显示的场景const currentScene = scenes[currentSceneIndex];// 渲染当前场景renderer.render(currentScene, camera);};// 开始动画循环animate();// 组件卸载时清理资源return () => {containerRef.current.removeChild(renderer.domElement);};}, [currentSceneIndex]);return (<div>{/* 创建一个 div 用于存放 3D 场景 */}<div ref={containerRef} />{/* 创建按钮用于切换场景 */}<button onClick={() => setCurrentSceneIndex(0)}>切换到场景 1</button><button onClick={() => setCurrentSceneIndex(1)}>切换到场景 2</button></div>);
};export default MultiSceneComponent;
3. 实现 WebGL 与后端数据交互
有时候我们需要从后端获取数据,然后根据这些数据来更新 3D 场景。这里我们模拟一个从后端获取数据的过程,然后根据数据来改变 3D 物体的属性。
// 引入 React 的 useEffect、useRef 和 useState 钩子
import React, { useEffect, useRef, useState } from'react';
// 引入 three.js 用于创建 3D 场景
import * as THREE from 'three';const DataInteractionComponent = () => {// 创建一个 ref 用于引用存放 3D 场景的 DOM 元素const containerRef = useRef(null);// 创建一个状态来存储从后端获取的数据const [data, setData] = useState(null);useEffect(() => {// 模拟从后端获取数据const fetchData = async () => {try {const response = await fetch('https://example.com/api/data');const jsonData = await response.json();setData(jsonData);} catch (error) {console.error('获取数据失败:', error);}};fetchData();}, []);useEffect(() => {if (data) {// 创建 three.js 的场景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 元素添加到 ref 对应的 DOM 元素中containerRef.current.appendChild(renderer.domElement);// 根据后端数据创建一个立方体const cubeGeometry = new THREE.BoxGeometry(data.size, data.size, data.size);const cubeMaterial = new THREE.MeshBasicMaterial({ color: data.color });const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);scene.add(cube);// 设置相机位置camera.position.z = 5;// 定义渲染函数const animate = () => {// 请求下一帧动画requestAnimationFrame(animate);// 渲染场景renderer.render(scene, camera);};// 开始动画循环animate();// 组件卸载时清理资源return () => {containerRef.current.removeChild(renderer.domElement);};}}, [data]);return (// 创建一个 div 用于存放 3D 场景<div ref={containerRef} />);
};export default DataInteractionComponent;
通过这些高级拓展和优化,你的 React 与 WebGL 项目会变得更加复杂和强大,能够满足更多的实际需求。
GLTF格式的特点和优势
GLTF 格式的特点和优势介绍
什么是 GLTF 格式
GLTF 就像是一个专门用来装 3D 模型和场景的“盒子”,它能把 3D 世界里的各种东西,像模型的形状、颜色、动画这些信息,有条理地打包起来,方便在不同的地方使用。
特点
1. 轻量化
GLTF 格式很“轻”,就好比一个轻装上阵的运动员。它不会携带一堆没用的东西,只装真正需要的信息。这样在传输的时候,速度就会很快,就像快递送一个很轻的包裹一样。而且它用一种叫 JSON 的格式来记录模型的基本信息,这种格式简单易懂,计算机处理起来也不费劲。
2. 通用性强
不管你用的是电脑、手机,还是其他什么设备,只要这个设备能处理 3D 内容,基本上都能打开 GLTF 格式的文件。就像一把万能钥匙,能开很多不同的“锁”,在各种 3D 软件、游戏引擎里都能使用。
3. 支持动画和材质
GLTF 可以把模型的动画也一起打包进去。想象一下,一个 3D 人物模型,它走路、跑步、挥手这些动作的动画,都能和模型本身放在一个“盒子”里。同时,它还能记录模型的材质信息,比如这个模型看起来是金属的、木头的,还是塑料的,都能清晰地表现出来。
4. 二进制扩展
除了基本的 JSON 格式,GLTF 还有二进制扩展。这就好比在原来的“盒子”外面又加了一个更结实的“外套”,能把一些更复杂、更占空间的数据,像模型的顶点数据,用二进制的方式存储,这样能让文件更小,读取速度也更快。
优势
1. 加载速度快
因为文件轻,所以在网页或者应用里加载 GLTF 格式的 3D 模型时,速度会非常快。用户不用等很长时间,就能看到模型,体验就会很好。
2. 易于编辑和共享
由于它的结构清晰,开发者很容易对 GLTF 文件进行编辑和修改。而且因为通用性强,不同的人之间分享这个格式的文件也很方便,大家都能打开和使用。
3. 跨平台兼容性好
不管是在电脑上的浏览器里,还是在手机的 APP 中,GLTF 格式的模型都能正常显示和使用。这样就可以让更多的人在不同的设备上体验到 3D 内容。
代码示例(使用 Three.js 加载 GLTF 模型)
// 引入 React 的 useEffect 和 useRef 钩子
import React, { useEffect, useRef } from'react';
// 引入 three.js 库,用于创建 3D 场景
import * as THREE from 'three';
// 引入 GLTFLoader 模块,专门用于加载 GLTF 格式的文件
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';// 定义一个 React 组件,用于展示加载的 GLTF 模型
const GLTFModelComponent = () => {// 创建一个 ref 对象,用于引用后续要添加 3D 场景的 DOM 元素const containerRef = useRef(null);useEffect(() => {// 创建一个 three.js 的场景对象,相当于一个 3D 世界的舞台const scene = new THREE.Scene();// 创建一个透视相机,设置视角、宽高比、近裁剪面和远裁剪面// 就像我们用相机拍照一样,确定我们看 3D 场景的视角和范围const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);// 创建一个 WebGL 渲染器,它的作用是把 3D 场景渲染成我们能看到的 2D 画面const renderer = new THREE.WebGLRenderer();// 设置渲染器的大小为窗口的宽度和高度,让场景能占满整个窗口renderer.setSize(window.innerWidth, window.innerHeight);// 将渲染器生成的 DOM 元素添加到之前创建的 ref 对应的 DOM 元素中containerRef.current.appendChild(renderer.domElement);// 创建一个环境光,让整个场景有一个基本的亮度,就像打开房间里的大灯const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);// 将环境光添加到场景中scene.add(ambientLight);// 创建一个点光源,它就像一个手电筒,可以照亮特定的区域const pointLight = new THREE.PointLight(0xffffff, 1);// 设置点光源的位置pointLight.position.set(2, 5, 2);// 将点光源添加到场景中scene.add(pointLight);// 创建一个 GLTFLoader 实例,用于加载 GLTF 文件const loader = new GLTFLoader();// 加载指定路径的 GLTF 文件// 第一个参数是文件的路径,第二个参数是加载成功后的回调函数loader.load('path/to/your/model.gltf', (gltf) => {// 获取加载的 GLTF 文件中的场景对象,也就是模型本身const model = gltf.scene;// 将模型添加到 three.js 的场景中scene.add(model);// 定义一个动画循环函数,用于不断更新和渲染场景const animate = () => {// 请求浏览器在下一次重绘之前调用 animate 函数,实现动画循环requestAnimationFrame(animate);// 渲染场景和相机,把 3D 场景变成我们能看到的画面renderer.render(scene, camera);};// 调用动画循环函数,开始动画animate();});// 设置相机的位置,让相机离场景有一定的距离,能看到整个场景camera.position.z = 5;// 组件卸载时的清理函数return () => {// 从 ref 对应的 DOM 元素中移除渲染器的 DOM 元素containerRef.current.removeChild(renderer.domElement);};}, []);// 返回一个 div 元素,用于承载 3D 场景return (<div ref={containerRef} />);
};// 导出这个组件,方便其他地方使用
export default GLTFModelComponent;
在这个代码示例中,我们使用 React 和 Three.js 来加载一个 GLTF 格式的 3D 模型。首先创建了一个 3D 场景和相机,然后添加了灯光,接着使用 GLTFLoader
加载 GLTF 文件,最后把加载的模型添加到场景中并进行渲染。这样就能在网页上看到加载的 3D 模型啦。
如何将GLTF格式的模型导入到WebGL项目中?
如何将 GLTF 格式的模型导入到 WebGL 项目中
1. 准备工作
在把 GLTF 格式的模型导入到 WebGL 项目之前,你得先有一个 WebGL 项目的基础框架,这里我们用 three.js
这个库,它能让我们更轻松地操作 WebGL。另外,你得准备好一个 GLTF 格式的 3D 模型文件,就好比你要往房子里放一件家具,得先有房子和家具。
2. 安装依赖
如果你还没安装 three.js
,可以用下面的命令来安装:
npm install three
3. 编写代码
下面是详细的代码示例,我会逐行加上注释,让你能看明白每一步是干啥的。
// 引入 React 的 useEffect 和 useRef 钩子,useEffect 用于处理副作用,useRef 用于创建一个可变的 ref 对象
import React, { useEffect, useRef } from'react';
// 引入 three.js 库,这是一个强大的 WebGL 抽象库,能让我们更方便地创建 3D 场景
import * as THREE from 'three';
// 引入 GLTFLoader 模块,它专门用于加载 GLTF 格式的模型
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';const GLTFModelComponent = () => {// 创建一个 ref 对象,用于引用后续要渲染 3D 场景的 DOM 元素const containerRef = useRef(null);useEffect(() => {// 创建一个新的 three.js 场景,这就像是一个舞台,所有的 3D 对象都会放在这个舞台上const scene = new THREE.Scene();// 创建一个透视相机,它决定了我们从哪个角度、多大范围去看这个 3D 场景const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);// 创建一个 WebGL 渲染器,它负责把 3D 场景渲染成我们能看到的画面const renderer = new THREE.WebGLRenderer();// 设置渲染器的大小为浏览器窗口的宽度和高度,这样画面就能占满整个窗口renderer.setSize(window.innerWidth, window.innerHeight);// 把渲染器生成的 DOM 元素添加到之前创建的 ref 对应的 DOM 元素中,这样渲染的画面就能显示在网页上了containerRef.current.appendChild(renderer.domElement);// 创建一个环境光,它会均匀地照亮整个场景,让场景不会太暗const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);// 把环境光添加到场景中scene.add(ambientLight);// 创建一个点光源,它就像一个灯泡,能产生有方向的光照,让物体有明暗对比const pointLight = new THREE.PointLight(0xffffff, 1);// 设置点光源的位置pointLight.position.set(2, 5, 2);// 把点光源添加到场景中scene.add(pointLight);// 创建一个 GLTFLoader 实例,用于加载 GLTF 模型const loader = new GLTFLoader();// 调用 loader 的 load 方法来加载 GLTF 模型,这里的 'path/to/your/model.gltf' 要替换成你实际的模型文件路径loader.load('path/to/your/model.gltf', (gltf) => {// 当模型加载成功后,gltf.scene 就是加载好的 3D 模型对象const model = gltf.scene;// 把模型添加到场景中,这样模型就会出现在我们的舞台上了scene.add(model);// 定义一个动画函数,用于实现动画效果const animate = () => {// 请求浏览器在下一次重绘之前调用 animate 函数,实现动画循环requestAnimationFrame(animate);// 这里可以添加模型的动画逻辑,比如让模型旋转,下面的代码让模型绕 y 轴旋转model.rotation.y += 0.01;// 调用渲染器的 render 方法,把场景和相机作为参数传入,渲染出当前的画面renderer.render(scene, camera);};// 调用 animate 函数,开始动画循环animate();}, undefined, (error) => {// 如果加载模型过程中出现错误,打印错误信息console.error('加载模型时出错:', error);});// 设置相机的位置,让相机往后退一点,这样能看到整个场景camera.position.z = 5;// 组件卸载时的清理函数,移除渲染器的 DOM 元素,避免内存泄漏return () => {containerRef.current.removeChild(renderer.domElement);};}, []);return (// 创建一个 div 元素,用于容纳 3D 场景,通过 ref 属性关联到之前创建的 ref 对象<div ref={containerRef} />);
};export default GLTFModelComponent;
4. 代码解释
- 引入必要的库和模块:
three.js
是核心库,GLTFLoader
专门用来加载 GLTF 模型。 - 创建场景、相机和渲染器:场景是 3D 对象的容器,相机决定了我们的视角,渲染器负责把场景渲染成画面。
- 添加光照:环境光和点光源能让模型看起来更真实,有明暗对比。
- 加载 GLTF 模型:使用
GLTFLoader
的load
方法,传入模型文件路径,加载成功后把模型添加到场景中。 - 实现动画:通过
requestAnimationFrame
实现动画循环,在循环中更新模型的状态,然后重新渲染画面。 - 清理工作:组件卸载时,移除渲染器的 DOM 元素,避免内存泄漏。
5. 注意事项
- 要把
'path/to/your/model.gltf'
替换成你实际的 GLTF 模型文件路径。 - 如果模型文件有纹理等资源,要确保这些资源的路径也正确。
通过以上步骤,你就能把 GLTF 格式的模型导入到 WebGL 项目中,并且让它动起来啦!
常用的处理GLTF格式的JavaScript库
常用处理 GLTF 格式的 JavaScript 库介绍
在开发使用 GLTF 格式 3D 模型的网页应用时,有几个常用的 JavaScript 库能帮助我们轻松处理这些模型。下面详细介绍这些库以及给出使用示例。
1. three.js
- 简介:three.js 是一个非常流行的 WebGL 抽象库,它把复杂的 WebGL 操作封装成简单的 API,让开发者能轻松创建和展示 3D 场景,同时也对 GLTF 格式有很好的支持。
- 代码示例:
// 引入 React 的 useEffect 和 useRef 钩子,用于在组件挂载和卸载时执行操作以及引用 DOM 元素
import React, { useEffect, useRef } from'react';
// 引入 three.js 库,用于创建 3D 场景
import * as THREE from 'three';
// 引入 GLTFLoader 模块,专门用于加载 GLTF 格式的模型
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';const ThreeJSGLTFExample = () => {// 创建一个 ref 对象,用于引用存放 3D 场景的 DOM 元素const containerRef = useRef(null);useEffect(() => {// 创建一个 three.js 的场景对象,所有的 3D 元素都会添加到这个场景中const scene = new THREE.Scene();// 创建一个透视相机,设置视角、宽高比、近裁剪面和远裁剪面,模拟人眼的视角const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);// 创建一个 WebGL 渲染器,负责将 3D 场景渲染成 2D 图像显示在网页上const renderer = new THREE.WebGLRenderer();// 设置渲染器的大小为窗口的宽度和高度renderer.setSize(window.innerWidth, window.innerHeight);// 将渲染器的 DOM 元素添加到之前创建的 ref 对应的 DOM 元素中,这样就能在网页上显示场景了containerRef.current.appendChild(renderer.domElement);// 创建一个 GLTF 加载器实例const loader = new GLTFLoader();// 使用加载器加载指定路径的 GLTF 模型文件loader.load('path/to/your/model.gltf', (gltf) => {// 获取加载好的模型的场景对象const model = gltf.scene;// 将模型添加到之前创建的场景中scene.add(model);});// 设置相机的位置,让相机离场景有一定距离,能看到场景中的物体camera.position.z = 5;// 定义一个动画函数,用于不断更新和渲染场景const animate = () => {// 请求浏览器在下一次重绘之前调用 animate 函数,实现动画循环requestAnimationFrame(animate);// 使用渲染器渲染场景和相机,将 3D 场景转换成 2D 图像显示在网页上renderer.render(scene, camera);};// 调用动画函数,开始动画循环animate();// 组件卸载时的清理函数,移除渲染器的 DOM 元素,避免内存泄漏return () => {containerRef.current.removeChild(renderer.domElement);};}, []);return (// 创建一个 div 元素,用于存放 3D 场景,使用 ref 关联到之前创建的 ref 对象<div ref={containerRef} />);
};export default ThreeJSGLTFExample;
2. Babylon.js
- 简介:Babylon.js 是一个功能强大的 3D 游戏和场景开发引擎,它提供了丰富的工具和功能,能让开发者快速创建出高质量的 3D 应用,对 GLTF 格式的支持也很完善。
- 代码示例:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><!-- 引入 Babylon.js 的核心库 --><script src="https://cdn.babylonjs.com/babylon.js"></script><!-- 引入 Babylon.js 的加载器扩展库,用于加载 GLTF 模型 --><script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script><title>Babylon.js GLTF Example</title>
</head><body><!-- 创建一个 canvas 元素,用于显示 3D 场景 --><canvas id="renderCanvas"></canvas><script>// 获取 canvas 元素const canvas = document.getElementById('renderCanvas');// 创建一个 Babylon.js 的引擎实例,负责管理渲染和更新逻辑const engine = new BABYLON.Engine(canvas, true);// 创建一个函数,用于创建 3D 场景const createScene = function () {// 创建一个新的场景对象const scene = new BABYLON.Scene(engine);// 创建一个自由相机,允许用户在场景中自由移动视角const camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5, -10), scene);// 设置相机看向场景的原点camera.setTarget(BABYLON.Vector3.Zero());// 让相机控制 canvas 的输入,比如鼠标和键盘操作camera.attachControl(canvas, true);// 创建一个半球光,照亮场景const light = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0, 1, 0), scene);// 设置光的强度light.intensity = 0.7;// 使用场景的加载器加载指定路径的 GLTF 模型文件BABYLON.SceneLoader.ImportMesh("", "path/to/your/", "model.gltf", scene, function (newMeshes) {// 当模型加载完成后,将第一个网格对象移动到指定位置newMeshes[0].position = new BABYLON.Vector3(0, 0, 0);});return scene;};// 调用创建场景的函数,得到场景对象const scene = createScene();// 监听引擎的渲染循环事件,不断更新和渲染场景engine.runRenderLoop(function () {scene.render();});// 监听窗口大小变化事件,当窗口大小改变时,调整渲染器的大小window.addEventListener('resize', function () {engine.resize();});</script>
</body></html>
3. PlayCanvas
- 简介:PlayCanvas 是一个基于 WebGL 的开源游戏开发平台,它提供了直观的可视化编辑器和强大的 JavaScript API,对 GLTF 格式的模型加载和处理也很方便。
- 代码示例:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><!-- 引入 PlayCanvas 的引擎库 --><script src="https://code.playcanvas.com/playcanvas-stable.min.js"></script><title>PlayCanvas GLTF Example</title>
</head><body><!-- 创建一个 canvas 元素,用于显示 3D 场景 --><canvas id="application-canvas"></canvas><script>// 获取 canvas 元素const canvas = document.getElementById('application-canvas');// 创建一个 PlayCanvas 的应用实例,传入 canvas 元素和配置对象const app = new pc.Application(canvas, {mouse: new pc.Mouse(canvas),touch: 'ontouchstart' in window? new pc.TouchDevice(canvas) : null});// 设置应用的分辨率为自动适应窗口大小app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);app.setCanvasResolution(pc.RESOLUTION_AUTO);// 启动应用app.start();// 创建一个实体作为相机,设置其位置和旋转const camera = new pc.Entity('camera');camera.addComponent('camera', {clearColor: new pc.Color(0.1, 0.1, 0.1)});camera.setPosition(0, 0, 5);app.root.addChild(camera);// 创建一个实体作为光照,设置其类型和颜色const light = new pc.Entity('light');light.addComponent('light', {type: 'directional',color: new pc.Color(1, 1, 1),intensity: 1});light.setEulerAngles(45, 30, 0);app.root.addChild(light);// 创建一个资源加载器,用于加载 GLTF 模型const loader = new pc.AssetLoader();// 定义一个资源对象,指定资源的类型为 GLTF 模型const modelAsset = new pc.Asset('model', 'container', {url: 'path/to/your/model.gltf'});// 将资源添加到加载器中loader.add(modelAsset);// 加载资源loader.load(function (err, assets) {if (err) {console.error('加载模型出错:', err);return;}// 获取加载好的模型资源const model = modelAsset.resource.instantiateRenderEntity();// 将模型添加到场景的根实体中app.root.addChild(model);});</script>
</body></html>
这些库都能帮助你轻松处理 GLTF 格式的模型,你可以根据自己的项目需求选择合适的库。
GLTF格式和FBX格式有什么区别?
GLTF 格式和 FBX 格式的区别
1. 整体用途和定位
- GLTF 格式:这是一种专门为网络传输设计的 3D 格式。就好比是为了在互联网上快速“快递”3D 模型而定制的包装。它的主要目标是让 3D 模型能在网页、游戏、虚拟现实(VR)和增强现实(AR)等场景里高效地加载和显示。
- FBX 格式:它是一种通用的 3D 交换格式,就像一个大仓库,能把各种 3D 软件里创建的模型、动画、材质等信息都存起来,方便在不同的 3D 软件之间传递和使用。比如说,你在 Maya 里做了个模型,想拿到 3ds Max 里接着做,就可以用 FBX 格式来传输。
2. 文件结构和大小
- GLTF 格式:它的文件结构比较简单,就像一个精简版的行李包。它把 3D 模型的信息分成几个部分,用 JSON 文件来描述模型的结构、材质、动画等,而模型的几何数据和纹理等可以单独存成二进制文件。这样一来,文件大小就比较小,在网络上传输起来就快多了。
- FBX 格式:FBX 文件就像一个装满东西的大箱子,它把所有的信息都打包在一起,包括模型的几何形状、骨骼动画、材质纹理、光照信息等等。虽然信息很全面,但文件往往比较大,传输起来就没那么快。
3. 兼容性
- GLTF 格式:在网络和现代 3D 引擎里的兼容性很好。很多流行的 3D 引擎,像 Three.js、Unity、Unreal Engine 等都对它有很好的支持。而且很多网页浏览器也能直接加载和显示 GLTF 模型,非常适合做网页 3D 展示。
- FBX 格式:在专业的 3D 建模和动画软件里兼容性很强。像 Maya、3ds Max、Blender 等软件都能很好地导入和导出 FBX 文件。但在网页端的支持就相对没那么好,需要额外的处理才能在网页上显示。
4. 数据存储方式
- GLTF 格式:它采用了一种分层的存储方式,就像把不同的东西放在不同的抽屉里。JSON 文件负责记录模型的整体结构和配置信息,而二进制文件专门存放模型的顶点数据、索引数据等。纹理文件也可以单独存储,这样可以根据需要灵活加载。
- FBX 格式:是一种二进制的整体存储方式,就像把所有东西都混在一个大袋子里。虽然这样能保证数据的完整性,但在修改和提取特定数据时就比较麻烦。
5. 代码示例(使用 Three.js 加载 GLTF 和 FBX 模型)
// 引入 React 的 useEffect 和 useRef 钩子
import React, { useEffect, useRef } from'react';
// 引入 three.js 用于创建 3D 场景
import * as THREE from 'three';
// 引入 GLTFLoader 用于加载 GLTF 格式的 3D 模型
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
// 引入 FBXLoader 用于加载 FBX 格式的 3D 模型
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';const ModelLoadingComponent = () => {// 创建一个 ref 用于引用存放 3D 场景的 DOM 元素const containerRef = useRef(null);useEffect(() => {// 创建 three.js 的场景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 元素添加到 ref 对应的 DOM 元素中containerRef.current.appendChild(renderer.domElement);// 创建一个环境光,让场景整体更亮const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);scene.add(ambientLight);// 创建一个点光源,让物体有明暗对比const pointLight = new THREE.PointLight(0xffffff, 1);pointLight.position.set(2, 5, 2);scene.add(pointLight);// 设置相机位置camera.position.z = 5;// 加载 GLTF 格式的模型const gltfLoader = new GLTFLoader();gltfLoader.load('path/to/your/model.gltf', (gltf) => {// 获取加载的模型const model = gltf.scene;// 将模型添加到场景中scene.add(model);});// 加载 FBX 格式的模型const fbxLoader = new FBXLoader();fbxLoader.load('path/to/your/model.fbx', (fbx) => {// 将加载的 FBX 模型添加到场景中scene.add(fbx);});// 定义渲染函数const animate = () => {// 请求下一帧动画requestAnimationFrame(animate);// 渲染场景renderer.render(scene, camera);};// 开始动画循环animate();// 组件卸载时清理资源return () => {containerRef.current.removeChild(renderer.domElement);};}, []);return (// 创建一个 div 用于存放 3D 场景<div ref={containerRef} />);
};export default ModelLoadingComponent;
在这个代码示例里,我们用 Three.js 分别加载了 GLTF 和 FBX 格式的 3D 模型。通过对比加载过程和效果,能更直观地感受到这两种格式的特点。
相关文章:

大白话react第十八章React 与 WebGL 项目的高级拓展与优化
大白话react第十八章React 与 WebGL 项目的高级拓展与优化 1. 实现 3D 模型的导入与动画 在之前的基础上,我们可以导入更复杂的 3D 模型,并且让这些模型动起来,就像在游戏里看到的角色和场景一样。这里我们使用 GLTF 格式的模型,…...

JavaScript系列06-深入理解 JavaScript 事件系统:从原生事件到 React 合成事件
JavaScript 事件系统是构建交互式 Web 应用的核心。本文从原生 DOM 事件到 React 的合成事件,内容涵盖: JavaScript 事件基础:事件类型、事件注册、事件对象事件传播机制:捕获、目标和冒泡阶段高级事件技术:事件委托、…...

C++:string容器(下篇)
1.string浅拷贝的问题 // 为了和标准库区分,此处使用String class String { public :/*String():_str(new char[1]){*_str \0;}*///String(const char* str "\0") // 错误示范//String(const char* str nullptr) // 错误示范String(const char* str …...

2.数据结构-栈和队列
数据结构-栈和队列 2.1栈2.1.1栈的表示和实现2.1.2栈的应用举例数制转换括号匹配检验迷宫给求解表达式求值 2.1.3链栈的表示和实现2.1.4栈与递归的实现遍历输出链表中各个结点的递归算法*Hanoi塔问题的递归算法 2.2队列2.2.1循环队列——队列的顺序表示和实现2.2.2链队——队列…...

aws(学习笔记第三十一课) aws cdk深入学习(batch-arm64-instance-type)
aws(学习笔记第三十一课) aws cdk深入学习 学习内容: 深入练习aws cdk下部署batch-arm64-instance-type 1. 深入练习aws cdk下部署batch-arm64-instance-type 代码链接 代码链接 代码链接 -> batch-arm64-instance-type之前代码学习 之前学习代码链接 -> aw…...

MySQL 中,SELECT ... FOR UPDATE
在 MySQL 中,SELECT ... FOR UPDATE 语句会对查询结果集中的行加排他锁(X 锁)。关于其他事务是否能读取当前行,以下是详细说明: 1. 排他锁(X 锁)的特性 排他锁是一种独占锁,加锁后&…...

云服务运维智能时代:阿里云操作系统控制台
阿里云操作系统控制台 引言需求介绍操作系统使用实例获得的帮助与提升建议 引言 阿里云操作系统控制台是一款创新型云服务器运维工具,专为简化用户的运维工作而设计。它采用智能化和可视化的方式,让运维变得更加高效、直观。借助AI技术,控制…...

【Agent的革命之路——LangGraph】如何使用config
有时我们希望在调用代理时能够对其进行配置。这包括配置使用哪个语言模型(LLM)等例子。下面我们将通过一个示例来详细介绍如何进行这样的配置。 在介绍 configurable 之前我们先介绍一下 Langchain 的 RunnableConfig。RunnableConfig是一个配置对象&…...

ArcGIS操作:15 计算点的经纬度,并添加到属性表
注意:需要转化为地理坐标系 1、打开属性表,添加字段 2、计算字段(以计算纬度为例 !Shape!.centroid.Y ) 3、效果...

Docker基础入门
第 1 章:核心概念与安装配置 本章首先介绍Docker 的三大核心概念: 镜像 (Image)容器(Container)仓库(Repository) 只有理解了这三个核心概念,才能顺利地理解Docker容器的整个生命周期。 随后࿰…...

【Linux】详谈 基础I/O
目录 一、理解文件 狭义的理解: 广义理解: 文件操作的归类认知 系统角度 二、系统文件I/O 2.1 标志位的传递 系统级接口open 编辑 open返回值 写入文件 读文件 三、文件描述符 3.1(0 & 1 & 2) 3.2 文件描…...

爬虫案例七Python协程爬取视频
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Python协程爬取视频 前言 提示:这里可以添加本文要记录的大概内容: 爬虫案例七协程爬取视频 提示:以下是本篇文章正文…...

[20250304] 关于 RISC-V芯片 的介绍
[20250304] 关于 RISC-V芯片 的介绍 1. 调研报告 一、RISC-V 芯片结构分析 RISC-V 芯片基于开源指令集架构(ISA),其核心优势在于模块化设计与高度灵活性。 指令集架构 基础指令集:包含 RV32I(32 位)、R…...

一学就会:A*算法详细介绍(Python)
📢本篇文章是博主人工智能学习以及算法研究时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在&am…...

Hadoop、Hive、Spark的关系
Part1:Hadoop、Hive、Spark关系概览 1、MapReduce on Hadoop 和spark都是数据计算框架,一般认为spark的速度比MR快2-3倍。 2、mapreduce是数据计算的过程,map将一个任务分成多个小任务,reduce的部分将结果汇总之后返回。 3、HIv…...

Excel·VBA江西省预算一体化工资表一键处理
每月制作工资表导出为Excel后都需要调整格式,删除0数据的列、对工资表项目进行排序、打印设置等等,有些单位还分有“行政”、“事业”2个工资表就需要操作2次。显然,这种重复操作的问题,可以使用VBA代码解决 目录 代码使用说明1&a…...

23种设计模式简介
一、创建型(5种) 1.工厂方法 总店定义制作流程,分店各自实现特色披萨(北京店-烤鸭披萨,上海店-蟹粉披萨) 2.抽象工厂 套餐工厂(家庭装含大披萨薯条,情侣装含双拼披萨红酒&#…...

python fire 库与 sys.argv 处理命令行参数
fire库 Python Fire 由Google开发,它使得命令行接口(CLI)的创建变得容易。使用Python Fire,可以将Python对象(如类、函数或字典)转换为可以从终端运行的命令行工具。这能够以一种简单而直观的方式与你的Py…...

PDF处理控件Aspose.PDF,如何实现企业级PDF处理
PDF处理为何成为开发者的“隐形雷区”? “手动调整200页PDF目录耗时3天,扫描件文字识别错误导致数据混乱,跨平台渲染格式崩坏引发客户投诉……” 作为开发者,你是否也在为PDF处理的复杂细节消耗大量精力?Aspose.PDF凭…...

Spring(1)——mvc概念,部分常用注解
1、什么是Spring Web MVC? Spring MVC 是一种基于 Java 的实现了 MVC(Model-View-Controller,模型 - 视图 - 控制器)设计模式的 Web 应用框架,它是 Spring 框架的一个重要组成部分,用于构建 Web 应用程序。…...

C语言(23)
字符串函数 11.strstr函数 1.1函数介绍: 头文件:string.h char *strstr ( const char * str1,const char *str2); 作用:在一个字符串(str1)中寻找另外一个字符串(str2)是否出现过 如果找到…...

Immich自托管服务的本地化部署与随时随地安全便捷在线访问数据
文章目录 前言1.关于Immich2.安装Docker3.本地部署Immich4.Immich体验5.安装cpolar内网穿透6.创建远程链接公网地址7.使用固定公网地址远程访问 前言 小伙伴们,你们好呀!今天要给大家揭秘一个超炫的技能——如何把自家电脑变成私人云相册,并…...

基于SpringBoot的在线付费问答系统设计与实现(源码+SQL脚本+LW+部署讲解等)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...

【Linux】信号处理以及补充知识
目录 一、信号被处理的时机: 1、理解: 2、内核态与用户态: 1、概念: 2、重谈地址空间: 3、处理时机: 补充知识: 1、sigaction: 2、函数重入: 3、volatile&…...

pandas——to_datatime用法
Pandas中pd.to_datetime的用法及示例 pd.to_datetime 是 Pandas 库中用于将字符串、整数或列表转换为日期时间(datetime)对象的核心函数。它在处理时间序列数据时至关重要,能够灵活解析多种日期格式并统一为标准时间类型。以下是其核心用法及…...

《DataWorks 深度洞察:量子机器学习重塑深度学习架构,决胜复杂数据战场》
在数字化浪潮汹涌澎湃的当下,大数据已然成为推动各行业发展的核心动力。身处这一时代洪流,企业对数据的处理与分析能力,直接关乎其竞争力的高低。阿里巴巴的DataWorks作为大数据领域的扛鼎之作,凭借强大的数据处理与分析能力&…...

Java 大视界 -- 基于 Java 的大数据实时数据处理框架性能评测与选型建议(121)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...

多线程-JUC
简介 juc,java.util.concurrent包的简称,java1.5时引入。juc中提供了一系列的工具,可以更好地支持高并发任务 juc中提供的工具 可重入锁 ReentrantLock 可重入锁:ReentrantLock,可重入是指当一个线程获取到锁之后&…...

DeepSeek:中国AGI先锋,用技术重塑通用人工智能的未来
在ChatGPT掀起全球大模型热潮的背景下,中国AI领域涌现出一批极具创新力的技术公司,深度求索(DeepSeek)便是其中的典型代表。这家以“探索未知、拓展智能边界”为使命的AI企业,凭借长文本理解、逻辑推理与多模态技术的…...

Vue 框架深度解析:源码分析与实现原理详解
文章目录 一、Vue 核心架构设计1.1 整体架构流程图1.2 模块职责划分 二、响应式系统源码解析2.1 核心类关系图2.2 核心源码分析2.2.1 数据劫持实现2.2.2 依赖收集过程 三、虚拟DOM与Diff算法实现3.1 Diff算法流程图3.2 核心Diff源码 四、模板编译全流程剖析4.1 编译流程图4.2 编…...