随着我在 Echobind 的投入时间以及我自己的空闲时间,我一直在慢慢学习 webGL 库,例如 three.js、Mozilla 的/Super Medium 的 A-Frame、Google 的模型查看器以及最近的 React-three- fiber(R3F)。

在第四季度的投资时间里,我与同事一起使用 R3F 创建了一个可滚动的 3D 网站。 在这个项目中,我想强调我为网络优化 3D 模型的过程。 从这个过程中,我能够将主要 3D 模型从 26MB 减少到 560KB。

three.js 等框架使 webGL编程变得更加容易。 此外,诸如 R3F 之类的库(它更多地抽象了 three.js)使在 web 上处理 3D 体验变得更加容易。

推荐:用 NSDT场景设计器 快速搭建3D场景。

1、加载时间问题

我们在处理此场景时面临的挑战之一是如何最大限度地减少客户端的加载时间。 我们的第一个方法是创建一个加载屏幕。 但是,由于我们的 3D 模型文件太大 (26MB),加载时间太长。 当它最终加载时,交互动画缓慢且断断续续。 为了纠正这些问题,我想找到一种方法来最小化文件大小。

2、我的解决方案

大文件的主要原因是我们的 3D 模型及其相关纹理的复杂性。 因此,我负责探索如何通过优化我们的 3D 模型来最大限度地减少加载时间。 我还发现场景中的材质和网格太多了。 通过最小化这两个组件,可以减小导出模型的文件大小。 以下是我采取的步骤:

3、精简、合并网格

第一步要做的,就是优化网格、删除多边形,然后重新组合对象

首先优化网格:

因为我们担心这个场景在网络上运行不佳,所以我想删除 blender 项目中网格上任何可能不必要的多边形。 这是使用精简修改器(Decimate Modifier)完成的。 我通常从将网格比率降低到 0.5 开始,如果它不会导致任何不需要的伪影,则再降低。 对大多数网格重复此步骤。

接下来删除多边形:

为了帮助展开并移除任何不会出现在最终视图中的东西,我移除了所有网格底部的所有多边形,例如雪网格的底部。 这是通过使用选择套索进入编辑模式>面选择来完成的。 对大多数网格重复此步骤。

为了开始组合网格,我需要确定哪些网格适合组合。 最后,我将场景中位于地面和地板网格上的雪顶上的所有对象组合在一起——减去帧。 我决定这样做是因为它们都适合相同的 UV 空间,并且希望它们都具有相同尺寸的材料。 雪占据了相当大的空间,将其添加到相同的 UV 空间会减小所有对象的比例; 这也会降低对象的纹理质量。 从那里开始,我想结合与帧相关的所有网格——减去玻璃和照片——因为我希望能够为照片图像添加尽可能多的质量。 玻璃需要自己的材料来防止场景中不需要透明度的其他部分出现任何透明度问题。 我根据它们的内容适当地重命名了网格:物体、框架、玻璃、照片、地板、雪以及它们的相关材料。

这导致场景从 65 个单独的网格减少到 6 个相关网格的对象。 组合网格实际上增加了 Blender 文件的大小,但帮助我删除了场景中任何潜在的重复项并快速选择了场景中的大量多边形,以便在接下来的步骤中更容易地操纵它们。

4、UV 压缩

在我能够展开 UV 并将其打包在一起之前,我需要将每个网格的所有多边形关联到一种材质中。 在这一点上,项目中有很多材料。 因此,首先需要做的是移除所有未使用的孤立材料。 通过删除所有孤立材质,我将场景中的材质从 71 种减少到 6 种。

这是展开对象的结果:

这是展开帧的结果:

所有剩余的网格也被展开。

5、材质ID

如果你已确定该部分有特定材质,材质 ID 使你能够快速选择网格的一部分。 我们可以利用材质 ID 并将这些选择的网格转换为可在步骤 5 中使用的单个纹理,而不是将多个材质添加到一个网格中,这会增加模型的文件大小。

为此,我创建了各种具有高对比度颜色的材质。 在对象网格和帧网格的所有多边形都添加了各种颜色材料后,我将颜色烘焙出来,以便将它们添加到网格的 UV 坐标中。

6、烘焙材质 ID

为此,烘焙过程是从我刚刚添加的各种彩色材料中获取所有颜色信息,并将这些颜色投射到纹理上。

这是烘焙后的材质 ID 贴图,如上所示。 在 Blender 中烘焙材料之前需要注意的一些事项:

  • 将渲染模式更改为cycles
  • 关闭所有直射和间接照明
  • 确保已在着色器视口中选择漫反射贴图
  • 选择添加了颜色的重复网格
  • 将具有展开 UV 的网格作为你的活动选择
  • 确保烘焙类型为漫反射
  • 点击烘烤按钮


Blender 的最后一步是将所有内容导出为 .fbx 以及导出所有材质 ID 纹理。

7、在 Substance Painter 中创建材质

Substance Painter 是我最喜欢的 3D 工具之一。 它可以使纹理化过程变得如此有趣和符合情境。 它基本上是 3D 模型的 photoshop。

在导入 .fbx 时,我还导入了对象网格和帧网格的材质 ID 纹理。

烘焙网格贴图(法线、世界空间法线、环境遮挡、曲线等)后,我为对象网格和相框网格的每种颜色创建了文件夹,并使用遮罩选择每个材质 ID 以归因于遮罩。 这就是我们如何能够向网格的一部分添加不同的颜色和纹理。

由于我们想要的预期结果不太现实,我决定只导出 baseColor 和环境遮挡,但由于我想将环境遮挡的阴影/照明添加到 baseColor,我需要将两者组合成一个纹理 . 为此,我需要在导出纹理视口中添加一个新预设。

8、在 Blender 中添加 baseColor

这一步真的很快。 我只需要添加来自 Substance Painter 的烘焙纹理结果并将它们添加到每个材质的 baseColor。 之后,我将所有内容导出为 .glb。 此时,导出的文件大小为 5.1MB。

9、glTF 压缩

既然模型已纹理化并从 Blender 导出,我将模型上传到 gltf.report 以进一步压缩 .glb。

将模型上传到 gltf.report 后,我单击脚本选项卡。 从那里我将纹理大小从 1024 x 1024 减小到 128 x 128,然后单击运行然后导出。

结果文件从 5.1MB 降到了 3MB。 然后将生成的简化网格添加到 /public/meshes/ 下的项目中。

在运行下一步之前,重要的是安装 nvm 并安装较早版本的节点。 否则,可能会在运行 gltfjsx 时遇到错误。

NVM ls
NVM use 14.20.0

在运行命令行工具之前,我需要将目录从项目文件夹更改为网格所在的位置。 否则结果将被添加到项目文件夹中。

cd /public/meshes/

现在,我可以运行 gltfjsx

npx gltfjsx main_scene.glb -T

运行 gltfjsx 的结果提供了一个较小的 .glb 文件以及 3D 模型的 react.js 组件。 结果将文件从 3MB 减少到 581KB。

如果你不想安装 gltfjsx 和更早的node版本,你也可以前往这里, 但结果可能会有所不同。

这是 560KB 的最终结果:

以下是来自 gltfjsx 的 main_scene.js 的结果:

/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
*/import * as THREE from 'three'
import React, { useRef } from 'react'
import { CycleRaycast, useGLTF } from '@react-three/drei'
import { GLTF } from 'three-stdlib'export function Main(props) {const { nodes, materials } = useGLTF('/meshes/main_scene.glb')return (<group {...props} dispose={null}><mesh geometry={nodes.floor.geometry} material={materials.floor} position={[-0.01, 0, -0.61]} /><mesh geometry={nodes.Snow.geometry} material={materials.Snow} position={[0, 0, -0.61]} /><mesh geometry={nodes.objects.geometry} material={materials.objects} position={[1.13, 0.28, 0.53]} rotation={[-Math.PI, -0.09, -Math.PI]} /><mesh // onClick={() => {console.log('frame clicked')}}geometry={nodes.frame.geometry} material={materials.frame} position={[-0.02, 1.27, -1.89]} rotation={[Math.PI, -0.02, Math.PI]} /><mesh onClick={() => props.setModalIsOpen(true)}geometry={nodes.photo.geometry} material={materials.photo} position={[-0.02, 1.24, -1.89]} rotation={[Math.PI, -0.02, Math.PI]} scale={0.09} >{/* testing out how to add cursor pointer based on mouse over the photo */}{/* docs here https://github.com/pmndrs/drei#cycleraycast */}{/* example use of useCursor https://codesandbox.io/s/ny3p4?file=/src/App.js:977-983 */}<CycleRaycastpreventDefault={true} // Call event.preventDefault() (default: true)scroll={true} // Wheel events (default: true)keyCode={9} // Keyboard events (default: 9 [Tab])onChanged={(objects, cycle) => console.log(objects)} // Optional onChanged eventonPointerOver={() => {console.log('hovered')}}/></mesh><mesh geometry={nodes.glass.geometry} material={materials.glass} position={[-0.02, 1.27, -1.89]} rotation={[0, 0.02, 0]} /></group>)
}useGLTF.preload('/meshes/main_scene.glb')

原文链接:WebGL 3D模型优化 — BimAnt

WebGL 3d模型优化实战相关推荐

  1. Polygon Cruncher(3D模型优化插件)v12.25版

    Polygon Cruncher是目前非常实用的一款3D模型优化插件,能够支持LightWave.3dsmax.maya三款软件的多个不同版本,可以在不影响3D模型外观的前提下,尽量减少模型的多边形数 ...

  2. Creator3D:3D模型优化-减面

    前言 3d游戏开发,3d模型是避免不了的,原生平台还好说,为了提高效果模型越清晰越好,但是对于小游戏,4M本地包是一个硬砍,而且大多和我一样的个人开发者模型基本上都是在网上下载的,一个模型就好几兆,那 ...

  3. WebGL 3D 电信机架实战之数据绑定

    前言 在前端中,视图层和数据层需要进行单向或者双向数据绑定,大家都已经不陌生了,有时候 2D 做的比较顺了之后,就会想要挑战一下 3D,不然总觉得痒痒的.这个 3D 机架的 Demo 我觉得非常有代表 ...

  4. Arm和Unity联合推出:适用于移动应用程序的3D美术优化-[2]几何体

    目录 1.几何体 - 简介 1.1.概述 1.2.什么是几何体? 1.3.总结 2.三角形和多边形的使用量 2.1.概述 2.2.在不同的硬件/屏幕大小上进行测试 2.3.重要区域的细节 2.4.避免 ...

  5. 视频教程-Three.js(webgl) webpack+es6 geojson 3d地图 项目实战视频教程-JavaScript

    Three.js(webgl) webpack+es6 geojson 3d地图 项目实战视频教程 2008年开始从事C#编程工作,2013年转向Unity游戏开发领域,在谷歌市场及苹果商店陆续 发布 ...

  6. Unity 3D模型展示之webGL平台展现

    在之前的项目基础上我们已经打包后在PC端进行展示了.这篇文章主要介绍在切换到webGL上时效果展示不出来需要进行调整,特此记录一下. 1.平台切换 选择WebGL平台切换,没有的可以进行安装,安装之后 ...

  7. PNAS | 开发用于优化蛋白质设计的3D模型

    研究人员开发了一个计算程序,以帮助设计治疗用蛋白质,预测相互作用. 研究人员已经开发出一种过程,他们说这种过程可以减少计算蛋白设计所涉及的工作.该技术使用三维(3D)结构模型来预测分子嵌段的新颖组合如 ...

  8. 分享一个WebGL开发的网站-用JavaScript + WebGL开发3D模型

    这张图每位程序员应该都深有感触. 人民心目中的程序员是这样的:坐在电脑面前噼里啪啦敲着键盘,运键如飞. 现实中程序员是这样的:编码5分钟,调试两小时. 今天我要给大家分享一个用WebGL开发的网站,感 ...

  9. three.js加载3d模型_基于WebGL的3D技术在网页中的运用 ThingJS 前端开发

    Three.js.ThingJS这些引擎库可以加载3D制作软件的模型,大幅度提高了制作效率,改变WebGL开发困难的局面,让Web开发者享受便捷的3D开发服务.三者的难度对比如下: ThingJS(框 ...

最新文章

  1. 往年包场丘赛的北大,今年被清华逆袭了
  2. 印象大使_基本服务-使用大使网关
  3. 科学计算机二进制算法,计算机是怎么理解二进制的?
  4. 世界人口钟实时数据_全球人口将达80亿 2019年世界人口总数统计数据
  5. 教师节快乐:删了库之后,不要着急跑路
  6. 大数据之-Hadoop源码编译_源码编译具体流程_以及编译步骤---大数据之hadoop工作笔记0046
  7. docker打包镜像(实用版)
  8. 关于Unity中OnGUI()的简单使用
  9. php5.6 win2008 mssql,Php5.6.31连接sqlserver 2008R2数据库问题sqlsrv(php5.3及以上版本)与mssql(php5.3以前版本)②...
  10. 微信小程序英文版:实现一键切换中英双语版(已组件化)
  11. linux查看程序bss段,[必须掌握].bss段和.data段的区别
  12. 7-3 学生成绩录入及查询 (20分)__C++
  13. android vlc 画面不动,vlc播放rtsp over tcp画面突然卡住问题
  14. 确定sw1开关信号输入端口_机械光开关 MEMS光开关
  15. vue实现图片自定义尺寸裁切并上传
  16. 烧一根不均匀的绳,从头烧到尾总共需要1个小时。现在有若干条材质相同的绳子,问如何用烧绳的方法来计时一 个小时十五分钟呢?(微软面试题)
  17.  Meltdown论文翻译【转】
  18. STM32 之三 标准外设版USB驱动库详解(架构+文件+函数+使用说明+示例程序)
  19. KindEditor 360浏览器系列无法显示
  20. 同时打开多个远程桌面连

热门文章

  1. 黑马程序员C++学习笔记<第一阶段_基础篇>
  2. 计算机园林辅助设计答案,园林计算机辅助设计 [常会宁编] 2010年版
  3. pe进不去linux系统怎么办,【u盘装系统进不了pe】u盘装系统有时进不了pe_u盘装系统进不去pe-系统城...
  4. 50年长盛不衰,SQL为什么如此成功?
  5. debian10 使用usb摄像头
  6. VC实现发送微博消息
  7. 跳出弹窗页面禁止滚动(PC端和手机端)
  8. 【100%通过率】华为OD机试真题 JavaScript 实现【最小调整顺序次数】【2023 Q1 | 100分】
  9. GluonTS 模型预测时间序列
  10. NLP 中的语言模型预训练微调