You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为外部.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组件,有两种修改方式:

  1. 批量修改所有材质
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>
  )
}
  1. 单独修改某个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:32:49