three.js中的instancedMesh類優化渲染多個同網格材質的模型

three.js小白的學習之路。

在上上一篇博客中,簡單驗證了一下three.js中的網格共享。寫的時候就有一些想法,如果說某個場景中有一萬棵樹,這些樹共享一個geometry和material,有沒有好的辦法將其進行一定程度上的渲染優化,以提高瀏覽器的幀率。

查閱了了一番資料,找到一個three.js中的類——InstanceMesh。

介紹

three.js的官網是這樣介紹的:InstancedMesh實例化網格是特殊版本的Mesh(具有mesh的相關屬性和方法),可以用來渲染大量的具有相同幾何體和材質、但具有不同世界變換的物體。InstancedMesh可以減少draw call的數量,從而提升程序整體的渲染性能。聽起來就和我們想要的效果很搭。

構造函數:

InstancedMesh(geometry: BufferGeometry, material: Material, count: Number)

其中geometry和material表示相同的幾何體和材質,count表示有多少共用這些幾何體和材質的mesh。

屬性:

.count

實例的數量,可以在運行時改變這個數值,范圍是[0, count],如果比count大,需要重新創建實例。

還有其他如boundingBox(外邊接矩形)、instancedColor(所有實例的顏色)、instanceMatrix(所有實例的局部變換)等。

方法:

.computeBoundingBox(): undefined
.computeBoundingSphere(): undefined

分別對應boundingBox和boundingSphere兩個屬性。

.dispose(): undefined

釋放實例的內部資源。

.setMatrixAt( index: Number, matrix: Matrix4): undefined

index表示是第幾個實例Mesh,范圍是[0, count);matrix表示一個給定的局部變化矩陣。

其他的方法還有setColorAt(設置已定義實例的顏色)、getColorAt、getMatrixAt等。

示例

假如說有這么一個山地場景,里面需要很多很多的樹(這里為了方便,就使用一個平面+五個立方體表示一棵樹)。每棵樹共用geometry和material,但是每個數的平移旋轉縮放均不相同。

首先先正常的將其加載到場景里面:

new GLTFLoader().load("/instanced.glb", (glb) => {const mesh = glb.scene;scene.add(mesh);
});

此時,場景的渲染幀率如圖所示:

幀率大概只有14幀左右。

接下來對場景中每棵樹,也就是立方體進行InstancedMesh實例化。

首先需要獲取到所有的立方體Mesh:

const instanceArr: Three.Mesh[] = [];  
glb.scene.traverse((item) => {if (item.isMesh && item.name.startsWith(name)) {instanceArr.push(item);}});

接下來就是對這些Mesh進行實例化:

  const count = instanceArr.length; // 相同模型的總個數// 創建InstancedMesh實例const instanceMesh = new Three.InstancedMesh(instanceArr[0].geometry,instanceArr[0].material,count);

通過數組的第一個元素,獲取到共享的geometry和material。

然后就是在獲取所有mesh的世界變換,并分別應用到每一個實例Mesh中:

  const matrix = new Three.Matrix4();const pos = new Three.Vector3();const qua = new Three.Quaternion();const sca = new Three.Vector3();instanceArr.forEach((obj, i) => {obj.getWorldPosition(pos);obj.getWorldQuaternion(qua);obj.getWorldScale(sca);matrix.compose(pos, qua, sca); // 將此矩陣設置為由平移、旋轉和縮放組成的變換。instanceMesh.setMatrixAt(i, matrix); // 更新InstancedMesh中每個實例的變換矩陣});

最后將InstancedMesh加入到場景中,并且將原有的所有立方體mesh從場景中移除:

  scene.add(instanceMesh);instanceArr.forEach((obj) => {obj.parent?.remove(obj); // 模型移除});instanceArr.splice(0, count); // 清除引用

看一下運行結果:

可以看到,幀率幾乎拉滿到60幀,提升效果顯著!

思考

做了一個簡單的實驗,就是將現在這個模型在一個性能較差(內存小,沒有獨顯等)電腦上加載,使用InstancedMesh前后的性能對比如圖所示:

使用前

使用后

可以看到,使用前后的幀率幾乎一樣,都在3-5幀。

這就拋出了一個問題,就是如果模型本身就已經超出或者將要超出瀏覽器的承載極限時,這個InstancedMesh方法幾乎是沒有效果的。從這個角度來說,這個優化或許有一些局限性,即適用于那些有大量的共享網格和材質,且瀏覽器幀率較低,但是瀏覽器依然可以正常運行的情況。

總結

InstancedMesh類可以很好地優化那些具有大量的共享材質和網格,但是有不同平移旋轉縮放的模型,就類似于blender中使用了Alt+D復制了很多份,然后每一個模型的位姿又有不同。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/80335.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/80335.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/80335.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL-自定義函數

自定義函數 函數的作用 mysql數據庫中已經提供了內置的函數,比如:sum,avg,concat等等,方便我們日常的使用,當需要時mysql支持定義自定義的函數,方便與我們對于需用復用的功能進行封裝。 基本…

ESP32上C語言實現JSON對象的創建和解析

在ESP32上使用C語言實現JSON對象的創建和解析,同樣可以借助cJSON庫。ESP-IDF(Espressif IoT Development Framework)本身已經集成了cJSON庫,你可以直接使用。以下是詳細的步驟和示例代碼。 1. 創建一個新的ESP-IDF項目 首先&…

【FAQ】PCoIP 會話后物理工作站本地顯示器黑屏

# 問題 工作人員從家里建立了到辦公室工作站的 PCoIP 連接,該工作站安裝了 HP Anyware Graphics Agent,并且還連接了本地顯示器。然后,遠程用戶決定去辦公室進行本地工作,工作站顯示器顯示黑屏(有時沒有信號&#xff…

el-table 目錄樹列表本地實現模糊查詢

table目錄樹結構實現模糊查詢 <el-form :model"queryParams" ref"queryForm" size"small" :inline"true" v-show"showSearch"><el-form-item label"名稱:" prop"Name"><el-input v-mode…

力扣hot100 LeetCode 熱題 100 Java 哈希篇

兩數之和 1. 兩數之和 - 力扣&#xff08;LeetCode&#xff09; 直接暴力 class Solution {public int[] twoSum(int[] nums, int target) {for(int i0;i<nums.length;i){for(int ji1;j<nums.length;j){long ans nums[i]nums[j];if(ans>target)continue;if(anstarg…

前后端部署

#在學習JavaWeb之后&#xff0c;進行了蒼穹外賣的學習。在進行蒼穹外賣的部署的時候&#xff0c;作者遇到了下面的問題# 1.前端工程nginx無法啟動&#xff1a; 當我雙擊已經部署好的nginx工程中nginx.exe文件的時候&#xff0c;在服務中&#xff0c;并沒有找到ngnix成功運行。…

基于 EFISH-SBC-RK3588 的無人機環境感知與數據采集方案

一、核心硬件架構設計? ?高性能算力引擎&#xff08;RK3588 處理器&#xff09;? ?異構計算架構?&#xff1a;集成 8 核 CPU&#xff08;4Cortex-A762.4GHz 4Cortex-A551.8GHz&#xff09;&#xff0c;支持動態調頻與多任務并行處理&#xff0c;單線程性能較傳統四核方案…

什么是Maven

Maven的概念 Maven是一個一鍵式的自動化的構建工具。Maven 是 Apache 軟件基金會組織維護的一款自動化構建工具&#xff0c;專注服務于Java 平臺的項目構建和依賴管理。Maven 這個單詞的本意是&#xff1a;專家&#xff0c;內行。Maven 是目前最流行的自動化構建工具&#xff0…

mongo客戶端操作mongodb記錄

背景&#xff1a; 長時間不操作mongodb數據庫&#xff0c;已經遺忘了命令&#xff0c;今天正好用到&#xff0c;溫習一下 直接上命令 #進入mongodb數據庫安裝bin目錄cd /opt/mongodb/bin#連接mongodb ./mongo #查看所有的數據庫 show dbs; #選擇數據庫 use xx; #查看表 show …

rocky9.4部署k8s群集v1.28.2版本(containerd)(純命令)

文章目錄 前言三個節點的主機名 所有節點操作主機名和ip解析關閉交換分區&#xff0c;關閉防火墻&#xff0c;關閉selinux更換阿里云yum源時間同步修改內核參數修改系統最大打開文件數開啟bridge網橋過濾&#xff0c;加載br_netfilter模塊&#xff0c;加載配置文件安裝ipset及i…

解析塔能科技:綠色低碳智慧節能一站式破局之匙

在能源問題日益凸顯的當下&#xff0c;綠色低碳、高效節能成為全球發展的重要課題。對各類節能方案進行深入剖析后&#xff0c;可以發現塔能科技的綠色低碳智慧節能一站式解決方案極具創新性與實用性&#xff0c;切實為眾多行業面臨的能源困境提供了有效解決路徑。 直面行業痛點…

精選面試題

1、js中set和map的作用和區別? 在 JavaScript 中&#xff0c;Set 和 Map 是兩種非常重要的集合類型 1、Set 是一種集合數據結構&#xff0c;用于存儲唯一值。它類似于數組&#xff0c;但成員的值都是唯一的&#xff0c;沒有重復的值。Set 中的值只能是唯一的&#xff0c;任何…

Flutter之路由和導航

目錄&#xff1a; 1、flutter路由和導航簡介2、路由的使用2.1、使用 Navigator2.2、使用命名路由2.3、使用路由器 3、應用中添加Tab導航4、頁面跳轉一個新頁面和回退5、傳遞數據到新頁面6、使用 RouteSettings 傳遞參數 1、flutter路由和導航簡介 Flutter 提供了一個完整的系統…

KMS工作原理及其安全性分析

在當今數字化時代&#xff0c;數據安全已經成為企業和個人最為關注的話題之一。隨著云計算和大數據的快速發展&#xff0c;如何安全地管理密鑰成為了一個重要的挑戰。KMS&#xff08;Key Management Service&#xff0c;密鑰管理服務&#xff09;作為一種專業的密鑰管理解決方案…

機器學習在網絡安全中的應用:守護數字世界的防線

一、引言 隨著信息技術的飛速發展&#xff0c;網絡安全問題日益凸顯&#xff0c;成為全球關注的焦點。傳統的網絡安全防護手段&#xff0c;如防火墻、入侵檢測系統&#xff08;IDS&#xff09;和防病毒軟件&#xff0c;雖然在一定程度上能夠抵御攻擊&#xff0c;但在面對復雜多…

Java在excel中導出動態曲線圖DEMO

1、環境 JDK8 POI 5.2.3 Springboot2.7 2、DEMO pom <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version></dependency><dependency><groupId>commons…

Android APP 爬蟲操作

工具 夜神模擬器、charles、mitm 等 mitm的使用參考:Mitmproxy對Android進行抓包&#xff08;真機&#xff09;_mitmproxy 安卓-CSDN博客 charles的使用參考&#xff1a;【全網最詳細】手把手教學Charles抓包工具詳細自學教程&#xff0c;完整版安裝教程&#xff0c;詳細介紹…

Redis的LFU策略具體怎么工作?

Redis的LFU&#xff08;Least Frequently Used&#xff09;策略通過動態跟蹤鍵的訪問頻率實現淘汰決策&#xff0c;其核心工作邏輯可分為以下四個部分&#xff1a; 數據結構設計? 字段拆分?&#xff1a;每個Redis對象&#xff08;redisObject&#xff09;的lru字段&#xff…

Redis 及其在系統設計中的作用

什么是Redis Redis 是一個開源的內存數據結構存儲系統&#xff0c;可用作數據庫、緩存和消息代理。它因其快速的性能、靈活性和易用性而得到廣泛應用。 Redis 數據存儲類型 Redis 允許開發人員以各種數據結構&#xff08;例如字符串、位圖、位域、哈希、列表、集合、有序集合…

MySQL:如何用關系型數據庫征服NoSQL核心戰場?

寫在前面&#xff1a;當SQL遇見NoSQL的十年之變 2012年MongoDB掀起文檔數據庫革命時&#xff0c;開發者們不得不在靈活性與事務一致性之間做痛苦抉擇。十年后的今天&#xff0c;MySQL 8.0的JSON功能已實現&#xff1a; ? 二進制存儲效率超越傳統BLOB 40% ? 多值索引使JSON查…