ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

React Three Fiber 如何为单个 mesh 通过 attach 分配多个材质?

2026/9/10 17:22:25 拓冰建站 浏览量
React Three Fiber 如何为单个 mesh 通过 attach 分配多个材质? React Three Fiber 如何为单个 mesh 通过 attach 分配多个材质【免费下载链接】react-three-fiber A React renderer for Three.js项目地址: https://gitcode.com/GitHub_Trending/re/react-three-fiber在 React Three Fiber 中一个mesh默认只能挂一个材质所有继承自THREE.Material的子组件会被自动推断为attachmaterial也就是说第二个meshBasicMaterial会直接覆盖第一个而不是追加。要让同一个 mesh 使用多个材质multi-material需要利用attach的数组下标语法attachmaterial-N把每个材质显式绑定到mesh.material数组的指定位置。本文基于仓库文档 docs/API/objects.mdx 和官方示例 example/src/demos/MultiMaterial.tsx给出写法、动态增删材质的处理方式以及在示例应用中核对结果的方法。attach 与数组下标多个材质为什么不能直接并列attach用来把子对象绑定到父对象的某个属性上子对象卸载时会自动从父对象上摘除。单个材质和几何体可以省略attachmesh meshBasicMaterial attachmaterial / boxGeometry attachgeometry / /mesh文档说明所有继承THREE.Material的对象自动获得attachmaterial所有继承THREE.BufferGeometry的对象自动获得attachgeometry。但多个材质对应的是父对象上的数组属性文档给出的数组 attach 语法是attacha-0表示绑定到foo.a[0]并且明确要求Arrays must have explicit order, for instance multi-materials数组必须有显式顺序例如 multi-materials。因此多材质必须逐个写死下标mesh meshBasicMaterial attachmaterial-0 colorhotpink / meshBasicMaterial attachmaterial-1 colorlightgreen / /meshattachmaterial-0最终把材质写到mesh.material[0]。如果只写attachmaterial放多个子组件后出现的会整体替换先出现的。基础写法静态多材质 mesh官方 demoTestMultiMaterialexample/src/demos/MultiMaterial.tsx给一个boxGeometrymesh 分配了 6 个材质是仓库中最完整的参考function TestMultiMaterial(props: ThreeElements[mesh]) { const ref useRefTHREE.Mesh(null!) const [okay, setOkay] useState(true) useEffect(() { const interval setInterval(() setOkay((okay) !okay), 1000) return () clearInterval(interval) }, []) useEffect(() { console.log(ref.current.material) }, [okay]) return ( mesh ref{ref} {...props} boxGeometry args{[0.75, 0.75, 0.75]} / meshBasicMaterial attachmaterial-0 colorhotpink toneMapped{false} / meshBasicMaterial attachmaterial-1 colorlightgreen toneMapped{false} / {okay ? ( meshBasicMaterial attachmaterial-2 colorlightblue toneMapped{false} / ) : ( meshNormalMaterial attachmaterial-2 / )} meshBasicMaterial attachmaterial-3 colorpink toneMapped{false} / meshBasicMaterial attachmaterial-4 colororange toneMapped{false} / meshBasicMaterial attachmaterial-5 colorlavender toneMapped{false} / /mesh ) }注意material-2是条件渲染okay每秒翻转一次下标 2 的材质在meshBasicMaterial和meshNormalMaterial之间替换但始终挂在同一个material-2位置上其余下标不受影响。动态数量的材质用 key 配合索引渲染当材质数量来自数据而不是写死时docs/API/objects.mdx 给出的模式是用map配合key和模板字符串下标colors是你自己的颜色数组mesh {colors.map((color, index) meshBasicMaterial key{index} attach{material-${index}} color{color} /)} /meshkey{index}保证 React 在列表增删时能正确复用或卸载对应下标的材质组件。卸载某个下标的材质时会发生什么同文件的TestMultiDelete演示了条件卸载{okay meshBasicMaterial attachmaterial-2 ... /}即下标 2 的材质周期性地从 mesh 上摘除再挂回。下标 attach 的挂载与卸载行为由 packages/fiber/tests/utils.test.ts 的用例 should create array when using array-index syntax 断言对prop-0执行 attach 后parent.object.prop变为[child]数组是自动创建的detach 后数组长度保持为 1被摘除的下标置为undefined。也就是说摘除一个材质不会收缩整个数组其他下标的材质保持原位这正是上面 demo 中只替换/摘除 material-2能稳定工作的前提。另外 packages/fiber/tests/renderer.test.tsx 中 can swap 4 array primitives via attach 用例验证了下标 attach 的顺序语义按userData-objects-${i}挂载 4 个对象后数组顺序与渲染顺序一致后续即使渲染顺序被反转或打乱各下标仍绑定到正确的对象。在示例应用中运行并核对仓库根目录 package.json 提供examples脚本即yarn workspace example dev底层是 Vite。示例应用依赖 React 19.2.0、three ^0.172.0见 example/package.json。在仓库根目录安装依赖yarn启动示例应用yarn examples浏览器打开 Vite 输出的本地地址访问路由/demo/MultiMaterial。example/src/App.tsx 中 wouter 的/demo/:name路由会把路径参数映射到 example/src/demos/index.tsx 中注册的同名 demo页面左侧的圆点面板也可以直接点选MultiMaterial。核对方式由 demo 自身实现TestMultiMaterial和TestMultiDelete组件通过useRefTHREE.Mesh拿到 mesh 实例在okay状态翻转时执行console.log(ref.current.material)。打开浏览器控制台每秒会打印一次mesh.material的当前值——多材质 mesh 上它是一个包含多个材质对象的数组且下标 2 的内容在两次渲染之间交替变化画面中对应的盒子 mesh 会呈现多种颜色。如果不想跑浏览器仓库根的yarn test执行jest --coverage会运行上述 attach 相关断言可直接核对数组下标挂载与 detach 的行为。边界与替代写法顺序必须显式数组下标 attach 不支持自动排序下标不连续如只有material-0和material-2时会得到中间含空位的稀疏数组空位行为以上述测试为准。attach 函数形式文档还允许把attach写成(parent, self) ...并返回清理函数用于显式parent.add(self)/parent.remove(self)的场景multi-material 数组场景不需要它这里仅作了解。卸载即摘除任何attach挂上去的对象在 React 卸载时自动从父对象移除无需手动清理材质、几何体等对象卸载时 R3F 会调用object.dispose()释放资源如果材质来自外部缓存且不想自动释放可以在父容器上设置dispose{null}。写完后如果某个下标的材质不生效先按文档核对两点材质子组件是否确实写在mesh内部attach只作用于父对象以及是否误写成attachmaterial那样会整体替换数组而不是填入下标。【免费下载链接】react-three-fiber A React renderer for Three.js项目地址: https://gitcode.com/GitHub_Trending/re/react-three-fiber创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考