引子
轻量化引擎,该合并的合并,该共享的共享,材质光影等等效果都很难再提升的时候,我们总不能转到隔壁的去渲染技术栈去吧?
最近几个月,陆陆续续做了很多的尝试,先把这些方案的思路记录下来,欢迎大佬给予点评,如果这里有坑,请偷偷告知我一声,避免踩雷,就当做做善事啦,谢谢。
关于threejs实现简易的遮挡剔除
原理
思路上是很简单的。以下来自知乎的大佬,忠文老弟。
作者:忠文老弟
链接:https://zhuanlan.zhihu.com/p/557549596
来源:知乎
- 增加一个预渲染pass,用以绘制场景中需要优化的对象列表的包围盒
- 注意这里是包围盒就可以减少大量的顶点数据
- 包围盒的数据结构是固定的,我们可以做一些特殊的优化使用,后面会介绍
- 预渲染的材质一定要尽量简单,同时需要在结果能够区分是哪个mesh,尽量使用同一个材质(也是优化内容)
- 构建独立的preScene和boxmesh(包围盒mesh),渲染结果存入新构建的 RenderTarget
- 对于预渲染pass的结果,通过颜色校验,判定某个mesh是否需要显示
- 针对每个mesh建立boxmesh(包围盒mesh)
- 建立颜色映射关系,mesh --> color,color --> mesh 进行相互映射
- 优化颜色取值范围,将整个 boxmeshes 放入一个 group,并且计算出group在预渲染结束之后的窗口坐标范围
- 使用renderer.readRenderTargetPixels函数将预渲染pass的RenderTarget特定区域的颜色信息读取到应用,进行后续的判断
上面有点啰嗦,我们翻译一下:
1、为每个物体生成box,并且赋予特有的颜色。1个色号=一个物体。把RGB用完都有255*255*255个了。大概够用。
2、离屏渲染到一个新的画布,并生成图片。
3、扫描图片的颜色。出现的色号对应的物体设置为可见,反之不可见。完闭。
其优势在于离屏渲染的是box,再加上是单一的baseMaterial,可以大量的使用合并,建议用顶点着色来设置(不用照搬忠文大佬的代码,它为每个物体创建的mateiral太多了)。
总结
但是,在建筑行业这一个方式不太可行。效果不佳
1、使用box,有一些板、路面、桥梁的box过大,误判成遮挡,其实并没有遮挡,还是要显示。
2、使用原始顶点……不划算。直接渲染算了。
在BIM模型轻量化中使用八叉树
其实找到了2个应用点。
导出原始模型的空间划分
为了避免大量的构件,特别是跨了楼层和远距离空间的合并,导致threejs自带的视锥剔除效果不佳(如果整个模型合并,视锥会直接失效!因为相机看哪里,这个庞大的合并mesh都得渲染。)
所以在模型出来的时候就先打组。原则上,组要足够聚合,这个度要自己尝试,很难把握。
合并构件的时候,不跨组。
模型点击-减少射线碰撞对象
原理
这个可以用threejs的官方库,拉下来three代码之后在这个路径下:three/examples/jsm/math/Octree.js
在threejs的scene场景分割八叉树,鼠标点击产生一条射线。这条射线路过的空间,所包含的构件才需要用来检测,提高pick效果。
总结
这不是一个最优的方法。
首先在八叉树中,还是跟大量的合并以及instanced对象产生冲突,并且,还挺费内存的。我怀疑这个技术路线没有哪个引擎在用。在小模型的时候,不如直接Raycaster去检测所有对象来得快。
另一种LOD
这是本人灵机一动,瞎折腾出来的骚操作。如果有大佬路过,也请不要嘲笑,如果有更好的方法可以留言。感谢。
这种LOD,我并没有使用第三方库去做减面,或者使用原始的Revit模型去设置精度参数。而是对物体的几何内部进行分割(类似八叉树,然后保留顶点聚合的盒子)。
于是这个盒子有一定的内聚性,将来在前面2个应用上,似乎都有条件去改善了。
1、先完成空间切分
2、保留顶点所有的box
3、可以对保留的这些盒子,进行合并。文章来源:https://www.toymoban.com/news/detail-809928.html
4、后期在应用的时候,可以当作LOD在视线距离上使用,也可以在剔除的时候使用。 文章来源地址https://www.toymoban.com/news/detail-809928.html
到了这里,关于基于threejs加载大型BIM模型的优化尝试的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!