为什么我在Three.js中无法将纹理正常映射到3D物体上?
问题原因
- 你加载的
WaltHeadLo_buffergeometry.json头部模型未预配置UV映射属性:UV坐标是实现纹理与3D模型顶点一一对应的必要参数,缺失时ThreeJS会默认所有顶点使用同一UV取值,最终仅呈现纹理平均色。 MeshStandardMaterial的color参数设置为灰色0xcccccc,会与纹理色彩叠加导致纹理整体偏暗,无法正常显示原图效果。
修复方案
在模型加载的成功回调中,先为无UV属性的模型手动生成UV坐标,再将材质基础色改为纯白色即可。你也可以根据需求调整纹理的重复参数,适配模型显示效果。
修复后完整JS代码
import * as THREE from 'https://threejs.org/build/three.module.js'; import { OrbitControls } from 'https://threejs.org/examples/jsm/controls/OrbitControls.js'; var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(45, 4 / 3, .1, 500) camera.position.set(240, 240, 240); camera.lookAt(scene.position); var renderer = new THREE.WebGLRenderer(); renderer.setClearColor(0xdddddd); renderer.setSize(800, 600); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; var tl = new THREE.TextureLoader(); var texture = tl.load('https://threejs.org/examples/models/json/lightmap/rocks.jpg'); // 可选:配置纹理重复模式 texture.wrapS = THREE.RepeatWrapping; texture.wrapT = THREE.RepeatWrapping; texture.repeat.set(2, 2); // 可自行调整重复次数 const loader = new THREE.BufferGeometryLoader(); loader.load( 'https://threejs.org/examples/models/json/WaltHeadLo_buffergeometry.json', function (geometry) { // 新增:手动生成UV坐标 if (!geometry.hasAttribute('uv')) { geometry.computeBoundingBox(); const box = geometry.boundingBox; const size = new THREE.Vector3(); box.getSize(size); const position = geometry.attributes.position; const uvs = new Float32Array(position.count * 2); for (let i = 0; i < position.count; i++) { // 基于模型X、Y轴归一化生成UV,可根据需求更换映射轴 const x = (position.getX(i) - box.min.x) / size.x; const y = (position.getY(i) - box.min.y) / size.y; uvs[i * 2] = x; uvs[i * 2 + 1] = y; } geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2)); } // 修改:color改为纯白色避免覆盖纹理色彩 var material = new THREE.MeshStandardMaterial({ color: 0xffffff, map: texture }); var object = new THREE.Mesh(geometry, material); object.name = "head"; scene.add(object); }, function (xhr) { console.log('loaded'); }, function (err) { console.log('An error happened'); } ); var spotLight1 = new THREE.SpotLight(0xffffff); spotLight1.name = "SpotLight1"; spotLight1.position.set(150, 300, 500); spotLight1.castShadow = true; scene.add(spotLight1); var canvas = document.getElementById("canvas"); canvas.appendChild(renderer.domElement); renderer.render(scene, camera); const controls = new OrbitControls(camera, renderer.domElement); animate(); function animate() { requestAnimationFrame(animate); controls.update(); renderer.render(scene, camera); }
HTML代码无需修改
<html> <body> <div id="canvas" width="800px" height="600px"></div> </body> </html>
内容的提问来源于stack exchange,提问作者Mehmet Emre Özer
相关产品推荐
相关产品推荐

