找回密码
 会员注册
查看: 11|回复: 0

WebGL大场景性能优化_UTF_8

[复制链接]

2万

主题

0

回帖

7万

积分

超级版主

积分
75037
发表于 2024-9-30 08:27:20 | 显示全部楼层 |阅读模式
一、WebGL 是什么WebGL(Web 图形库)是一个 JavaScript API,可在任何兼容的 Web 浏览器中渲染高性能的交互式 3D 和 2D 图形,而无需使用插件。WebGL 通过引入一个与 OpenGL ES 2.0 非常一致的 API 来做到这一点,该 API 可以在 HTML5 元素中使用。这种一致性使 API 可以利用用户设备提供的硬件图形加速。[摘自 MDN]本质:一个用来创建 2D/3D 图形网页的 JavaScript API二、WebGL 能做什么2D 框架/引擎PIXI.jsdemo:https://pixijs.com/gallery/Pixi.js 使用 WebGL,是一个超快的 HTML5 2D 渲染引擎。作为一个 Javascript 的 2D 渲染器,Pixi.js 的目标是提供一个快速的、轻量级而且是兼任所有设备的 2D 库。Pixi 渲染器可以开发者享受到硬件加速,但并不需要了解 WebGL。Phaser.jsdemo:https://phaser.io/examplesPhaser 是一个开源的桌面和移动 HTML5 2D 游戏开发框架,支持 JavaScript 和 TypeScript。高性能: 快速、免费、易于维护。一方面,开发者可以直接通过 Koding 平台上的 VM 开发系统进行代码编写及预览。另一方面,也可以在支持 Canvas 的浏览器中直接安装 Phaser 来进行游戏开发。two.jsdemo:https://two.js.org/examples/two.js 是一个二维的绘图 API,用于较新的 Web 浏览器,可基于不同上下文绘制,包括 svg、canvas 和 webgl。3D 框架/引擎Three.jsdemo:https://threejs.org/examples/#webgl_animation_keyframes当下最流行的 WebGL 库, 轻量级,容易使用,很多 webgl 库都是基于它来构建。Babylon.jsdemo:https://www.babylonjs.com/community/Babylon.js 是一个使用 HTML5 和 WebGL 构建 3D 游戏的 JavaScript 框架。Cesium.jsdemo:https://sandcastle.cesium.com/Cesium 是一款开源的基于 JavaScript 的 3D 地图框架。Cesium 能够跨平台、跨浏览器支持绝大多数的浏览器和移动端浏览器;使用 WebGL 进行 3D 图形展示。可应用于三维数字地球, 数据可视化, 创建虚拟场景等功能。三、大场景案例分析场景分类Gis 主场景https://sandcastle.cesium.com/src=3D%20Tiles%20Photogrammetry%20Classification.html3D 室内漫游场景https://dashboard.archilogic.com/scene/!7defaa68-4293-446c-b55a-d731d3506047/viewer2D 室内编辑场景https://dashboard.archilogic.com/scene/!7defaa68-4293-446c-b55a-d731d3506047/viewer各场景痛点Gis 主场景Gis 数据老旧与当前场景现实情况不一致,需要引入当前场景的最新数据,数据量大。中心场景效果要求较高(光照,阴影,反射等),对中心模型的处理很多。主场景的需要还原真实环境(实时天气,整个中心场景的统筹看板),对接数据过大。3D 室内漫游场景1 比 1 精确还原场景,对数据精确度要求很高,同时还需要附加一些效果。IOT/IBMS 数据挂接,实时状态显示及控制。2D 室内编辑场景场景内圆形、扇形等体块很多,场景三角面很多。 WebGL 基本绘图元素只有点、线、三角形,如下图中的这种复杂图形,它也是由三角形构成。编辑场景中拆分、新增、测量、合并、辅助线等操作很多,吸附、碰撞检测等计算量很大。场景中构件种类很多,不同种类的渲染呈现方式也不同,支持的操作功能亦不相同。性能问题总结模型数据过大及挂接数据较多导致的请求过多过慢问题片元处理及计算过多draw call 次数过多场景复杂三角面过多节点吸附、标签避障计算影响性能四、解决方案1. 自定义 GeoJSON 数据结构及大数据压缩方案GeoJSON 是一种开放标准的地理空间数据交换格式,可表示简单的地理要素及其非空间属性。GeoJSON 以 JavaScript 对象表示法 (JSON) 为基础,是对各种地理数据结构进行编码时所采用的格式。该格式使用地理坐标参考系(世界大地测量系统 1984),并且以十进制度作为单位。{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point",//点"coordinates":[102.0,0.5]},"properties":{"prop0":"value0"},},{"type":"Feature","geometry":{"type":"LineString",//线段"coordinates":[[102.0,0.0],[103.0,1.0],[104.0,0.0],[105.0,1.0]]},"properties":{"prop0":"value0","prop1":0.0},},{"type":"Feature","geometry":{"type":"Polygon",//面"coordinates":[[[100.0,0.0],[101.0,0.0],[101.0,1.0],[100.0,1.0],[100.0,0.0]]]},"properties":{"prop0":"value0","prop1":{"this":"that"}},},...]}由于每个场景中需要显示的元素很多。导致每个楼层的 GeoJSON 的数据过大(大约每层 4MB),这样通过 http 传输就会很慢,再加上还要请求其他的挂接数据,导致页面在渲染前耗费的时间就占用了页面所有时间的一半。思路从 GZip 来的灵感 => Deflate 算法 => LZ77 + Huffman。LZ77与LZ78是亚伯拉罕·蓝波与杰可布·立夫在 1977 年以及 1978 年发表的论文中的两个无损数据压缩算法。这两个算法是大多数 LZ 算法变体,如 LZW、LZSS 以及其它一些压缩算法的基础。与最小冗余编码器或者行程长度编码器不同,这两个都是基于字典的编码器。LZ77 是“滑动窗”压缩算法,这个算法后来被证明等同于 LZ78 中首次出现的显式字典编码技术。下面我们来举一个例子。有一份数据文件的内容如下https://www.bytedance.com https://sso.bytedance.com其中有些部分的内容,前面已经出现过了,下面用()括起来的部分就是相同的部分。https://www.bytedance.com (https://)sso(.bytedance.com)我们使用 (两者之间的距离,相同内容的长度) 这样一对信息,来替换后一块内容。https://www.bytedance.com (26,8)sso(26,14)(26,8) 中,26 为相同内容块与当前位置之间的距离,8 为相同内容的长度。(23,4) 中,26 为相同内容块与当前位置之间的距离,14 为相同内容的长度。由于(两者之间的距离,相同内容的长度)这一对信息的大小,小于被替换内容的大小,所以文件得到了压缩。霍夫曼编码(英语:Huffman Coding),又译为哈夫曼编码、赫夫曼编码,是一种用于无损数据压缩的熵编码(权编码)算法。由美国电脑科学家大卫·霍夫曼(David Albert Huffman)在 1952 年发明。[摘自维基百科]字符空格aefhimnstloprux频率7443222222111111编码1110100001101101010000111001010110110110010011010011110000011110010我们可以看到,Huffman 树的建立方法就保证了,出现次数多的符号,得到的 Huffman 编码位数少,出现次数少的符号,得到的 Huffman 编码位数多。读文件,统计每个符号的出现次数。根据每个符号的出现次数,建立 Huffman 树,得到每个符号的 Huffman 编码。将每个符号的出现次数的信息保存在压缩文件中,将文件中的每个符号替换成它的 Huffman 编码,并输出。优化前后对比优化前:约 4MB优化后:约 800KB2. 片元处理及计算过多片元处理优化(减少需要处理的片元数目)控制绘制顺序 为了最大限度地避免 overdraw,一个重要的优化策略就是控制绘制顺序。由于深度测试的存在,如果我们可以保证物体都是从前往后绘制的,那么就可以很大程度上减少 overdraw。这是因为,在后面绘制的物体由于无法通过深度测试,因此,就不会再进行后面的渲染处理。时刻警惕透明物体 由于透明度物体处理时,会导致一些硬件优化策略失效(比如说遮挡剔除,把看不到物体的顶点剔除)。对于透明度混合技术,需要关闭深度写入,所以要保持正确的渲染顺序。透明度测试没有关闭深度测试,但由于它的实现使用了 discard 或 clip 操作。也就是说,只要在执行了所有的片元着色器后,GPU 才知道哪些片元会被真正渲染到屏幕上,这样,原先那些可以减少 overdraw 的优化就都无效了。处理方式:控制绘制顺序,同时先对不透明物体从前往后排序后绘制,再绘制透明物体,进行混合。减少片元计算减少实时光照和阴影,可以使用光照贴图代替实时计算。3. draw call 次数过多使用批处理简单理解就是将使用同一个材质的物体一起处理 们之间的不同就是顶点数据的差别。如果使用不同材质,但要使用批处理,也可以将这些纹理合并到同一张大纹理称为图集,再使用不同的采样坐标对纹理采样即可。如果需要微小的不同,使用顶点颜色数据来储存。批处理是 OpenGL 的概念,WebGL 有实例绘制,告诉 GPU 使用共享模型来绘制每一个实例,也是一次绘制多个物体。在 WebGL2.0 绘制方法是:gl.drawArraysInstanced(mode,first,count,instanceCount);gl.drawElementsInstanced(mode,count,type,offset,instanceCount);下面这个方法调整实例位置:gl.vertexAttribDivisor(index,divisor);WebGL1.0 可以使用扩展:varext=gl.getExtension('ANGLE_instanced_arrays');ext.drawArraysInstancedANGLE();ext.drawElementsInstancedANGLE();在 ThreeJS 中使用 InstanceMesh 或 InstanceGeometry。Mesh 合并Mesh 网格 ,Mesh 是指模型的网格,3D 模型是由多边形拼接而成,而多边形实际上是由多个三角形拼接而成的。所以一个 3D 模型的表面是由多个彼此相连的三角面构成。三维空间中,构成这些三角面的点以及三角形的边的集合就是 Mesh。为了尽量降低 drawcall,即调用 mesh 绘制的次数。因为一次性处理一个大 mesh 比多次绘制小 mesh 要快得多。从而达到性能优化在 ThreeJS 中使用 THREE.Geometry 对象的上面的 merge 方法。举个 :当我们使用普通组的情况,绘制 20000 个立方体,帧率在 15 帧左右,如果我们选择合并以后,再绘制两万,就会发现,我们可以轻松的渲染 20000 个立方体,而且没有性能的损失。合并的代码如下:vargeometry=newTHREE.Geometry();for(vari=0;i
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-15 17:51 , Processed in 0.684209 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表