Three.js开发中遇到的常见问题总结和性能优化

关于Three.js开发中遇到的一些问题总结

1.加载外部模型文件无法在场景中显示:

(1) 确保当前文件内容是否能被读取,在Javascript的console中查找错误,并确定当你调用.load()的时候,使用了onError回调函数来输出结果, 如果err 输出则表示当前glb 文件内容无法被读取从新换一个glb文件尝试

javascript 复制代码
	const loader = new GLTFLoader()
	loader.load('/three/1.glb', (result) => {
			 console.log(result)
			}, () => {
			}, (err) => {
				console.log(err)
		})

(2) 尝试将模型放大缩小到原来的1000倍。许多模型的缩放比例各不相同,如果摄像机位于模型内,则大型模型将可能不会显示。或者可以在模型加载完成之后根据模型比例大小设置合适的缩放值

javascript 复制代码
		//设置模型位置
		this.model.updateMatrixWorld()
		const box = new THREE.Box3().setFromObject(this.model);
		const size = box.getSize(new THREE.Vector3());
		const center = box.getCenter(new THREE.Vector3());
		// 计算缩放比例
		const maxSize = Math.max(size.x, size.y, size.z);
		const targetSize = 2.5; // 目标大小
		const scale = targetSize / (maxSize > 1 ? maxSize : .5);
		this.model.scale.set(scale, scale, scale)
	     // 设置控制器最小缩放值
		this.controls.maxDistance = size.length() * 10
		// 设置相机位置
		this.camera.position.set(0, 2, 6)
		// 设置相机坐标系
		this.camera.lookAt(center)
		this.camera.updateProjectionMatrix();

(3)增加相机远端面的值 far,如果在创建相机时摄像机视锥体远端面的值设置过小也无法蒋模型正确的显示出来

javascript 复制代码
this.camera = new THREE.PerspectiveCamera(45, clientWidth / clientHeight, 0.25, 100)
this.camera.far = 2000
this.camera.updateProjectionMatrix()

(4) 尝试添加一个光源并改变其位置。模型或许被隐藏在黑暗中。

javascript 复制代码
       // 创建一个平行光
		this.directionalLight = new THREE.DirectionalLight('#1E90FF', 1)
		this.directionalLight.position.set(-1.44, 2.2, 1)
		this.directionalLight.castShadow = true
		this.scene.add(this.directionalLight)

2.模型材质辉光效果影响背景图的正常显示

(1)在场景动画帧渲染中对背景图进行单独处理

javascript 复制代码
	sceneAnimation() {
		this.renderAnimation = requestAnimationFrame(() => this.sceneAnimation())
		// 将不需要处理辉光的材质进行存储备份
		this.scene.traverse((v) => {
			if (v instanceof THREE.Scene) {
				this.materials.scene = v.background
				v.background = null
			}
			if (!this.glowMaterialList.includes(v.name) && v.isMesh) {
				this.materials[v.uuid] = v.material
				v.material = new THREE.MeshBasicMaterial({ color: 'black' })
			}
		})
		this.glowComposer.render()
		// 在辉光渲染器执行完之后在恢复材质原效果
		this.scene.traverse((v) => {
			if (this.materials[v.uuid]) {
				v.material = this.materials[v.uuid]
				delete this.materials[v.uuid]
			}
			if (v instanceof THREE.Scene) {
				v.background = this.materials.scene
				delete this.materials.scene
			}
		})

		this.effectComposer.render()
	}

3.窗口大小改变场景画面像素变得模糊

在窗口监听方法中更新相机,渲染器等相关信息

javascript 复制代码
	window.addEventListener("resize", this.onWindowResize.bind(this))
				// 监听窗口变化
	onWindowResize() {
		const { clientHeight, clientWidth } = this.container
		//调整屏幕大小
		this.camera.aspect = clientWidth / clientHeight //摄像机宽高比例
		this.camera.updateProjectionMatrix() //相机更新矩阵,将3d内容投射到2d面上转换
		this.renderer.setSize(clientWidth, clientHeight)
		this.effectComposer.setSize(clientWidth, clientHeight)
		this.glowComposer.setSize(clientWidth, clientHeight)
	}
			

4.修改材质的position(x,y,z)没有实际的效果

模型材质类型为 Mesh 的材质支持修改 position

javascript 复制代码
	const mesh = this.model.getObjectByName(name)
	if(mesh.type == 'Mesh){
        mesh.position.set(1,10,1)
   }

5.材质设置网格,透明度和颜色没有实际效果或者造成材质显示不正确?

three.js支持 修改网格,透明渡和颜色的材质有: MeshBasicMaterial,MeshLambertMaterial,MeshPhongMaterial,MeshStandardMaterial,MeshPhysicalMaterial,MeshToonMaterial 这六种

6.鼠标(点击,拖拽,缩放,移动)等操作不影响场景内容

javascript 复制代码
// 启用或禁用摄像机平移,默认为true。
this.controls.enablePan = false
// 当设置为false时,控制器将不会响应用户的操作。默认值为true。
thsi.controls.enabled =false
// 启用或禁用摄像机水平或垂直旋转。默认值为true。
thsi.controls.enableRotate  =false
// 启用或禁用摄像机的缩放。
thsi.controls.enableZoom =false

7.将three.js color 值转化为普通 css 值

javascript 复制代码
const colot = new THREE.Color(colorRGB).getStyle()

8.调整相机角度,模型的部分材质内容显示不完整或者不显示

将 frustumCulled值设置为false不管是否在相机视椎体都会渲染

javascript 复制代码
   this.model.traverse(item => {
        if (item.isMesh && item.material) {
            item.frustumCulled = false  
        }
    })

9.模型文件加载进度条 total 为0 lengthComputable为false?

可能原因有以下几种: 1.文件资源在项目本地文件夹public(vue项目) 2.服务器未提供 Content-Length: 服务器在响应头中未提供正确的 Content-Length 字段,或者提供的值无效。在这种情况下,浏览器无法确定要加载的总字节数,因此 lengthComputable 被设置为 false 3.流式传输: 一些加载场景中,数据是通过流式传输的方式加载的,因此无法预先知道要加载的总字节数。例如,通过 WebSocket 或 SSE (Server-Sent Events) 加载数据时,通常无法确定总字节数。 lengthComputable 为false 情况单独处理 :

javascript 复制代码
  onModelProgress(progressEvent ){
      const { loaded ,total ,lengthComputable } = progressEvent 
        //lengthComputable  true 可以获取到当前文件的总字节大小
       if(lengthComputable ){
        const progress = loaded / total * 100
        console.log( progress + '% loaded' )
        }else{
          console.log('已加载'+loaded+'字节' )
      }
   }

关于Three.js开发中性能优化

在页面关闭销毁跳转离开 时清除代码中 定时器事件监听动画帧等相关方法。释放场景中的材质内存,清除场景和模型相关信息

javascript 复制代码
   // 清除模型数据
	onClearModelData(){
		cancelAnimationFrame(this.rotationAnimationFrame)
		cancelAnimationFrame(this.renderAnimation)
		cancelAnimationFrame(this.animationFrame)
		this.container.removeEventListener('click', this.onMouseClickModel)
		this.container.removeEventListener('mousedown', this.onMouseDownModel)
		this.container.removeEventListener('mousemove', this.onMouseMoveModel)
		window.removeEventListener("resize", this.onWindowResize)
		// 材质释放内存
	 	this.scene.traverse((v) => {
			  if (v.type === 'Mesh') {
						v.geometry.dispose();
						v.material.dispose();
		    	}
		  })
		  // 清除场景和模型相关信息
	    this.model.clear()
        this.scene.clear()
	}

完整的代码可参考:gitee.com/ZHANG_6666/...基于three.js开发3d模型可视化编辑器

相关推荐
果子切克now36 分钟前
vue2与vue3知识点
前端·javascript·vue.js
积水成江1 小时前
Vite+Vue3+SpringBoot项目如何打包部署
java·前端·vue.js·windows·spring boot·后端·nginx
一丝晨光1 小时前
Web技术简史、前后端分离、游戏
前端·javascript·css·游戏·unity·前后端分离·cocos
假客套1 小时前
2024 uniapp入门教程 01:含有vue3基础 我的第一个uniapp页面
前端·uni-app·vue3·hbuilder x
柒小毓2 小时前
网站开发基础:HTML、CSS
前端·css·html
&白帝&3 小时前
Vue.js 过渡 & 动画
前端·javascript
总是学不会.3 小时前
SpringBoot项目:前后端打包与部署(使用 Maven)
java·服务器·前端·后端·maven
Fanfffff7204 小时前
深入探索Vue3组合式API
前端·javascript·vue.js
光影少年4 小时前
node配置swagger
前端·javascript·node.js·swagger
昱禹4 小时前
关于CSS Grid布局
前端·javascript·css