ThreeJS门模型相机移动时出现透明渲染伪影问题求助
ThreeJS门把手相机移动时出现透明伪影问题解决
我正在开发一个ThreeJS应用,用RoundedBoxGeometry制作门、STL模型制作门把手,现在遇到问题:鼠标移动相机时,渲染出现伪影,模型部分区域变为透明,效果极差。
正常门把手效果:
相机移动后的异常效果:
初始化代码
//* Renderer this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas, antialias: true }); this.renderer.shadowMap.enabled = true; this.renderer.setPixelRatio(devicePixelRatio); this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight); //* Scene this.scene = new THREE.Scene(); this.scene.background = new THREE.Color(0x1f1f1f); //* textures const textureLoader = new THREE.TextureLoader(); this.doorTexure = textureLoader.load('./assets/3d/textures/steal.png'); this.doorTexure.wrapS = THREE.RepeatWrapping; this.doorTexure.wrapT = THREE.RepeatWrapping; this.doorTexure.repeat.set(7, 7); this.handlerTexure = textureLoader.load('./assets/3d/textures/steal.png'); //* Handler const loaderSTL = new STLLoader() loaderSTL.load('./assets/3d/test.stl', geometry => { this.handlerMaterial = new THREE.MeshPhongMaterial({ color: 0x222222, specular: 0xFFFFFF, shininess: 250, map: this.handlerTexure }); this.handlerMesh = new THREE.Mesh(geometry, this.manigliaMaterial); this.handlerMesh.castShadow = true; this.handlerMesh.receiveShadow = true; this.scene.add(this.handlerMesh); }); //* Door this.doorMesh = new THREE.Mesh(); this.doorMesh.receiveShadow = true; this.scene.add(this.doorMesh); this.doorMaterial = new THREE.MeshPhongMaterial({ map: this.doorTexure }); this.doorMesh.material = this.doorMaterial; //* Camera this.camera = new THREE.PerspectiveCamera(1, this.canvas.clientWidth / this.canvas.clientHeight, 0.1, 10000000); this.camera.position.x = 100; this.camera.position.y = 100; this.camera.position.z = 5000; //* Lights const light1 = new THREE.DirectionalLight(0xffffff, 5); light1.castShadow = true; light1.position.set(-10, 10, 12); this.scene.add(new THREE.DirectionalLightHelper(light1, 5)); this.scene.add(light1); const light2 = new THREE.DirectionalLight(0x999999, 1); light2.position.set(10, 10, 10); this.scene.add(new THREE.DirectionalLightHelper(light2)); this.scene.add(light2); const light3 = new THREE.DirectionalLight(0x999999, 1); light3.position.set(10, 10, -10); this.scene.add(new THREE.DirectionalLightHelper(light3)); this.scene.add(light3); //* Axes helper const axesHelper = new THREE.AxesHelper(30); this.scene.add(axesHelper);
用户修改门宽高时的更新代码
// Door this.doorMesh.geometry = new RoundedBoxGeometry(this.door.width / 10, this.door.height / 10, 2, 6, 0.21); this.doorMaterial.color = new THREE.Color(this.door.color); // Handler this.handlerMesh.scale.set(this.handler.width / 2500, this.hanlder.height / 2500, 0.05); this.handlerMesh.position.x = this.handler!.x / 100; this.handlerMesh.position.y = this.handler.y / 100; this.handlerMesh.position.z = 2;
解决思路
- 修复材质赋值拼写错误
初始化代码中创建handlerMaterial后,赋值给handlerMesh时误用了this.manigliaMaterial,导致材质未正确应用。修正为:
this.handlerMesh = new THREE.Mesh(geometry, this.handlerMaterial);
- 缩小相机远裁剪面范围
相机far值设为10000000过大,会导致深度精度不足,引发Z-fighting(深度冲突)。调整为合理值:
this.camera = new THREE.PerspectiveCamera(1, this.canvas.clientWidth / this.canvas.clientHeight, 0.1, 1000);
- 计算STL模型法线
STL模型可能存在法线缺失或方向错误,导致面被错误剔除。加载后手动计算法线:
loaderSTL.load('./assets/3d/test.stl', geometry => { geometry.computeVertexNormals(); // 其余代码保持不变 });
- 避免几何体内存泄漏与渲染异常
更新门几何体时,先销毁旧几何体再创建新的:
if (this.doorMesh.geometry) { this.doorMesh.geometry.dispose(); } this.doorMesh.geometry = new RoundedBoxGeometry(this.door.width / 10, this.door.height / 10, 2, 6, 0.21);
- 调整门把手Z轴位置避免重叠
门把手Z轴缩放后与门的厚度重叠,引发Z-fighting,将位置微调至门前方:
this.handlerMesh.position.z = 2.01;
内容的提问来源于stack exchange,提问作者user3471528
相关产品推荐
相关产品推荐

