大家好,本文使用three.js实现了渲染大场景,在移动端也有较好的性能,并给出了代码,分析了关键点,感谢大家~

关键词:three.js、Instanced Draw、大场景、LOD、Frustum Cull、优化、Web3D、WebGL、开源

代码:Github

我正在承接Web3D数字孪生项目,具体介绍可看承接各种Web3D业务

加QQ群交流:106047770

需求描述

数字孪生项目通常需要渲染超大场景,比如智慧城市就需要渲染一片城市区域,甚至整个城市

渲染大场景所需要的技术点包括:

  • Instanced Draw

    一个Draw Call批量渲染物体,物体可以有不同的Transform、Color
  • Frustum Cull

    剔除视椎体外的物体
  • Occlusion Cull

    剔除被遮挡的物体(WebGL1不支持)
  • LOD

    根据物体到相机的距离,显示不同Level的物体。越远的越粗糙,越近的越细致
  • GPU Driven Pipeline

    把前几个优化都放到GPU中来做,并且物体可以有更多差异(需要WebGPU)
  • Space Partition

    使用Octree、BVH、BSP等加速结构来划分场景,在Cull、碰撞检测、Ray Picking等操作时查询加速结构而不是遍历所有物体,从而提高性能
  • Multi Thread Render

    开一个渲染线程来渲染
  • AssetBundle、Stream Load

    划分为多个场景包,动态、流式加载

本文使用Instanced Draw+Frustum Cull+LOD来渲染大场景,最终实现效果演示:

场景总三角面数是千万级,总物体数量是1万(PC端)/5000(移动端)

动态物体数量是800(PC端)/400(移动端)

其中,树使用了Instanced Draw+LOD,白色立方体使用了Instanced Draw

可以把相机拉进、拉远,可看到不同Level的树

移动相机,可看到红框内的Triangles在变化(大概在几十万到几百万),这是Frustum Cull后的三角面数

在5年前的中配手机上,FPS可达15左右

下面开始实现各个关键点,给出实现的思路:

Instanced Draw

比如要将克隆的1000个Mesh改为Instanced的,则保留它们作为source,并创建一个InstancedMesh,count设为1000,写入1000个Mesh的世界矩阵;然后隐藏source,显示InstancedMesh

之所以保留source,是因为可以用它们来做碰撞检测、Ray Picking等单个Mesh的操作

值得注意的是物体可能是多材质的Object3D(如树),所以要将其中的每个Mesh拆分到一组Instanced Draw中。举例来说,如果树有个3个材质(即3个子Mesh),则需要创建3个InstancedMesh,然后将所有树的第一个材质的Mesh对应到第一个InstancedMesh中,其余的以此类推

Frustum Cull

如上图所示,实现Instanced Draw+Frustum Cull的原理是将要剔除的物体移到InstancedMesh的instanceMatrix的最后,并将count减1

值得注意的是要将three.js默认的对单个Object3D的frustum cull关闭(即将source的frustumCulled设为false)

另外,我们直接遍历所有的待剔除物体来进行Fustum Cull检测,没有使用Octree等加速结构

相关的讨论请参考:

Linear search vs Octree (Frustum cull)

LOD

如上图所示,假设车有3个Level的LOD层级,我们希望离相机越远,显示越高的Level(Geometry、Material越简单)

我们需要创建3个InstanceMesh,分别对应不同的Level,如下图所示:

参考资料

InstancedMesh2 - Easy handling and frustum culling

What is a more straightforward way to do instance culling?

Linear search vs Octree (Frustum cull)

100kTrees

LOD + Instancing

LOD with Instancing and Multi-Material Meshes

Three.js InstancedMesh performance optimizations - DevLog 10

three.js使用Instanced Draw+Frustum Cull+LOD来渲染大场景(开源)的更多相关文章

  1. arcgis for js学习之Draw类

    arcgis for js学习之Draw类 <!DOCTYPE html> <html> <head> <meta http-equiv="Cont ...

  2. AeroGear.js 1.2.0 发布,手机Web应用脚手架 - 开源中国社区

    AeroGear.js 1.2.0 发布,手机Web应用脚手架 - 开源中国社区 AeroGear.js 1.2.0 发布,手机Web应用脚手架

  3. three.js引擎基础知识—摄像机、场景及渲染器

    一.three.js采用右手坐标系: x轴正方向向右,y轴正方向向上,z轴由屏幕从里向外,如下图右: 二.3D编程三要素:场景.渲染器.摄像机 1.场景:创建的物品和模型都需放入场景中 threejs ...

  4. 关于Unity中LOD和渲染队列----渲染通道通用指令(一)

    每个shader里面有很多的subshader,如果所以的subshader都不执行的话就,就执行fallback.每个subshader都可以设置一个LOD,整个shader也有一个LOD. 系统就 ...

  5. Vue.js 2.0源码解析之前端渲染篇

    一.前言 Vue.js框架是目前比较火的MVVM框架之一,简单易上手的学习曲线,友好的官方文档,配套的构建工具,让Vue.js在2016大放异彩,大有赶超React之势.前不久Vue.js 2.0正式 ...

  6. Vue.js 源码分析(三) 基础篇 模板渲染 el、emplate、render属性详解

    Vue有三个属性和模板有关,官网上是这样解释的: el ;提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标 template ;一个字符串模板作为 Vue 实例的标识使用.模板将会 ...

  7. three.js 源代码凝视(十六)Math/Frustum.js

    商域无疆 (http://blog.csdn.net/omni360/) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:商域无疆 -  本博客专注于 敏捷开发 ...

  8. three.js 入门详解(一)

    1. 概述 1.1 什么是WebGL? WebGL是在浏览器中实现三维效果的一套规范 想要使用WebGL原生的API来写3D效果的话,很吃力.three.js是WebGL的一个开源框架,它省去了很多麻 ...

  9. js css3实现钟表效果

    原理: 利用transform-origin改变旋转的圆心,实现秒数和分钟数的刻度线,利用transfrom translate实现钟表小时刻度的显示 html: <div class=&quo ...

  10. 解决js动态改变dom元素属性后页面及时渲染问题

    今天实现一个进度条加载过程,dom结构其实就是两个div <div class="pbar"> <div class="ui-widget-header ...

随机推荐

  1. import.meta.globEager('./src/components/**/*.vue'); 遍历文件

    main.js const importAll = (modules) => { Object.keys(modules).forEach((key) => { const compone ...

  2. 【mac】Alfred 无法调用Terminal

    原因:是从mac app商店安装的Alfred class 解决方案:建议从官网下载安装:https://www.alfredapp.com/ 参考:https://www.alfredforum.c ...

  3. Ubuntu 14.04 升级到Gnome3.12z的折腾之旅(警示后来者)+推荐Extensions.-------(二)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文发布于 2014-12-22 15:33:35 ...

  4. 简单使用vim编辑器的用法

    vim的使用笔记可以涵盖很多内容,以下是一些基本操作和常见命令的简要总结: 启动Vim 打开或创建文件:vim filename 基本模式切换 正常模式(Normal Mode):启动时默认进入此模式 ...

  5. 记录--npm, npx, cnpm, yarn, pnpm梭哈

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 依赖管理解决了在软件开发过程中管理和协调各种依赖项的问题,简化了开发流程,提高了项目的可靠性.可维护性和可重复性.它们帮助开发人员更高效地 ...

  6. KingbaseES Json 系列二:Json对象函数

    KingbaseES Json 系列二--Json对象函数(JSONB_BUILD_OBJECT,JSONB_OBJECT,JSON_BUILD_OBJECT,JSON_OBJECT) JSON 数据 ...

  7. PicGo图床配置github仓库上传typora图片

    (前提是已注册github并新建一个仓库作为你上传图片的位置) 首先在PicGo官网下载软件:https://picgo.github.io/PicGo-Doc/zh/ 打开typora,找到偏好设置 ...

  8. 5W1H聊开源之Why——为什么要参与开源?

    中国开源的发展速度发展加快,个人和组织对于为开源作贡献有着前所未有的激情.据<2020年IT行业项目管理调查报告>,约四成受访者以自己开发开源项目.为他人提交项目代码.作为成员开发维护项目 ...

  9. #单位根反演,二项式定理#LOJ 6485 LJJ 学二项式定理

    题目 \[\large\sum_{i=0}^nC(n,i)S^ia_{i\bmod 4} \] \(n\leq 10^{18},S,a\leq 10^8\) 分析 前面这一坨看起来就像是二项式定理,考 ...

  10. OpenHarmony社区运营报告(2023年8月)

      本月快讯 ● 2023年8月3日,OpenAtom OpenHarmony(以下简称"OpenHarmony")发布了Beta2版本.OpenHarmony 4.0 Beta2 ...