Tengo un proyecto con 100 BoxGeometries, cada una con su propia imagen dentro (alrededor de 10kb). He notado problemas de rendimiento y saltos de fotogramas en dispositivos móviles cuando los cuadros se renderizan por primera vez, lo que me gustaría eliminar.
Por el momento, primero cargo todas las imágenes y creo texturas antes de agregar los cuadros:
let loader = new THREE.TextureLoader() for(let img of assets) { loader.load(img.url, texture => { textures[img.name] = texture assets.splice(assets.indexOf(img),1) if(!assets.length) { addBoxes() } }) }Luego coloco 100 cuadros en una cuadrícula, aquí hay un pseudocódigo para ilustrar:
textures.forEach((texture,i) => { let box = new THREE.Mesh( new THREE.BoxGeometry(1, .04, 1), [ blackMaterial, blackMaterial, new THREE.MeshBasicMaterial({ map: Controller.textures[boxMaterial.postID] }), blackMaterial, blackMaterial, blackMaterial ] ) box.position.x = (i % 10 - 5) box.position.z = (Math.floor(i / 10) - 5) scene.add( box ) }) requestAnimationFrame( step )Tengo una TRES.OrthographicCamera que puede desplazarse y hacer zoom alrededor de estos cuadros. He notado que cuando aparecen por primera vez, hacen que la memoria se dispare, pero una vez que se han visto todas las casillas, el montón neto cae drásticamente, y el rendimiento se suaviza y no se reducen las velocidades de fotogramas.
Tenga en cuenta que después de 6 segundos, la memoria se aplana repentinamente, esto es una vez que se han visto todas las casillas una vez:
Para combatir esto, he probado el parámetro frustrumCulled en las cajas:
box.frustumCulled = falseEsto resuelve el problema de alguna manera. Una vez cargado, el rendimiento es extremadamente fluido desde el principio y los problemas de memoria desaparecen. Sin embargo, parece que no tengo una forma de detectar una vez que se cargan todas las mallas, por lo que la carga inicial es lenta y tengo una animación de introducción, y las primeras interacciones son irregulares y requieren un rendimiento intensivo, ya que comienzan demasiado pronto.
Entiendo que cargar todas las cajas con carga ansiosa causará un mayor tiempo de carga, y esto estaría bien para este proyecto, para evitar problemas de memoria debido a la carga diferida. Sin embargo, ¿qué otras opciones tengo? Quizás box.frustumCulled no es el enfoque correcto.
¿Y hay alguna manera de tener detectores de eventos en dicha actividad de carga? Idealmente, cargaría todas las cajas correctamente, como si se hubieran visto una vez, con un precargador, y cuando el sistema estuviera listo, podría activar un método init.
Está utilizando todos los cubos, por lo que pueden compartir su definición de geometría. Incluso si desea que tengan diferentes tamaños, puede aplicar una transformación de escala a la malla más adelante.
let boxGeo = new THREE.BoxGeometry(1, .04, 1) textures.forEach((texture,i) => { let box = new THREE.Mesh( boxGeo, [ blackMaterial, blackMaterial, new THREE.MeshBasicMaterial({ map: Controller.textures[boxMaterial.postID] }), blackMaterial, blackMaterial, blackMaterial ] )Ahora, su programa solo necesita cargar una definición de geometría a la GPU en lugar de las que haya creado para cada textura.
Esta es una toma en la oscuridad, pero intente crear sus cubos por adelantado, con un material transparente, y aplique sus texturas más tarde. Mi idea es que eliminar la carga de la geometría desde el principio reducirá el tiempo de su renderizado inicial.
No estoy actualizado sobre cómo three.js maneja los materiales instanciados, pero es posible que pueda usar InstancedMesh para crear sus cubos y aumentar incluso su rendimiento general de representación.