欢迎光临
我们一直在努力

超大规模 3D 仓储:基于 Three.js + WebGPU 的性能优化实践

一、 场景痛点:浏览器里的“幻灯片”

在最近交付的一个 AS/RS 立体仓库数字孪生项目中,我们遇到了严重的性能墙:

  • 规模:仓库有 50 排货架,总计 52,000 个货位,每个货位上可能放着不同颜色的箱子。

  • 现状:开发团队使用 Three.js 传统的 new THREE.Mesh() 方法,循环创建了 5 万个 Cube 对象。

  • 灾难:

  • Draw Calls 爆炸:GPU 绘制调用次数超过 50,000 次,远超浏览器瓶颈(通常 3000 次就开始卡)。

  • FPS 暴跌:在 i7 的开发机上只有 8 FPS,在现场的中控大屏(通常配的是集显 Mini PC)上直接浏览器崩溃(WebGL Context Lost)。

  • 交互延迟:点击一个箱子查看详情,需要 2 秒才有反应。

  • 架构师指令:停止使用独立 Mesh。

    对于这种“形状相同、位置不同”的大规模物体,必须使用 InstancedMesh (实例化网格) 技术。将 5 万次绘制合并为 1 次绘制,利用 GPU 的并行计算能力更新位置和颜色。


    二、 架构设计:数据驱动的实例化管道

    我们采用 React Three Fiber (R3F) 作为胶水层,结合 WebGPU 计算着色器(可选)处理状态更新。

  • 渲染层:使用单个 InstancedMesh 承载所有货箱。内存中只存一份 Geometry(几何体)和 Material(材质)。

  • 数据层:不使用 React State 存储实时位置(太慢)。使用 Refs 直接操作 ArrayBuffer(类型化数组)。

  • 通信层:WebSocket 接收 WMS 的库存变动指令(如 Slot_A1_02: { status: empty }),直接修改 Buffer 中的颜色矩阵。

  • 渲染管线:

    WMS 数据流 -> [WebSocket Worker] -> [SharedArrayBuffer] -> [Three.js InstancedMesh] -> GPU


    三、 核心实施步骤 (Copy & Paste)

    这里演示如何用 React Three Fiber 实现 5 万个动态货箱的渲染。

    1. 创建实例化网格组件 (InstancedBoxes.jsx)

    核心在于 useLayoutEffect 中对 tempObject 的复用,以及 setColorAt / setMatrixAt 的调用。

    Jsx

    import React, { useRef, useLayoutEffect, useMemo } from 'react'
    import * as THREE from 'three'
    import { useFrame } from '@react-three/fiber'

    const COUNT = 50000; // 5万个货位

    export default function WarehouseBoxes({ dataStream }) {
      const meshRef = useRef();
      const colorArray = useMemo(() => new Float32Array(COUNT * 3), []);
      
      // 临时对象,用于计算矩阵,避免 GC
      const tempObject = new THREE.Object3D();
      const tempColor = new THREE.Color();

      useLayoutEffect(() => {
        // 1. 初始化位置 (只执行一次)
        let i = 0;
        for (let x = 0; x < 100; x++) {
          for (let y = 0; y < 50; y++) {
            for (let z = 0; z < 10; z++) {
              const id = i++;
              tempObject.position.set(x * 1.2, y * 1.2, z * 1.5);
              tempObject.updateMatrix();
              meshRef.current.setMatrixAt(id, tempObject.matrix);
              
              // 初始化颜色 (空位为灰色)
              meshRef.current.setColorAt(id, tempColor.setHex(0xaaaaaa));
            }
          }
        }
        meshRef.current.instanceMatrix.needsUpdate = true;
        meshRef.current.instanceColor.needsUpdate = true;
      }, []);

      // 2. 实时更新 (每帧调用,或者在 WebSocket 回调中调用)
      useFrame(() => {
        if (!dataStream.current.hasUpdate) return;
        
        // 假设 dataStream 包含需要变更的 ID 和颜色
        dataStream.current.updates.forEach(({ id, status }) => {
          const color = status === 'occupied' ? 0xffa500 : 0xaaaaaa;
          meshRef.current.setColorAt(id, tempColor.setHex(color));
        });
        
        // 关键:告诉 GPU 颜色数据变了,需要重绘
        if (dataStream.current.updates.length > 0) {
           meshRef.current.instanceColor.needsUpdate = true;
           dataStream.current.clear();
        }
      })

      return (
                          )
    }

    2. WebGPU 优化 (进阶)

    如果 2026 年你的目标浏览器支持 WebGPU(Chrome 130+),可以使用 WebGPURenderer 和 Compute Shader 来处理粒子的物理运动(如 AGV 的平滑移动),将 CPU 彻底解放。

    注:Three.js TSL (Three Shading Language) 是 2026 年操作 WebGPU 的标准方式。


    四、 踩坑复盘 (Red Flags)

    1. 交互检测 (Raycasting) 的性能黑洞

    • BVH 优化:引入 three-mesh-bvh 库,为 InstancedMesh 构建空间索引,将射线检测速度提升 1000 倍。

    • 节流:不要在 mousemove 里每帧都做检测,限制为 100ms 一次。

    • 现象:渲染很快,但鼠标一移上去想看货位信息,画面就卡顿。

    • 原因:Three.js 默认的 Raycaster 会遍历所有 50,000 个实例进行碰撞检测,CPU 算不过来。

    • 对策:

    2. 视锥体剔除 (Frustum Culling) 失效

    • 现象:当摄像机只看仓库的一个角落时,GPU 依然在渲染背后的 4 万个箱子。

    • 原因:InstancedMesh 默认被视为一个整体对象。只要这个整体有一部分在屏幕内,整个对象都会被提交给 GPU。

    • 对策:如果仓库极大,需进行空间分块 (Spatial Partitioning)。将 5 万个箱子拆分成 10 个 InstancedMesh(每个 5000 个),分布在不同区域。这样 Three.js 就能自动剔除看不见的区域块。

    3. 内存泄漏 (Geometries Not Disposed)

    • 风险:在 React 中频繁切换场景(如从“仓库视图”切到“产线视图”)导致内存暴涨。

    • 对策:确保在组件卸载(Unmount)时调用 geometry.dispose() 和 material.dispose()。使用 R3F 的


    五、 关联资源与选型

    跑得动 5 万个 3D 物体,对显卡和 CPU 还是有一定要求的。

    • Intel Core Ultra 5 / AMD Ryzen 8000:核显性能强劲,完全能胜任这种轻量级 3D 渲染,无需独显。

    • 推荐工控机配置:

    开发工具:

    • React Three Fiber (R3F):工业 3D 开发首选,组件化管理极佳。

    • Drei:R3F 的生态库,提供了现成的 Instances 组件,比手写原生代码更简单。

    赞(0)
    未经允许不得转载:171主机测评 » 超大规模 3D 仓储:基于 Three.js + WebGPU 的性能优化实践
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址