gltfjsx导入React模型后,如何缩放无缝纹理?
解决gltfjsx+React中纹理repeat/offset/wrap属性无效的问题
直接通过material-map传递useTexture返回的纹理对象时,无法自动应用repeat、offset等属性——因为GLTF材质默认的纹理包裹模式是ClampToEdgeWrapping,且纹理属性需要显式修改并通知Three.js更新。以下是正确的实现方式:
步骤1:加载并修改纹理属性
先通过useTexture加载所有纹理,再用useEffect设置纹理的包裹模式、重复次数和偏移量,最后标记纹理需要更新:
import { useTexture, useEffect } from '@react-three/fiber'; import * as THREE from 'three'; // 组件内部逻辑 const baseColor = useTexture("Gravel_001_BaseColor.jpg"); const roughnessMap = useTexture("Gravel_001_Roughness.jpg"); const normalMap = useTexture("Gravel_001_Normal.jpg"); const aoMap = useTexture("Gravel_001_AmbientOcclusion.jpg"); useEffect(() => { // 处理基础颜色纹理 if (baseColor) { baseColor.wrapS = THREE.RepeatWrapping; baseColor.wrapT = THREE.RepeatWrapping; baseColor.repeat.set(4, 4); // 设置x、y方向重复次数 baseColor.offset.set(0.1, 0.1); // 设置纹理偏移量 baseColor.needsUpdate = true; // 通知Three.js更新纹理状态 } // 处理粗糙度纹理(其他纹理同理) if (roughnessMap) { roughnessMap.wrapS = THREE.RepeatWrapping; roughnessMap.wrapT = THREE.RepeatWrapping; roughnessMap.repeat.set(4, 4); roughnessMap.needsUpdate = true; } // 同理处理法线贴图和环境遮挡贴图 if (normalMap) { normalMap.wrapS = THREE.RepeatWrapping; normalMap.wrapT = THREE.RepeatWrapping; normalMap.repeat.set(4, 4); normalMap.needsUpdate = true; } if (aoMap) { aoMap.wrapS = THREE.RepeatWrapping; aoMap.wrapT = THREE.RepeatWrapping; aoMap.repeat.set(4, 4); aoMap.needsUpdate = true; } }, [baseColor, roughnessMap, normalMap, aoMap]);
步骤2:将修改后的纹理传递给Mesh
把处理好的纹理对象传给mesh的材质属性即可:
<mesh geometry={nodes.BON_GRAVA.geometry} material={materials.BON_GRAVA} material-map={baseColor} material-metalness={0.0} material-roughness={1.0} material-roughnessMap={roughnessMap} material-normalMap={normalMap} material-aoMap={aoMap} />
关键说明
- 必须将纹理的
wrapS和wrapT设置为THREE.RepeatWrapping,否则repeat属性不会生效(默认是ClampToEdgeWrapping,纹理会被拉伸而非重复)。 - 修改纹理属性后要设置
needsUpdate = true,确保Three.js重新渲染纹理。 - 所有需要重复的纹理(基础色、粗糙度、法线等)都要单独设置,因为它们是独立的纹理对象。
内容的提问来源于stack exchange,提问作者Ana
相关产品推荐
相关产品推荐

