3D 網站的效能問題分成三段,量法與解法互不通用。載入是使用者等多久才看到產品、多久能開始操作;記憶體是手機撐不撐得住、會不會閃退;每幀是轉動與縮放時畫面順不順。三段混成一句「很卡」,就無法判斷該改哪裡。
Core Web Vitals 量得到什麼、量不到什麼
LCP 是首屏中最大的影像、文字區塊或影片的繪製時間,從使用者開始導覽時計算,良好門檻是 2.5 秒以內(Walton 等,2019)。INP 綜合整段拜訪中所有點擊、點按與按鍵的互動延遲,取最差的互動並排除離群值,200 毫秒以下為良好,500 毫秒以上為差(Wagner 等,2022)。
CLS 衡量非預期的版面位移,良好是 0.1 以下,高於 0.25 為差(Mihajlija 等,web.dev)。依這些定義,畫布裡的產品何時第一次出現、何時能開始操作,以及轉動模型時的每幀時間,都不在涵蓋範圍內,需要另外設量測點。
MDN 文件的 WebGL 建議(MDN Web Docs,2026)同樣分三部分:減少 draw call、管理貼圖記憶體,以及先編譯全部著色器再連結。draw call 與著色器編譯落在每幀,貼圖落在記憶體與載入。文件只給原則,沒有實測數字。

卡頓先分時序與成本,再判瓶頸
3D 卡頓有兩種完全不同的病。時序問題是動畫接不上、轉場停頓;成本問題是每一幀都在做太多事。持續卡,先量每秒幀數、shader 重編次數與 GPU 時間;只在轉場卡,才去看動畫時序。
持續卡頓常見的誤判,是反覆調動畫時序卻始終無效。真因可能有兩個:畫面被鎖在持續渲染,但內容其實是靜止的;介面標注每隔一小段時間整批重建,卸載第三方線段元件時還連帶釋放了仍在使用的材質,shader 因此每秒重編多次。診斷改為攔截 WebGL 呼叫:clear 的次數約等於幀數,linkProgram 的次數就是 shader 重編次數。drawElements 一幀就有上百次,不適合當指標。
一款產品配置器的場景約有 60 個 draw call、約 100 萬個三角形。把畫面像素比掃過七個值做迴歸,可以把每幀成本拆成固定成本與隨像素成長的成本。桌機每幀約 4 ms,固定成本約占 60%;手機組態每幀約 2.5 ms,固定成本約占 80%。固定成本不會因為降解析度而減少。
- 確認症狀持續卡,還是只在轉場時卡
- 量成本每秒幀數、shader 重編次數、GPU 時間
- 拆成本結構固定成本與隨像素成長的成本
- 只在轉場或切換時卡查動畫時序喚醒時長、相機動畫、補幀順序
- 持續卡,shader 規律重編找出被反覆建立與釋放的材質介面標注不整批重建
- 持續卡,固定成本占大宗幾何減面與降階,draw call 合併繪製拖曳時改用降階模型,靜態件用貼圖圖集
- 持續卡,成本隨像素與疊層成長降低每像素的疊層與材質運算只降解析度不一定有效
預算在專案初期訂,逐項換算
預算要在專案初期談定,像預算表一樣逐項分配。以一個建案看屋網站為例,手機的 Chromium 模擬記憶體約 2.6 GB,目標分兩階段:先降到約 0.9 GB,再往更低的整段流程高點收緊,之後新增的樹、夜景與漸進清晰,都要算進同一份預算。逐項換算如下:
- 解碼 worker 每批載完就關閉,上傳 GPU 後釋放 CPU 端的副本。
- 手機的環境貼圖、陰影、水面鏡面與全景快取,各自降階。
- 貼圖分級由業主決定,手機採 1024 級,桌機依裝置選擇。
- 手機的幾何切成每塊不超過 65,536 個頂點,索引改用 16 位元,位置與法線以整數量化。
功能各自沒事、合起來才爆的情況,只能靠量測找出來。夜景與樹各自在流程的每一步只增加不到 5 MB,同時打開卻每一步跳升約 40 MB,原因是行程的記憶體高水位,而不是兩者相加。決策是手機保留樹、夜景城市只給桌機,業主同意。後來改做只點亮塔樓的手機輕量夜景,長流程的尖峰增量約為零。
第一階段之後,整段流程的記憶體高點約 910 至 960 MB;第二階段之後降到約 510 至 710 MB,單次尖峰約 750 MB,量測雜訊約 ±40 MB。數字來自桌機 Chromium 模擬手機。預算表追的是每一項,而不是一個總數。
首屏下載量是另一張預算。LIDROP 的 3D 配置器案例用固定的量法分輪盤點:建置後在 headless 瀏覽器讀取所有資源請求,依副檔名分類,3D 檔約占 80%。每一輪只動執行期用不到的位元組:第一輪把首屏下載量從約 57 MB 降到約 43 MB,第二輪降到約 37 MB。模型優化前後的對照,另見3D 模型優化前後的下載量對照。
- 盤點前約 57 MB首屏下載量
- 第一輪約 14 MB三項調整,皆為執行期用不到的資料
- 第一輪後約 43 MB首屏下載量
- 第二輪約 6 MB資產端三項調整
- 第二輪後約 37 MB首屏下載量
LIDROP 3D 配置器,同一款;建置後在 headless 瀏覽器讀取資源請求,依副檔名分類
第三輪的起點是另一個版本,把執行期必定被換掉的內嵌底色圖縮成 4×4,座墊貼圖降到 1024,說明資料延後載入,由約 36.5 MB 降到約 32.5 MB,起點版本與前兩輪不同,所以不接成同一條曲線。新增部位時先確認:這張內嵌貼圖在執行期會不會被換掉,會就縮。
另有兩項需要動載入架構:按款拆檔約可省 3.4 MB,四支檔共用同一張貼圖約可省 2.5 MB。

依瓶頸選解法
同一個症狀,解法取決於瓶頸。下表每一列都是實測結果,不是通則。
| 瓶頸 | 有效做法 | 無效或要付代價的做法 |
|---|---|---|
| 幾何、draw call | 以簡化幾何代理鏡面反射,拖曳時用降階模型;合併繪製、貼圖圖集 | 只降解析度,固定成本不減 |
| 填充與材質運算 | 降低每像素的疊層;能預先算好的光影離線渲染成貼圖 | 把解析度永久壓低:變糊,沒有更快 |
| shader 反覆重編 | 避免整批重建介面標注,仍在使用的材質不釋放 | 調整動畫時序,對持續卡頓無效 |
| 一次性成本 | 照時間預算分幀建立,每幀最多 2 ms,近鏡頭的先建 | 一次建完上百個物件,單格卡約 50 至 100 ms |
幾何受限的例子,用 GPU timer query 把主繪製與鏡面繪製的 GPU 時間分開量,鏡面繪製約 1.1 至 1.2 ms,改用簡化幾何代理後降到 0.2 ms 以下(桌機 headless、手機尺寸視窗,只信交錯比值)。離線渲染的例子,把環境預先渲成全景與近地面貼圖,手機層 GPU 的兩個繪製合計由約 8.1 ms 降到約 4.7 ms,代價是地面積水處的產品倒影預設拿掉,這類取捨事前列給客戶決定。
填充受限的例子,是一個高斯潑濺(3DGS)掃描場景:量到平均重疊約 180 層,健康值約 5 至 15 層,減少高斯數量有效,只降解析度沒有變快。鏡頭移動時降頻的例子,來自一個活動地圖網站:模擬手機下倒影更新由每秒 60 次降到 30 次,拖曳時每幀的 JavaScript 時間由約 8.5 ms 降到約 6.5 ms。
降解析度只在瓶頸是像素時有效
降解析度換流暢是常見做法,有效與否取決於瓶頸,而且每次切換本身有成本。一款配置器的實測,像素降到約 36%,桌機每幀時間只少約 25%,手機組態只少約 15%,因為固定成本占大宗。每次改解析度還要重新配置繪圖緩衝,一降一升在桌機約 20 ms、手機約 10 ms;損益兩平在桌機要連續拖曳約 0.4 秒,手機永遠不會平。所以該配置器只在載入畫面擋著時降解析度,互動時不降。另一個產品的瓶頸在材質的片段著色,像素就是成本所在,手機拖曳因此固定使用較低的像素比。
壓縮格式的答案會隨網速反轉
Khronos 的 EXT_meshopt_compression 擴充描述另一套幾何壓縮格式,重點是快速解碼(Kapoulkine 等,Khronos)。KTX2 搭配 Basis Universal 的貼圖,由引擎轉碼成平台支援的區塊壓縮格式(Callow 等,2020)。兩份規格都沒有給量化的節省數字,要省多少需要自己量。
以建模師的原始檔為基準,轉成 meshopt 後檔案平均變大 1.5 至 2.3 倍,所以編碼要依首次進站的體感重算。同一個輪圈模型,draco 下載約 3.8 MB、解碼約 1.2 秒,meshopt 下載約 6.4 MB、解碼約 0.8 秒;下載加解碼合計,約 46 Mbps 以下 draco 較快,以上 meshopt 較快,100 Mbps 時已是 meshopt 較快。這組數字用來說明交叉點存在,實際交叉點隨裝置與網路而異。
- 約 26 MBmeshopt約 52 MB
- 約 16 MB純 draco約 97 MB
- 約 21 MB量化後再 draco定案約 52 MB
LIDROP 首屏 7 支模型檔的合計;與整頁首屏下載量是不同的量法
純 draco 的檔案最小,但解碼成完整精度的浮點數,GPU 上的幾何近 97 MB;先量化再 draco,下載與 GPU 兩者兼得,成為預設。比較必須從原始檔出發:把已經是 meshopt 的檔轉回 draco,檔案反而變大 71%。
載入順序:先顯示,再補畫質
載入慢常常不是檔案太大,而是等待的順序不對。常見的寫法是等整個產品(約 80 至 100 MB)都載完才拿掉載入畫面。改法是把揭幕條件改成兩個主體與六類關鍵部件各自就緒,非關鍵部件在揭幕後再補。接著在 index.html 預抓關鍵 GLB 與解碼器,因為 JavaScript 還在解析、部件清單的 API 還沒回應的那段時間,網路原本是閒置的。20 Mbps 下,解碼器到位時間由約 12 至 13 秒降到約 6.5 至 7.4 秒。預抓有兩條不能踩的線:
- as=fetch 必須搭配 crossorigin=anonymous,沒配上會下載兩次,比不預抓更糟。
- 預抓清單若有兩份(HTML 與程式常數),不同步只會白抓,而且不會出任何錯誤。
揭幕等首屏的整組資產時,首屏時間在滿載的線路上幾乎等於位元組除以頻寬。以 20 Mbps 節流為例,首屏約 35 MB,載入畫面約 15.9 秒消失;以每秒約 2.5 MB 計,下載約 14 秒。調整請求順序後約 15.8 秒,差距落在雜訊內,有效的槓桿只有揭幕前少下載。
畫質要求高的產品,載入拆成兩段:每個配色先載輕量版,內含幾何、2048 的底色,以及 1024 的法線與材質參數貼圖,約 10.7 MB,載入畫面只等這一份;高清貼皮在背景並行抓取、轉碼、換上。8K 貼皮一次上傳約 89 MB,桌機會卡約 69 ms,因此改成約 1 MB 的切片,每幀最多花 4 ms。
量測採本機正式包、冷快取、節流、每格取三次中位數、真 GPU 的 headless。手機以 10 Mbps 連線,產品出現時間由約 24 秒降到約 12 秒;桌機首次總下載量多約 4 MB;升級完成後的截圖與一次載完的畫面逐像素相同。另存為 WebP 的小貼皮只讓產品早出現約 0.35 秒,暫時的 GPU 佔用卻從約 10 MB 升到約 35 MB,法線細紋整片消失,因此不採用。
進場前看不到的東西,一律不擋第一次互動。一個活動地圖網站在慢速手機網路上,三座島的模型(共約 2.5 MB)延到可互動之後才載,島先以外殼佔位;可互動之前不下載之後才看得到的圖;倒數頁不載 3D 的 JavaScript。模擬手機的慢速 4G 下,可互動時間由約 60 秒降到約 48 秒,第二批調整後再降到約 41 秒。
可互動之前
- 主場景與關鍵部件揭幕條件只等這些
- 島的外殼位置靠常數,模型未到先佔位
- 第一屏看得到的圖版面以寬高佔位
可互動之後
- 三座島的模型共約 2.5 MB,到了才換上並淡入
- 之後才看得到的圖可互動之前不給網址
- 不需要 3D 的頁面倒數頁不載 3D 的 JavaScript
不擋第一次互動看不到的東西一律延後,使用者能操作之後再逐一補上
一個活動地圖網站,模擬手機慢速 4G 下的調整
驗收看可重現的數字
驗收看的是可重現的數字,而不是一段錄影。每一格寫明條件:目標機型、網路節流、快取狀態,以及取幾次的中位數。機器同時有其餘負載時,單次量測會飄動約 2 ms,所以只信交錯執行的比值。驗收分四欄:
- 載入:產品第一次出現的時間與首屏下載量,依機型與網速各一格。
- 記憶體:整段流程的高點與尖峰,同一份建置只切換功能旗標比較。
- 每幀:拖曳與縮放時的每幀時間,與 shader 重編次數。
- 畫質:升級後的截圖與基準逐像素比對。
實機驗證是獨立的一格。本文的數字大多來自桌機環境的模擬或 headless 量測,沒有註明實機的就不是實機數字。量測誤差的來源與可信的量法,另見3D 效能數字的量測誤差與可信量法。3D 網站開發的完整範圍見3D 網站開發服務。
同一套方法放進實際的購買路徑,見建案 3D 看屋的路徑與訂製招牌的實景預覽。
分層載入用在 3D 世界地圖的做法,見線上博覽會的前端做法。
不適合的情況
- 內容沒有互動需求:影片就夠。
- 目標裝置很舊,預算又不允許分級:不同裝置給不同品質,是預算表能成立的前提。
- 決策者只想看漂亮畫面,不願意為手機取捨:預算表的每一格都是取捨,需要有人拍板。
評估前的準備
評估開始前,需要準備四項資料:
- 目標機型清單:最舊要支援到哪一款,決定預算怎麼訂。
- 首屏要出現的素材:決定載入預算的基準。
- 現有的模型檔:用來從原始檔重新量測。
- 現有版本的頁面網址:用來量第一輪基線。
資料備齊後,可以洽詢 3D 網站的效能評估。




