【three.js / React-three-fiber】加载3D模型性能优化

这篇具有很好参考价值的文章主要介绍了【three.js / React-three-fiber】加载3D模型性能优化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、 引入

无论是大型虚拟世界还是简单的网站,性能优化都是必要的。

特别是在运用三维模型的情况下,我们需要更加深入的优化。因为三维模型通常包含大量的数据和复杂的几何形状,如果不进行性能优化,浏览器可能会因为负载过重而崩溃。

在本文中,我们将探讨如何在three.js / React-three-fiber中对加载三维模型进行性能优化。我们将介绍一些实践方法和技巧,让你的虚拟世界或网站能够以更好的性能运行。

二、 性能监测工具简介:stats.js \ r3f-perf \spector.js

① 写原生three.js可用stats.js

Stats.js是一个轻量级的性能监测库,可以用于监测WebGL或者其他HTML5应用的帧速率、内存使用情况等性能指标。它可以在浏览器中展示FPS(每秒帧数)、渲染时间、内存占用等性能指标,便于开发者实时监测应用程序的性能状况并进行优化。

react-three-fiber primitive,javascript,react.js,3d

代码示🌰:

var stats = new Stats();
stats.showPanel(1); // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild(stats.dom);

function animate() {
  stats.begin();

  // monitored code goes here

  stats.end();

  requestAnimationFrame(animate);
}

requestAnimationFrame(animate);
② 在react-three/fiber可用r3f-perf

r3f-perf是一个React Three Fiber(R3F)的性能分析工具,它可以帮助开发者识别和解决在使用R3F构建WebGL应用程序时可能遇到的性能问题。它提供了实时的性能指标,例如帧率、GPU和CPU使用率、内存使用量等

react-three-fiber primitive,javascript,react.js,3d

代码示🌰:

import { Canvas } from "@react-three/fiber";
import { Perf } from "r3f-perf";

function App() {
  return (
    <Canvas>
      <Perf position="bottom-left" />
    </Canvas>
  );
}
③ 用spector.js深入分析

Spector.js可以捕获所有WebGL调用,并将其记录到一个文件中,以便开发人员可以分析和调试应用程序中的问题,不仅有依赖包,还有浏览器插件,数据详细,适用于性能深入分析。

react-three-fiber primitive,javascript,react.js,3d


三、解决方案

(1) 使用 gltf-pipeline 压缩文件

react-three-fiber primitive,javascript,react.js,3d

1. 简单介绍gltf-pipeline

gltf-pipeline 是一个用于转换、优化和验证 GLTF 文件的命令行工具。它可以

  • 校验 GLTF 文件的结构、语法和语义是否正确;
  • 优化 GLTF 文件的大小和加载性能
  • 转换 GLTF 文件到其他格式,如 glb、FBX、OBJ、Collada、Three.js JSON 等。

2. 代码示例

压缩glb文件命令行

  gltf-pipeline -i male.glb -o male-processed.glb -d
① 使用原生 three.js 时,需要用 DRACOLoader 解码
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";

const loader = new GLTFLoader();

// 创建解码器实例
const dracoLoader = new DRACOLoader();
// 设置解压库文件路径
dracoLoader.setDecoderPath(DECODER_PATH);
// 加载解码器实例
loader.setDRACOLoader(dracoLoader);

loader.load(MODEL_FILE_PATH, (gltf) => {
  let model = gltf.scene;
  // ....
});
② 使用 react-three/fiber 时,直接使用 useGLTF 加载即可
  • primitive 只可加载一个模型
import { Clone } from "@react-three/drei";

function Model() {
  const { scene } = useGLTF(MODEL_FILE_PATH);
  return <primitive object={scene} />;
}
  • Clone 可批量加载多个模型
import { Clone, useGLTF } from "@react-three/drei";
function Model() {
  const { nodes } = useGLTF(MODEL_FILE_PATH);
  return <Clone object={nodes.foo} />;
}

3. 优缺点

优点:
  • 压缩后的文件大小更小,加载速度更快
  • 可以优化模型的渲染性能,减少 GPU 的工作负担,提高帧率和动画流畅度
  • 可以自动优化模型的材质和纹理,使其更加符合 GPU 的渲染特性,提高渲染效率
缺点:
  • 压缩过程可能会损失一些模型细节和质量,导致模型不够精细;
  • 压缩后的文件需要解压缩才能使用,增加了一些额外的步骤和时间

4. 适用场景

① 在移动端等网络环境较差的情况下,压缩模型可以减少加载时间和流量消耗;
② 当模型文件较大,需要优化渲染性能时,可以使用压缩工具进行优化;
③ 在需要快速加载和渲染大量模型的场景中,压缩文件可以提高整体性能。


(2) 使用 instanceMesh 减少 draw call

react-three-fiber primitive,javascript,react.js,3d

1. instanceMesh 定义

InstancedMesh 是 Mesh 的一个特殊版本,支持实例化渲染。如果您需要渲染大量具有相同几何和材质但具有不同世界变换的对象,请使用 InstancedMesh。使用 InstancedMesh 将帮助你减少绘制调用的数量(draw calls),从而提高应用程序的整体渲染性能。

2. instanceMesh 原理

InstancedMesh 是一种优化技术,它允许在场景中创建多个具有相同形状和材质的对象,同时只使用一次网格数据。它的原理是通过使用单个网格实例来渲染多个实例,而不是为每个实例创建单独的网格。

在实现上,InstancedMesh 的原理是使用 instancing 技术,通过将变量和矩阵传递到着色器中,来控制每个实例的位置、旋转和缩放等属性。

3.代码示例

① 使用原生 three.js

性能测试例子、性能测试代码

react-three-fiber primitive,javascript,react.js,3d

不使用instanceMesh
drawcalls为1000

核心代码如下:

	const count = 1000;
        const matrix = new THREE.Matrix4();

	for ( let i = 0; i < count; i ++ ) {
	     randomizeMatrix( matrix );
	     const mesh = new THREE.Mesh( geometry, material );
	     mesh.applyMatrix4( matrix );

	     scene.add( mesh );

	}

react-three-fiber primitive,javascript,react.js,3d

使用instanceMesh
drawcalls为1

核心代码如下:

const count = 1000;
const matrix = new THREE.Matrix4();
const mesh = new THREE.InstancedMesh(geometry, material, count);

for (let i = 0; i < count; i++) {
  randomizeMatrix(matrix);
  mesh.setMatrixAt(i, matrix);
}

scene.add(mesh);
② 使用 react-three/fiber

实现 instanced 的例子

将 glb/gltf 文件自动转为 gltfjsx 的工具:gltfjsx

(拖拽文件生成 https://gltf.pmnd.rs/ ,但是自动生成的可能不对,需要自己调整一下)

react-three-fiber primitive,javascript,react.js,3d

再举个🌰

// 定义InstancesProvider
import React, { useMemo, useContext, createContext } from 'react'
import { useGLTF, Merged, } from '@react-three/drei'

const context = createContext()
export function InstancesProvider({ children, ...props }) {
  const { nodes } = useGLTF(MODEL_FILE_PATH)
  const instances = useMemo(() => ({ Screw1: nodes['Screw1'], Screw2: nodes['Screw2'] }), [nodes])
  return (
    <Merged meshes={instances} {...props}>
      {(instances) => <context.Provider value={instances} children={children} />}
    </Merged>
  )
}

// 定义Model
export function Model(props) {
  const instances = useContext(context)
  return (
    <group {...props} dispose={null}>
      <instances.Screw1 position={[-0.42, 0.04, -0.08]} rotation={[-Math.PI / 2, 0, 0]} />
      <instances.Screw2 position={[-0.42, 0.04, -0.08]} rotation={[-Math.PI / 2, 0, 0]} />
    </group>
  )
}

// 使用Model
import { InstancesProvider, Model } from './Model'

<InstancesProvider>
  <Model position={[10,0,0]}>
  <Model position={[-10,0,0]}>
  <Model position={[-10,10,0]}>
</InstancesProvider>

4. 优缺点

优点:
  • 减少了渲染调用的数量,提高了渲染效率
  • 能够轻松地复制多个相同的模型,节省了内存空间
  • 可以通过修改实例矩阵来实现动态变换,比如实现粒子效果。
缺点:
  • 不能直接修改实例的顶点属性,只能通过修改实例矩阵来实现动态变换;
  • 需要对实例矩阵进行矩阵计算,可能会影响性能

5.适用场景及不适用场景

① 适用场景

(在这些场景下,使用 InstancedMesh 可以减少 GPU 的工作量,从而提高渲染性能):

大量相似的物体需要被渲染,例如草、树、石头等;
② 展示大规模的复杂场景,例如城市或者森林等;
③ 大量重复的元素需要被渲染,例如在复杂的建筑中的砖块、玻璃面板等;
④ 需要在不同的地方渲染同一个物体,例如在多个镜头之间切换的时候。

② 不适用场景

(在以下场景下使用 InstancedMesh 有可能会使性能变差):

① 当需要在每个实例之间进行大量不同的计算时,例如不同的动画或者物理模拟;
② 当需要在每个实例之间进行大量不同的着色器计算时,例如每个实例有不同的材质或者纹理;
③ 当需要经常更新实例的位置、旋转或者缩放时。


(3) 其他优化方案

  • 减少模型面数:可以通过优化 3D 模型来减少面数,从而提高性能。可以使用 Blender 等建模软件来进行优化,也可以使用 Three.js 自带的 SimplifyModifier 和 DecimationModifier 来进行简化。
  • 使用纹理贴图:纹理贴图可以减少几何体的面数,同时提高渲染效率。可以使用 UV 映射技术将纹理贴图应用到 3D 模型上。
  • 合并几何体:将多个几何体合并成一个可以减少渲染调用次数,从而提高性能。可以使用 Three.js 自带的 MergeGeometry 和 BufferGeometryUtils 工具类来实现。
  • 使用 LOD(Level of Detail):使用 LOD 技术可以根据距离远近来切换不同的模型细节级别,从而提高性能。
  • 使用 GLTFpack 实现快速压缩和优化 GLTF 文件,提高加载速度。

四、总结

本文先简单介绍了三种性能监测工具:stats.js \ r3f-perf \spector.js,再针对运用原生three.jsreact-three/fiber加载三维模型提供了多种优化性能的方案,其中,主要探讨了使用 gltf-pipeline 压缩文件和
使用 instanceMesh 减少 draw call的原理、实践方法、优缺点及使用场景。

在实践中,注意要根据项目特性选择适合的优化方案,多进行性能对比再使用~文章来源地址https://www.toymoban.com/news/detail-787340.html

(由于本人刚入three.js的坑,对于3D技术实践较少,如有错误,请告知,谢谢啦~)

五、参考与感谢

  1. 3D 性能优化 | 说一说 glTF 文件压缩
  2. three 中使用 GLTF/GLB 模型性能优化
  3. The Big List of three.js Tips and Tricks!
  4. Draco Compressed Meshes with glTF and 3D Tiles

到了这里,关于【three.js / React-three-fiber】加载3D模型性能优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • React Three Fiber动画

    使用静态对象和形状构建 3D 场景非常酷,但是当你可以使用动画使场景栩栩如生时,它会更酷。 在 3D 世界中,有一个称为角色装配的过程,它允许你创建称为骨架的特殊对象,其作用类似于骨骼和关节系统。 这些骨架连接到一块 3D 几何体上,例如人、动物或其他任何物体

    2024年02月02日
    浏览(35)
  • 使用 React Three Fiber 和 GSAP 实现 WebGL 轮播动画

    参考:Building a WebGL Carousel with React Three Fiber and GSAP 在线 demo github 源码 效果来源于由 Eum Ray 创建的网站 alcre.co.kr,具有迷人的视觉效果和交互性,具有可拖动或滚动的轮播,具有有趣的图像展示效果。 本文将使用 WebGL、React Three Fiber 和 GSAP 实现类似的效果。通过本文,可以了

    2024年02月05日
    浏览(43)
  • Three.js 模型加载及加载简单动画

    时间过的好快啊~再一次感叹,忙忙碌碌一年又过去了,新年第一帖,新的一年也要加油呀! 简单介绍下Three.js吧,Three.js是基于原生WebGL封装运行的三维引擎,在所有WebGL引擎中,Three.js是国内文资料最多、使用最广泛的三维引擎。因为使用简单,入门比较容易。 Three.js的具体

    2024年02月12日
    浏览(40)
  • Three.js之加载外部三维模型

    建模软件绘制3D场景 … 加载.gltf文件(模型加载全流程) 注:基于Three.js v0.155.0 三维建模软件 gltf格式 加载.gltf文件 OrbitControls辅助设置相机参数:相机位置、相机目标对象 gltf不同文件形式(.glb) 模型命名(程序与美术协作): .getObjectByName() 递归遍历层级模型修改材质: .traverse

    2024年02月05日
    浏览(33)
  • three.js添加3d模型

    three官方的几何体也就那么几个,想要生成各种各样的模型,其难度十分之大,这时引入外部模型也不失为一种选择。具体引入办法如下。 虽然名字为GLTFLoader,但实际上glb文件也是能加载的。 其中需要注意的是调节相机参数与相机位置,否则很有可能导致场景中看不见任何东

    2024年02月04日
    浏览(65)
  • Three.js加载FBX模型并解析骨骼动画

    通过Threejs先加载一个.FBX格式的三维模型文件,然后解析该文件中的骨骼动画信息。  FBX 加载器 FBXLoader.js 加载fbx模型文件 加载模型文件,加载完成后,如果模型显示位置不符合要求,可以通过Threejs程序进行平移、缩放等操作。 查看FBX模型帧动画数据 stl、obj都是静态模型,

    2024年02月07日
    浏览(58)
  • Three.js--》实现3d地球模型展示

    目录 项目搭建 实现网页简单布局 初始化three.js基础代码 创建环境背景 加载地球模型 实现光柱效果 添加月球模型 今天简单实现一个three.js的小Demo,加强自己对three知识的掌握与学习,只有在项目中才能灵活将所学知识运用起来,话不多说直接开始。 项目搭建 本案例还是借

    2024年02月08日
    浏览(47)
  • Three.js--》实现3d字体模型展示

    目录 项目搭建 初始化three.js基础代码 设置环境纹理 加载字体模型 今天简单实现一个three.js的小Demo,加强自己对three知识的掌握与学习,只有在项目中才能灵活将所学知识运用起来,话不多说直接开始。 项目搭建 本案例还是借助框架书写three项目,借用vite构建工具搭建vue项

    2024年02月07日
    浏览(50)
  • Three.js--》实现3d小岛模型搭建

    目录 项目搭建 初始化three.js基础代码 设置环境背景 设置水面样式 添加天空小岛 今天简单实现一个three.js的小Demo,加强自己对three知识的掌握与学习,只有在项目中才能灵活将所学知识运用起来,话不多说直接开始。 项目搭建 本案例还是借助框架书写three项目,借用vite构建

    2024年02月05日
    浏览(37)
  • Three.js--》实现3d踢球模型展示

    目录 项目搭建 初始化three.js基础代码 设置环境纹理加载模型 使用Cannon-es实现物理世界 今天简单实现一个three.js的小Demo,加强自己对three知识的掌握与学习,只有在项目中才能灵活将所学知识运用起来,话不多说直接开始。 项目搭建 本案例还是借助框架书写three项目,借用

    2024年02月11日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包