码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • three.js使用Instanced Draw+Frustum Cull+LOD来渲染大场景(开源)


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

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

    代码:Github

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

    加QQ群交流:106047770

    目录
    • 需求描述
    • Instanced Draw
    • Frustum Cull
    • LOD
    • 参考资料

    需求描述

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

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

    • 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来渲染大场景,最终实现效果演示:

    image

    场景总三角面数是千万级,总物体数量是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

    image

    如上图所示,实现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

    image

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

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

    参考资料

    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

  • 相关阅读:
    基于ISO14229协议的安全访问系列_1
    MySQL数据库之存储引擎
    CiteSpace的介绍、重要调整参数及其重要术语
    父子工程搭建
    DOM--页面渲染流程
    算法笔记(1)—— 搜索算法:线性搜索(LS)、二分搜索(BS)、记忆化搜索(MS)
    SpringCloud复习:(3)LoadBalancerInterceptor
    SpringCloud微服务实战——搭建企业级开发框架(四十七):【移动开发】整合uni-app搭建移动端快速开发框架-添加Axios并实现登录功能
    lv6 嵌入式开发-Flappy bird项目
    django_model_一对一映射
  • 原文地址:https://www.cnblogs.com/chaogex/p/18152526
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号