如何为外部.glb模型设置THREE.BackSide属性?
给GLB模型设置
THREE.BackSide的解决方法 一、使用<primitive>加载模型时的处理方式
直接通过traverse遍历模型所有节点,找到Mesh后修改材质的side属性:
import { useGLTF } from '@react-three/drei' import { useEffect, useRef } from 'react' import * as THREE from 'three' export default function RoomModel() { const gltf = useGLTF('/room.glb') const sceneRef = useRef<THREE.Object3D>(null) useEffect(() => { sceneRef.current?.traverse((obj) => { if (obj instanceof THREE.Mesh) { // 处理单材质或多材质数组的情况 if (Array.isArray(obj.material)) { obj.material.forEach(mat => { mat.side = THREE.BackSide mat.needsUpdate = true }) } else { obj.material.side = THREE.BackSide obj.material.needsUpdate = true } } }) }, [gltf]) return <primitive ref={sceneRef} object={gltf.scene} /> }
二、使用gltfjsx生成的JSX组件时的处理方式
gltfjsx会把模型拆分为独立的Mesh组件,有两种修改方式:
- 批量修改所有材质
import { useGLTF } from '@react-three/drei' import { useEffect } from 'react' import * as THREE from 'three' // gltfjsx生成的Room组件 export default function Room(props: JSX.IntrinsicElements['group']) { const { nodes, materials } = useGLTF('/room.glb') useEffect(() => { // 遍历所有材质,统一设置BackSide Object.values(materials).forEach(mat => { mat.side = THREE.BackSide mat.needsUpdate = true }) }, [materials]) return ( <group {...props} dispose={null}> <mesh geometry={nodes.Wall.geometry} material={materials.WallMaterial} /> <mesh geometry={nodes.Floor.geometry} material={materials.FloorMaterial} /> </group> ) }
- 单独修改某个Mesh的材质
直接在对应mesh标签中覆写材质属性:
<mesh geometry={nodes.Wall.geometry} material={{...materials.WallMaterial, side: THREE.BackSide, needsUpdate: true}} />
三、通用复用的自定义Hook
可以封装一个Hook来复用遍历设置逻辑:
import { useEffect, useRef } from 'react' import * as THREE from 'three' export function useSetBackSide(ref: React.RefObject<THREE.Object3D>) { useEffect(() => { const updateSide = (obj: THREE.Object3D) => { if (obj instanceof THREE.Mesh) { if (Array.isArray(obj.material)) { obj.material.forEach(mat => { mat.side = THREE.BackSide mat.needsUpdate = true }) } else { obj.material.side = THREE.BackSide obj.material.needsUpdate = true } } } ref.current?.traverse(updateSide) }, [ref]) }
使用示例:
const sceneRef = useRef<THREE.Object3D>(null) useSetBackSide(sceneRef) return <primitive ref={sceneRef} object={gltf.scene} />
注意事项
- 若修改后未生效,务必设置
material.needsUpdate = true,强制Three.js更新材质缓存 - TypeScript环境下,必须通过
obj instanceof THREE.Mesh做类型判断,避免类型报错
内容的提问来源于stack exchange,提问作者naeemgg
相关产品推荐
相关产品推荐

