如何在Unity WebGL上实现一套全流程简易的TextureStreaming方案

news2024/9/27 13:35:52

项目介绍

《云境》是一款使用Unity引擎开发的WebGL产品,有展厅,剧本,Avatar换装,画展,语音聊天等功能,运行在微信小程序和PC,移动端网页,即开即用。
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

当前问题和现状

当前项目面临的问题和场景现状

  1. 首次场景包体大,首次下载时间长,用户首次进入到场景耗时较长。
  2. 项目场景本身偏展厅风格,非大世界,非大型游戏场景,云境的场景元素整体比较集中,当前项目场景多数多数是室内场景或者小场景,拆分出去的内容有限,美术人力资源有限,对场景做更细致的拆分处理和分块加载成本较高。

我们需要一套简单适用的方案,降低场景包体大小。为了优化场景资源包大小,我们首先需要分析资源包里面的不同类型的资源占比,看哪些资源可以做优化和拆分

场景资源包分析

AssetBundle使用LZ4压缩,下面是针对三个原始场景资源包的分析
公园场景park_001.bundle,8.63MB,Mesh(6.5MB)+Texture2D(5.7MB)
请添加图片描述

剧本场景scenes_bxzf.bundle,11.3MB,Mesh(8.9MB),Texture2D(8.0MB)
请添加图片描述

某个展馆scenes_jttd.bundle,5.3MB,Mesh(439.3KB),Texture2D(8.0MB)
请添加图片描述

通过针对多个场景的资源包分析,会看到Mesh+Texture2D是一个场景资源包占比最高的两种资源类型,Texture2D基本占比在50%以上,而且针对个别场景Texture2D的资源占比会超过80%

方案确定

根据场景资源包的分析,可以得出的结论,针对云境目前的场景特点,多数场景Texture纹理贴图占比在50%~80%,如果采用Texture的处理能够很大程度上降低场景资源包的大小,收益比较明显,同时TextureStreaming的实现,相对MeshStreaming相对简单,投入产出比高,TextureStreaming不会改变场景原有的结构,可以降低美术人员的参与成本。

第一期设计一套简单,易实现,工作流完善的TextureStreaming方案,降低场景资源包中Texture的占比。

Unity引擎自身基于MipMapLevel实现的TextureStreaming,在WebGL平台该功能无法使用 所以需要自己开发一套简化版本并和平台无关的TextureStreaming功能。和Unity的TextureStreaming方案相比,解决的问题有相似的地方,比如控制Texture在运行时的内存占用,将纹理内存维持在一个范围内。但是我们设计的TextureStreaming方案需要关注场景资源包大小同时能够在运行时降低Texture内存的占用。

什么是TextureStreaming

定义的轻量级TextureStreaming功能:将使用高清纹理的场景,离线处理成极低分辨率的场景叫做Lod Scene,在运行时加载Lod Scene,根据规则,从外部加载相应的高清纹理,对低分辨率的纹理做替换。原理简单容易理解。

整体设计目标-TextureStreaming

核心目标:实现简单,工作流程清晰,全自动化

方案需要达成的目标

  1. 非侵入式,做材质和纹理贴图的全量拷贝,降低复杂度和资源引用维护成本
    • 不改变原场景
    • 不修改原场景引用的材质,避免造成材质混乱,错误修改
    • 不修改原场景引用的纹理贴图
    • 不修改打包规则和之前的加载逻辑
    • 保留原始场景光照贴图和渲染设置,忽略对光照贴图的Lod处理
  2. 一键式处理,通过EditorSceneDescriptionConfig文件控制生成的Lod Scene内容,避免人工处理,节省人力
  3. EditorSceneDescriptionConfig需要支持的动态配置
    • 控制单个贴图LOD分辨率,提供x16,x32,x64,x128和原始贴图尺寸
  4. Editor离线和运行时配置分开,运行时配置数据结构简单
  5. Texture AssetBundle包大小,根据配置自动分割AB包
    • 最小化更新,Texture AssetBundle打包更新不会造成,整个Lod Scene也被更新
    • 需要HD Texture AssetBundle和Lod Scene AssetBundle无依赖关系
  6. 运行时,支持Texture Streaming功能分场景动态开关,加载HD Scene还是Lod Scene
  7. 运行时,支持Streaming流式加载(分Grid,分帧加载TextureCell)
  8. 运行时,支持Texture Bundle分帧请求加载,降低可能带来的卡顿
  9. 运行时,支持Material分帧修改,降低可能带来的卡顿(经过测试,暂时未发现该部分的耗时情况)
  10. 运行时,Grid直接选择九宫格方式,当前Grid索引+外部8个Grid的内容
  11. 运行时,使用最简单的加载规则,玩家在场景中的世界坐标作为整体输入参数
  12. 运行时,场景切换HD Texture加载和卸载正常
  13. 运行时,纹理切换不会卡顿

方案设计和实现

资源管理

目前使用Unity Addressable进行资源运行时管理和资源打包

Texture Streaming美术处理管线

完整的处理流程图如下:
请添加图片描述

场景处理管线具体介绍

创建SceneDescriptionConfig配置

请添加图片描述

采集场景资源:材质,纹理

获取场景中,所有引用的材质球和关联的纹理贴图,为后续生成LodScene做数据准备
忽略的部分:

  • 光照贴图
  • TMP Shader相关的材质球和纹理

拷贝Material,生成LodTexture,LodScene

生成LodScene

  1. 将依赖的材质拷贝一份,生成Lod Materials
  2. 将材质球依赖的所有Textures拷贝一份,生成HD Textures
  3. 根据设定的HD Texture 分辨率执行Texture缩放,生成Lod Textures
  4. 拷贝原始场景,生成Lod Scene
  5. Lod Materials引用的Texture更换为Lod Textures
  6. Lod Scene关联的Material替换为拷贝的Lod Materials

经过上述的处理,完成了Lod Scene的生成,保证对原始场景的资源无侵入处理,会带来一定的资源冗余比如Lod Textures,不过牺牲一小部分的内存,能够简化流程和实现方式,在当前项目目前是可以接受的

设置Grid参数,按照规则Grid分割场景

请添加图片描述

目前只支持规则的Grid切分,Grid的可调整的参数如下:

  • Grids起始位置
  • Grids,行列大小
  • 每个Grid大小的大小
    请添加图片描述

获取每个Grid包含的Renders

遍历场景中的所有Renders,确定所在的Grid,确定每个Grid依赖的Renders,通过Renders确定当前Grid依赖的Lod Materials,根据Lod Materials确定当前Grid需要加载的HD Textures

创建运行时Config,建立Grid,材质和贴图的映射关系配置

建立Grid-HD Texture-Materials之间的映射关联配置

运行时配置文件

请添加图片描述

Grid配置,一个Grid关联到多个Texture Cells

请添加图片描述

Texture Cells配置

  1. 资源Addressable Key(GUID),用于Addressable通过Key执行加载
  2. 对应的Lod texture引用
  3. 当前HD Texture关联的材质球和纹理槽位,如果当前HD Texture加载完毕,更新关联的Material对应的纹理槽位即可
    请添加图片描述

自动化资源分组

Lod Scene:Lod场景

  • Lod Scene Material + Runtime Config:Lod场景引用的材质球和运行时配置
  • Lod Scene HD Textures:Lod场景引用的HD Textures,按照Texture单个包体指定的大小,自动生成对应的Label做分包处理,Group使用Pack Together By Label模式打包

最终管线输出产物

自动化生成的工程产物

请添加图片描述

  • HDTextures:存放拷贝出来的原始纹理资源
  • LodTextures:存放处理过后的低分辨率的纹理资源
  • Mats:存放Lod Scenes引用的材质球资源
  • outdoors_001_gen_lod.scene:Lod 场景文件
  • outdoors_001_gen_lod_runtime.asset:TextureStreaming运行时配置文件

Addressable资源打包分组

Lod Scene-单独Group分组

  • Lod Materials+Runtime Config-单独的Group分组
  • Lod Textures-同一个Group分组,但是打包的采用Packed Together By Label方式打包成多个AssetBundle包
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述

运行时逻辑

运行时的逻辑比较简单直接

接收角色位置输入->确定Gird->确定关联的TextureCells->使用Key加载->加载完毕,更新TextureCell关联的Materials
最终实现Lod Texture到HD Texture的动态更新
为了防止Grids关联的TextureCells过多,导致请求数量多,加载多,做了简单的“分帧”处理

  1. 玩家位置设定更新间隔,一定间隔检查Grid是否变换,有变换执行Grid管理资源加载
  2. 增加最大加载TextureCells数量限制,超过当前加载的数量,放入到等待队列中
  3. 等待队列检测增加轮询间隔
  4. HD Textures加载完毕放入队列,增加间隔去设置SetTexture,经过测试SetTexture并不会造成卡顿,所以取出对SetTexture的分帧处理

场景切换之后需要调用Addressables.Release(tc.Value);释放Texture2D资源

TextureStreaming方案收益

场景资源包大小在使用TextureStreaming之后的大小优化对比,目前已有的18个场景,场景包体大小都控制在5.5MB以下,首次加载时间优化,按照4G网络情况理论测算缩短3~5s,贴图资源量越大,包体减小越大,收益会比较明显
请添加图片描述

基础场景实现效果

streaming展示

总结和展望

本文介绍了适用于WebGL平台的场景包体大小优化的TextureStreaming方案,相对大世界流式加载复杂完善的方案,当前的TextureStreaming方案在一定程度上解决项目的痛点,优化了WebGL应用的场景包体大小,缩短下载时间,但是该方案还有很多需要继续细化和完善的地方,比如Grid粒度“粗糙”,加载逻辑更细致的控制,后续也会持续改进。

TextureStreaming后续完善的方向

  1. 场景处理管线,细化分割粒度和规则
  2. 运行时,细化加载规则,更精准的优先级,支持更多参数的输入视角,朝向
  3. 运行时,根据规则预加载Grid,降低延迟
  4. 运行时,支持动态卸载Grid,降低内存占用
  5. 打包资源,更精确化的Texture分包,目前采用Editor模式获取纹理大小,某些情况下获取的纹理大小和实际打包压缩之后的AB包大小差别比较大,导致Texture,AB分包并不均匀
  6. 针对LOD的纹理图片可以直接关闭MipMap,更快的加载速度和更小的内存,开启MipMap会带来33%的内存增大

场景资源包优化其他思路

  1. 支持Mesh Streaming
  2. 支持场景物件的拆分,将物件拆分出去,降低包体大小和场景对象数量
  3. LightMap的处理,进一步减少Texture2D的占用

TextureStreaming方案从问题分析,方案设计,到工具开发,运行时实现,整体比较简单易理解。
只有适合项目并解决项目痛点的方案才是合理的方案。当前的方案还有许多可以继续优化和扩展的地方,后续会持续优化。

希望能够提供一些思路和帮助,欢迎交流和指正~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2170121.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt-QTableWidget多元素控件(37)

目录 描述 QTableWidget 方法 QTableWidgetItem 信号 QTableWidgetItem 方法 使用 图形化界面操作 代码操作 描述 这是一个表格控件,表格中的每一个单元格,都是一个 QTableWidgetItem 对象 QTableWidget 方法 item(int row,int column)根据⾏数…

[半导体检测-7]:半导体检测技术:无图案晶圆检测与图案晶圆检测

前言: 半导体检测技术中,无图案晶圆检测与图案晶圆检测是两种重要的检测方式,它们在检测原理、应用场景及挑战等方面存在显著差异。以下是对这两种检测技术的详细分析: 一、无图案晶圆检测 1. 检测原理 无图案晶圆检测主要关注…

DRF实操学习——收货地址的设计

DRF实操学习——收货地址的设计 1.行政区划表的设计2. 行政区划表接口演示1.返回所有的省份2. 查询指定上级行政区划的所有子区划,以及展示自身区划 3.行政区划表接口重写补充:前端请求逻辑4. 优化5.收货地址的设计6. 收货地址表接口重写7.优化1. 优化返…

Android 12系统源码_输入系统(三)输入事件的加工和分发

前言 上一篇文章我们具体分析了InputManagerService的构造方法和start方法,知道IMS的start方法经过层层调用,最终会触发Navite层InputDispatcher的start方法和InputReader的start方法。InputDispatcher的start方法会启动一个名为InputDispatcher的线程&…

混拨动态IP代理的优势是什么

在当今互联网时代,隐私保护和网络安全成为了人们关注的焦点。无论是个人用户还是企业,都希望能够在网络上自由、安全地进行各种活动。混拨动态IP代理作为一种新兴的技术手段,正逐渐受到大家的青睐。那么,混拨动态IP代理到底有哪些…

【工具】JDK版本不好管理,SDKMAN来帮你

前言 🍊缘由 SDKMAN真是好,JDK切换没烦恼 🐣 闪亮主角 大家好,我是JavaDog程序狗 今天跟大家能分享一个JDK版本管理工具SDKMAN 当你同时使用JDK 1.8的和JDK 17并行维护两个项目时。每次在两个项目之间并行开发,切…

进阶数据库系列(十三):PostgreSQL 分区分表

概述 在组件开发迭代的过程中,随着使用时间的增加,数据库中的数据量也不断增加,因此数据库查询越来越慢。 通常加速数据库的方法很多,如添加特定的索引,将日志目录换到单独的磁盘分区,调整数据库引擎的参…

2.4卷积3

2.4卷积3 文章学习自https://zhuanlan.zhihu.com/p/41609577,详细细节请读原文。 狄拉克 δ \delta δ 函数: δ ( x ) { ∞ , x 0 0 , x ≠ 0 \delta (x){\begin{cases} \infty ,& x0\\ 0,& x\neq 0\end{cases}} δ(x){∞,0,​x0x0​ 并…

小柴冲刺软考中级嵌入式系统设计师系列二、嵌入式系统硬件基础知识(2)嵌入式微处理器基础

目录 冯诺依曼结构 哈佛结构 一、嵌入式微处理器的结构和类型 1、8位、16位、32位处理器的体系结构特点 2、DSP处理器的体系结构特点 3、多核处理器的体系结构特点 二、嵌入式微处理器的异常与中断 1、异常 2、中断 flechazohttps://www.zhihu.com/people/jiu_sheng …

54 循环神经网络RNN_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录循环神经网络使用循环神经网络的语言模型困惑度(perplexity)梯度剪裁 循环神经网络 使用循环神经网络的语言模型 输入“你”,更新隐变量,输出“好”。 困惑度(perplexity&#xff…

【递归】8. leetcode 671 二叉树中第二小的节点

题目描述 题目链接:二叉树中第二小的节点 2 解答思路 注意这句话:该节点的值等于两个子节点中较小的一个 二叉树的根节点的值是整棵树中最小的值 本道题所要求的是二叉树中第二小的节点。因为根节点是最小的节点,那么我们只需要找到第一…

HT5169内置BOOST升压的11W I2S输入D类音频功放

1 特性 ● 电源供电 升压输入VBAT:2.5V-5.5V; 升压输出PVDD可调,最高7.5V DVDD/AVDD分辨率:3.3V ● 音频性能 9.0W (VBAT3.7V, PVDD 7.5V, RL3Ω.THDN10%) 11.0W(VBAT3.7V, PVDD 7.5V, RL2Ω.THDN10% 5.5W (VBAT3.7V, PVDD 6.5V, RL4Ω.THDN10%) ● 灵活的…

红米k60至尊版工程固件 MTK芯片 资源预览 刷写说明 与nv损坏修复去除电阻图示

红米k60至尊版机型代码为:corot。 搭载了联发科天玑9200+处理器。此固件mtk引导为MT6985。博文将简单说明此固件的一些特点与刷写注意事项。对于NV损坏的机型。展示修改校验电阻的图示。方便改写参数等 通过博文了解 1💝💝💝-----此机型工程固件的资源刷写注意事项 2…

css 中 ~ 符号、text-indent、ellipsis、ellipsis-2、text-overflow: ellipsis的使用

1、~的使用直接看代码 <script setup> </script><template><div class"container"><p><a href"javascript:;">纪检委</a><a href"javascript:;">中介为</a><a href"javascript:…

曲线图异常波形检测系统源码分享

曲线图异常波形检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comput…

【cache】浅析四种常用的缓存淘汰算法 FIFO/LRU/LFU/W-TinyLFU

本文浅析淘汰策略与工作中结合使用、选取&#xff0c;并非针对算法本身如何实现的 文章目录 FIFOLFULRUW-TinyLFU实践与优化监控与调整 FIFO first input first output &#xff0c; 先进先出&#xff0c;即最早存入的元素最先取出&#xff0c; 典型数据结构代表&#xff1a;…

SpringCloud-Netflix第一代微服务快速入门

1.springCloud常用组件 Netflix Eureka 当我们的微服务过多的时候&#xff0c;管理服务的通信地址是一个非常麻烦的事情&#xff0c;Eureka就是用来管理微服务的通信地址清单的&#xff0c;有了Eureka之后我们通过服务的名字就能实现服务的调用。 Netflix Ribbon\Feign : 客…

Python精选200Tips:171-175

深度学习实战项目 P171--CIFAR10数据集图像分类(Image Classification)P172--MS COCO数据集物体检测(Object Detection)P173-- MNIST手写数字数据集DCGAN生成P174--基于EasyOCR的字符识别P175--基于Air Quality数据集的变分自编码器(Variational autoEncoder&#xff0c;VAE) 运…

QT版数据采集系统研发过程记录

研发目的&#xff1a;通过智能监测设备将各个变电站运行的电压、电流、温湿度等数据采集汇总到计算机中心服务器&#xff0c;通过系统软件展示各个站点对应的运行工况。 软件架构&#xff1a;使用QT开发跨平台&#xff08;Windows系统、Ubuntu20.04&#xff09;客户端软件、连…

基于MATLAB的苹果外观特征检测

摘 要 本文根据苹果分级判定标准中的两个评定指标&#xff1a;果径和果面缺陷&#xff0c;探讨如何利用MATLAB技术进行苹果外观的特征检测&#xff0c;从而提高苹果品质检测的工作效率。 关键词 MATLAB&#xff1b;苹果分级&#xff1b;果径&#xff1b;果面缺陷 0 引言 …