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

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;

解决思路

  1. 修复材质赋值拼写错误
    初始化代码中创建handlerMaterial后,赋值给handlerMesh时误用了this.manigliaMaterial,导致材质未正确应用。修正为:
this.handlerMesh = new THREE.Mesh(geometry, this.handlerMaterial);
  1. 缩小相机远裁剪面范围
    相机far值设为10000000过大,会导致深度精度不足,引发Z-fighting(深度冲突)。调整为合理值:
this.camera = new THREE.PerspectiveCamera(1, this.canvas.clientWidth / this.canvas.clientHeight, 0.1, 1000);
  1. 计算STL模型法线
    STL模型可能存在法线缺失或方向错误,导致面被错误剔除。加载后手动计算法线:
loaderSTL.load('./assets/3d/test.stl', geometry => {
  geometry.computeVertexNormals();
  // 其余代码保持不变
});
  1. 避免几何体内存泄漏与渲染异常
    更新门几何体时,先销毁旧几何体再创建新的:
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);
  1. 调整门把手Z轴位置避免重叠
    门把手Z轴缩放后与门的厚度重叠,引发Z-fighting,将位置微调至门前方:
this.handlerMesh.position.z = 2.01;

内容的提问来源于stack exchange,提问作者user3471528

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:37:03