Three.js: Adopte algunas características de ES6

Creado en 16 abr. 2015  ·  74Comentarios  ·  Fuente: mrdoob/three.js

Se acerca ES6, con navegadores y herramientas que ahora están ganando soporte rápidamente. Creo que THREE.js podría beneficiarse enormemente de algunas de las nuevas características que trae ES6.

Por diversión y para fomentar el debate en torno a una posible migración del proyecto, he creado este problema y he creado algunos ejemplos de código.

Características demostradas en los ejemplos siguientes:

  • Parámetros predeterminados
  • Palabra clave let con ámbito de bloque
  • Iteradores + para .. de
  • Clases
  • Funciones de flecha
  • Generadores
  • Módulos

Ejemplo de clase

import Object3D from '../core/Object3D';
import Geometry from '../core/Geometry';
import MeshBasicMaterial from '../materials/MeshBasicMaterial';

class Mesh extends Object3D {
    constructor(
        geometry = new Geometry(),
        material = new MeshBasicMaterial({color: Math.random() * 0xffffff}
    ) {
        super();

        this.geometry = geometry;
        this.material = material;

        this.updateMorphTargets();
    }
}

export default Mesh;

Ejemplo de generador transversal

class Object3D {
    constructor() {
        ...
    }

    traverse(callback) {
        callback(this);

        for (let object of this.children) {
            object.traverse(callback);
        }
    },

    *traversalGenerator() {
        this.traverse(object => yield object);
    }

    ...
}

Generador en uso:

for (let object of scene.traversalGenerator()) {
    if (object.name === 'Blah') {
        break;
    }
}

Nota: no he probado nada de esto

Suggestion

Comentario más útil

https://github.com/mrdoob/three.js/commit/1017a5432eede4487436d6d34807fda24b506088

Bien, creo que podemos empezar con let y const en src/ .

@DefinitelyMaybe ¿Es esto algo en lo que le gustaría ayudar?

Todos 74 comentarios

¿Probablemente un poco antes? El soporte no es siempre excelente en todos los navegadores: http://kangax.github.io/compat-table/es6/

let no expuestos en FF y no en el 100% de las situaciones en Chrome e IE.
generators no disponible en IE
class solo está en Chrome, la vista previa técnica de IE12 (Spartan) para Win10 y FF39, que es dos por encima de la versión actual.
import aún no está disponible en ningún lugar
super solo está disponible en IE12, no en IE11, Chrome o FF
arrow functions no en IE11 o Chrome

Además, tanto los generadores como for-of son asesinos de optimización para Chrome

Imo también es demasiado pronto solo para una sintaxis más elegante. Es discutible cuando algo en la lista daría ganancias notables en el rendimiento o beneficios en la legibilidad del código. Tal vez alguien que conozca la base de código y las características de ES6 pueda comentar sobre eso.

Llego un poco tarde a la fiesta de ES6. Esto me parece un idioma diferente. Contribuyo con regularidad a Three.js, pero si se pareciera a los fragmentos anteriores, no sé si continuaría. Simplemente no tengo la paciencia para aprender una versión de JavaScript de aspecto diferente y funcionamiento diferente, que básicamente hace lo mismo que 'new function ()' y 'object.prototype', pero posiblemente más lento.

¿Es esto lo que la comunidad web le ha pedido al comité de idiomas de ES6? He estado codificando durante 20 años y la palabra 'clase' no aparece en ninguna parte de mis proyectos (ni lo hará nunca si me salgo con la mía). Francamente, JavaScript está empezando a parecerse a JAVA ... (script). : - \

Estoy con @benaadams y @jonnenauha ; demasiado pronto, y podría ralentizar el código si Chrome y Firefox no optimizan en gran medida esta nueva versión del lenguaje como si ya estuvieran optimizando JavaScript bajo el capó (V8, etc.).

: +1:

@erichlof Bueno, en realidad estoy esperando la clase ES6 y la compatibilidad con el módulo más. Actualmente estoy usando AMD para mis aplicaciones. El proyecto principal de JS en el que trabajo es de ~ 10k líneas con cientos de "clases" y AMD es un salvavidas. Tanto durante el desarrollo como en la producción de compilaciones. Los proyectos grandes o incluso más pequeños de Imo necesitan tener algún tipo de sistema de módulos y una forma de que las cosas declaren de qué dependen. Se vuelve demasiado complicado de manejar una vez que tiene una estructura de proyecto compleja. No debe dejarse que el programado averigüe en qué orden colocar 25x <script> etiquetas. Esto es una tontería una vez que tienes la cantidad de archivos que tiene three.js. La mayoría de los proyectos resuelven esto creando un archivo js grande (como three.js) y luego hay carpetas de extras / ayudantes aleatorias donde puede incluir otras cosas. Esto es algo limitante y tengo que incluir una construcción de ~ 500kb (minificada) para tener ~ todo bajo el sol.

En un momento, creo que tres agregaron compatibilidad con AMD, pero eso es solo un pequeño bloque de código que detecta si se usa AMD y llama a una función en lugar de declarar efectivamente window.THREE. No sé qué tan difícil es actualmente hacer compilaciones personalizadas que eliminen la funcionalidad que no necesito y agreguen las cosas que quiero fuera del núcleo y las optimicen en un solo archivo de trabajo que cargue las cosas en orden.

Es posible que no tenga "clase" en sus proyectos, pero si usa object.prototype (como lo hace en gran medida three.js) es efectivamente lo mismo, ¿estaría de acuerdo? Nos gusta juntar objetos y darles un propósito. Otro código luego quiere usar dichos objetos y una forma declarativa limpia para importarlos.

Todo lo que digo que las clases y módulos de ES6 serían una buena adición también a three.js para darle más estructura y modularidad para las compilaciones. Es demasiado pronto porque afaik no admite navegadores, por ejemplo. módulos todavía. Otros podrían decir que debería comenzar a usarlos y usar babel, etc. y generar compilaciones compatibles con ES5, no estoy seguro de si eso es una buena idea, pero quién sabe. Esto dificulta el desarrollo, debe iniciar automáticamente la compilación cuando guarda archivos y la depuración también puede volverse más compleja. Solo por estas cosas, tiendo a pensar que estos transpiladores no valen la pena.

PD: No fue una diatriba contra three.js, solo dije que podría haber beneficios en ES6 para proyectos como three.js una vez que haya compatibilidad con el navegador :) y sobre todo su azúcar más sintáctico que convertirlo en un lenguaje completamente nuevo. Simplemente tendrá más cosas.

Otra característica que podría ser beneficiosa para three.js es WeakMap y posiblemente WeakSet . No estoy seguro de las implicaciones, pero parece que esto podría usarse para realizar un seguimiento de las cosas sin que el GC haga su trabajo si el "propietario" ya no tiene la referencia. Hay muchos estados como este en three.js y su uso interno podría marcar la diferencia. Me parece que esto es un poco similar a ptrs compartidos / débiles en C ++ para declarar la propiedad.

Un buen candidato podría ser cosas como https://github.com/mrdoob/three.js/blob/master/src/lights/SpotLight.js#L12 donde esto podría ser una referencia débil y se borraría automáticamente si el objetivo fuera retirado de la escena y recogido. Pero supongo que de todos modos no podría depender de la colección, pero de todos modos tendría que anular eso una vez que el objetivo se elimine de la escena.

Quién sabe, esperaré a que los expertos escriban algunas publicaciones de blog sobre cómo todas estas funciones podrían beneficiar a las aplicaciones en general :)

Hola @jonnenauha ,

Sí, estoy de acuerdo en que las nuevas características como 'importar' y 'exportar' serán útiles, especialmente en lo que respecta a la modularidad. Creo que esa es la dirección que @coballast y @kumavis están tratando de hacer para hacer que THREE.js sea más modular y manejable para compilaciones personalizadas y mantenibilidad de base de código. Estoy a favor de los módulos y la reutilización de objetos y funciones, especialmente cuando tenemos un formato de biblioteca grande como THREE.js.

Sin embargo, no creo que necesitemos el azúcar sintáctico adicional de clases, super, let, for, of, funciones de flecha, etc. cuando básicamente obtenemos la misma funcionalidad en JavaScript ahora que ha estado en uso durante décadas y tiene un mucha tracción ya. Puede que sea anticuado, pero estoy con Douglas Crockford cuando dice que JavaScript ya es un lenguaje orientado a objetos (es decir, funciones = objetos = ciudadanos de primera clase), pero no uno 'clásico', por lo que no deberíamos preocuparnos por clases de calzado en JavaScript. Fue diseñado con un enfoque diferente, un enfoque que me sorprendió al principio (viniendo de la programación C / C ++ en la década de 1990), pero con el que estoy cada vez más de acuerdo cada vez que me siento a programar o trato de resolver la arquitectura del código. problemas.

En lugar de cambios sintácticos en THREE.js, preferiría ver la migración hacia funciones como la nueva interfaz de programación SIMD. Creo que TODO el código matemático de TRES (especialmente Vector3 y Matrix4) podrían beneficiarse enormemente de esto. Aquí hay un enlace de video (consulte las 22:51 en el código de tiempo):
https://youtu.be/CbMXkbqQBcQ?t=1371
Cuando esta función llegue a los principales navegadores, cada usuario de THREE.js verá como resultado una notable aceleración en su velocidad de fotogramas.

Lo siento si mi publicación anterior sonó como una perorata, solo me gusta THREE.js cómo se ve ahora: puedo seleccionar fácilmente cualquier parte aleatoria y saber qué está sucediendo, de dónde vino y qué usa. :)

@erichlof @jonnenauha Me siento obligado a señalar que las clases de es6 son simplemente azúcar y están utilizando internamente el mecanismo de prototipo para implementar todo en tiempo de ejecución.

Soy bastante optimista de que las características de es6 no afectarán el rendimiento computacional. Los módulos es6 pueden afectar el tiempo de carga cuando finalmente los motores los implementan, porque está obteniendo un montón de archivos pequeños en lugar de un archivo grande. Sin embargo, HTTP / 2 podría hacer que eso no sea un problema. De cualquier manera, si usamos módulos es6 podemos usar browserify para construir un paquete como siempre lo hacemos.

Personalmente, estoy a favor de usar la sintaxis es6 en el código base tanto como sea posible, porque haría el código más conciso y reduciría los errores. Creo que mucha gente tiende a abusar de la cadena de prototipos y a usarla incorrectamente. Aunque no tengo un buen ejemplo.

También creo que sentarse y esperar a que se implemente es6 en los motores es una idea equivocada. Los transpilers están disponibles en este momento y producen buenos resultados que se ejecutan en los navegadores en este momento. Creo que los beneficios de hacer esto son enormes, por lo que deberíamos estar impacientes y comenzar a trabajar en esto de inmediato.

No creo que mover el código manualmente sea una buena idea. Como dijo Doug McIlroy, el inventor de las tuberías Unix y, en general, un semidiós:
"Utilice las herramientas en lugar de la ayuda no especializada para aligerar una tarea de programación, incluso si tiene que desviarse para construir las herramientas y esperar deshacerse de algunas de ellas después de haber terminado de usarlas".

Animaría a cualquier persona interesada en es6 a participar y ayudar a contribuir a este repositorio: https://github.com/5to6/5to6

No estoy de acuerdo en convertir toda la biblioteca a un subconjunto diferente de javascript. Como siempre, deberíamos discutir qué es posible y cuáles son los pros y los contras. Porque el rendimiento va a diferir entre versiones.

Por ejemplo, los mapas débiles son algo que sería una gran ganancia en los renderizadores para manejar los estados de los objetos. Sus mayores desventajas fueron un polyfill débil y muy poca compatibilidad con el navegador y características de rendimiento desconocidas. (Ha pasado un tiempo desde que investigué esto, por lo que es probable que esto haya cambiado)

Y no solo deberíamos mirar es6. Por ejemplo, ams.js sería genial como tecnología que ejecuta un renderizador de software. Para obtener más información, http://stackoverflow.com/questions/18427810/three-and-asmjs/18439786#18439786.

Y no debemos olvidar que la mayoría de los contribuyentes están contribuyendo principalmente porque javascript es familiar y es6 aún no lo es para la mayoría.

@ gero3 Esos son buenos puntos en los que no pensé. Si hablamos de microoptimización, estoy 100% de acuerdo contigo. No quisiera aprovechar esas funciones sin la compatibilidad del navegador.

En gran parte, de lo que estaba hablando anteriormente era del uso de azúcar sintáctico que tiene una semántica idéntica a las características de es5 existentes, por lo que podría construirse con transpilers sin afectar demasiado el rendimiento.

ACTUALIZAR:
Quizás a nadie le importe, pero cambié de opinión. Creo que no deberíamos usar clases. Sigo pensando que los módulos es6 son una buena idea.

Estoy totalmente a favor de las clases. Obtengo todas las cosas maravillosas que puede hacer el prototipo de objeto en JavaScript. Sin embargo, en THREE.js (y muchos otros proyectos de sistemas operativos modernos) estamos usando la herencia de prototipos para simular clases, así que ¿por qué no tener la buena sintaxis para acompañarlo y deshacerse de las cosas hacky como:

THREE.Object3D.call( this );

y

THREE.Scene.prototype = Object.create( THREE.Object3D.prototype );

Tan pronto como las clases sean compatibles con Chrome y Firefox estables, no me importaría considerar actualizar el código 😊

Las clases de

Safari en iOS parece ser el que arrastra hoy en día ... 😣

Las clases son increíbles y también lo son otras características de ES7. Los estamos usando en uno de nuestros proyectos, pero tuvimos que introducir un compilador cruzado (babel.js) porque necesitamos ejecutarlo en todos los navegadores: Chrome, Firefox, IE y Safari.

Hay una transformación de browserify para ejecutar babel.js (babelify), por lo que funcionaría bien con mis esfuerzos.

Solo por curiosidad, ¿se ha comenzado a trabajar en algunos de estos? :)

no, ya que todavía no conocemos las implicaciones sobre la velocidad de estos.

Según tengo entendido, ES6 en su mayoría no funciona y, por lo tanto, no está destinado a la producción hasta que no se lo implique en el navegador. Dicho esto, los proyectos o módulos más nuevos deberían adaptar estas comodidades hoy, pero el rendimiento debe tenerse en cuenta en esta decisión.

Estoy de acuerdo con @erichlof imo, la implementación más útil sería SIMD (https://github.com/tc39/ecmascript_simd), incluso con el uso de polyfill. Parece que los usuarios se beneficiarían más de eso.

¿Dónde encajaría SIMD en ThreeJS? Creo que ThreeJS ya descarga todos los cálculos significativos a la GPU. Si bien puedo entender su uso en las clases de Vector, hay muy pocas matemáticas que se hagan en ThreeJS, en lugar de eso, en su mayoría, esos vectores simplemente se transportan a la GPU.

Hablo por experiencia, ya que implementé extensiones SSE2 / SSE4 antes y descubrí que los beneficios eran fugaces en la mayoría de los casos; los únicos casos reales en los que era un beneficio eran cuando tenía arreglos grandes en los que quería hacer lo mismo. operación.

Hola @bhouston ,
¿Se aplica lo mismo a las operaciones de Matrix? Cuando pensaba en SIMD, pensaba que las operaciones matriciales 4 X 4 serían las que más se beneficiarían. Y como todos sabemos, las matrices se utilizan en cada cuadro de animación en Three.js en el lado de JavaScript / CPU, sin importar la complejidad de la aplicación.

Si a los chicos de Babylon.js no les importa, aquí hay una pista de cómo empezar todo esto:
https://github.com/BabylonJS/Babylon.js/blob/master/src/Math/babylon.math.js#L2030 -L2093

Creo que un único múltiplo de matriz si tiene que convertir el formato es probablemente un perdedor. Si tiene sus matrices siempre en formato SIMD, entonces puede ser una ventaja.

Pero aun así, la multiplicación de matrices a menudo no es óptima porque tiene que multiplicar columnas por filas, lo que requiere una operación de reordenación.

Descubrí que la mayoría de los esfuerzos en la optimización de SIMD (excluyendo arreglos grandes con operaciones homogéneas) no valen la pena, pero estoy de acuerdo con que otros hagan evaluaciones comparativas para averiguarlo.

El código resultante también es difícil de depurar y mantener.

Una estrategia que puede funcionar es hacer que todos los vectores y matrices usen un diseño de memoria compatible con SIMD como su representación nativa, que es lo que Quake 3 hizo, creo en su biblioteca matemática. Pero luego debe usar 4 flotadores para los tipos vec2 y vec3 para mayor eficiencia, pero eso se vuelve problemático cuando desea cargar a la GPU porque ahora tiene flotadores adicionales en el camino.

Entiendo lo que quiere decir, gracias por su conocimiento y experiencia. Estar impresionado por la presentación de SIMD.js hace un tiempo, y pegarlo en three.js y mantenerlo son dos cosas diferentes, supongo. Sería interesante, como dijiste, hacer algunas comparaciones de rendimiento. ¿Quizás las bibliotecas de física como Cannon.js y Oimo.js, que se utilizan junto con three.js, obtendrían más beneficios de SIMD?

@bhouston Ahh ok, eso tiene algún sentido, aunque algunos puntos de referencia serían bastante interesantes.

@erichlof si está interesado, he iniciado una sucursal, https://github.com/Globegitter/three.js/tree/include-SIMD , donde comencé a reemplazar Vector3 con SIMD. Todavía es un trabajo en curso pesado y mi tiempo es limitado, así que veremos hasta dónde llegaré. Además, al usar el último Firefox todas las noches, puede ejecutar este código sin un polyfill (donde la implementación nativa es aparentemente ~ 20 veces más rápida en comparación con el polyfill: https://blog.mozilla.org/javascript/2015/03/10/state -of-simd-js-performance-in-firefox /).

@erichlof @jonnenauha Me siento obligado a señalar que las clases de es6 son simplemente azúcar y están utilizando internamente el mecanismo de prototipo para implementar todo en tiempo de ejecución.
Soy bastante optimista de que las características de es6 no afectarán el rendimiento computacional.

Es posible que se apresure un poco a concluir que: De hecho, existen diferentes rutas de código para ES6 en cada motor JS en la implementación (bastante compleja) de los objetos JS.

Los módulos es6 pueden afectar el tiempo de carga cuando finalmente los motores los implementan, porque está obteniendo un montón de archivos pequeños en lugar de un archivo grande. Sin embargo, HTTP / 2 podría hacer que eso no sea un problema.

Es posible que los clientes aún deseen utilizar la compresión de nivel JS de toda la aplicación para reducir el ancho de banda de la red y proteger su propiedad intelectual.

Hacer que el compilador de cierre entienda Three.js permitiría compilar en ES6 y ver cuándo es el momento adecuado para cambiar, además de muchos beneficios adicionales. Creo que aquí es donde deberían dirigirse esfuerzos de este tipo por ahora ...

Pero aun así, la multiplicación de matrices [SIMD] a menudo no es óptima porque tiene que multiplicar columnas por filas, lo que requiere una operación de reordenamiento.

Los conjuntos de instrucciones SIMD a menudo tienen una instrucción "multiplicar por escalar y sumar", para implementar la multiplicación de matrices como esta:

for i : 0..3:
    dst.col[i] = lhs.col[i] * rhs.co[i][0] // multiply vector by scalar
    for j : 1..3:
        dst.col[i] += lhs.col[i] * rhs_col[i][j] // multiply vector by scalar & add

La multiplicación de matrices en realidad es simplemente aplicar una transformación a los vectores de columna del operando del lado derecho. Ahora, las transformaciones pueden verse como un montón de productos escalares (la forma confusa que usamos generalmente con lápiz y papel), o como una combinación lineal de los vectores de eje del espacio de destino = vectores de columna del lado izquierdo operando.

@Globegitter ¡ Guau, ese es un comienzo increíble! ¡Voy a obtener Firefox Nightly para poder experimentar con la nueva rama también!

@Globegitter Me encanta cuando alguien simplemente sigue adelante y hace algo cuando cree en ello. El código resuelve puntos de vista divergentes más rápido que la discusión.

donde la implementación nativa es aparentemente ~ 20 veces más rápida en comparación con el polyfill

Estaría interesado en ver también cuánto más lento es el polyfill en comparación con no SIMD

¡Voy a obtener Firefox Nightly para poder experimentar con la nueva rama también!

También debería poder probarlo en Edge cambiando experimental y asm.js en about: flags

@Globegitter Creo que su editor está cambiando el espacio en blanco que conduce a diferencias realmente desagradables: https://github.com/Globegitter/three.js/commit/d835ca3a22eed4ed4603534773ae55c29d5a8026

Noto que está haciendo el tipo SIMD como un sidecar:

https://github.com/Globegitter/three.js/commit/8ed9c1d351a3b0587a1f05051922d271d79f642d

¿Puedo sugerirle que simplemente cambie Vector3 x, y, z en getter / setters y solo almacene un float32x4? Creo que este enfoque puede ser mucho más fácil de implementar con menos cambios.

No estoy seguro de la mejor manera de definir propiedades, pero mrdoob hace algo así aquí:

https://github.com/mrdoob/three.js/blob/5c7e0df9b100ba40cdcaaf530196290e16c34858/examples/js/wip/proxies/ProxyVector4.js#L18

Tener el SIMD como el tipo de almacenamiento principal detrás de un tipo matemático es probablemente lo más eficiente, no se requieren conversiones adicionales. Aquí está la biblioteca matemática SSE de Bullet Physics si necesita una guía para cualquier operación estándar de vector / matriz:

https://code.google.com/p/bullet/source/browse/trunk/src/vectormath/sse/

@bhouston , gracias por estas notas. Estaba llegando directo allí para ver qué tan lejos llegaría en unas pocas horas sin haber trabajado mucho con tres y SIMD antes (lo usamos en la mayoría de nuestros proyectos). Entonces, esta retroalimentación de alguien que conoce a tres es realmente apreciada. Y sí, tengo que apagar eso en mi editor.

@tschw ¡ gracias por la nota sobre las matemáticas de matriz / vector! Tienes razón en que es mejor.

@Globegitter Aquí hay un mejor ejemplo de setter / getter en el prototipo de un objeto: https://github.com/mrdoob/three.js/blob/master/src/core/Object3D.js#L83

Algunos céntimos en trabajar en ES2015 (principalmente en nodo)

  • Hay lugares en los que los motores de JavaScript (por ejemplo, V8) necesitan ponerse al día optimizando las funciones de ES6
  • a partir de mi experiencia, el código como let x = 1, y = 2 desoptimizaría v8, aunque esperaría que v8 lo admita eventualmente
  • el código transpilado a ES5 se puede ejecutar más lento que el código ES6 (por eso prefiero usar solo las funciones ES6 compatibles en> nodo 4, que es casi todo excepto el sistema de importación y exportación)
  • Los mapas y conjuntos son victorias en rendimiento
  • Las clases son agradables
  • Usar Babel puede ser una molestia para su flujo de trabajo, probablemente no valga la pena el esfuerzo si usa ES6 solo para el azúcar de sintaxis

Hace medio año convertí algunas funciones de Three.js (multiplicación de matrices 4x4, Vector4, etc.) a SIMD y puedes probarlas. En algún momento funcionó como marcador, pero ahora puede requerir una actualización para funcionar con la última versión de Three

  • Firefox Nightly es compatible con SIMD nativo listo para usar
  • Chrome con la bandera --js-flags = "- harmony-simd" es compatible con JS polyfill de SIMD, por lo que será más lento que la versión sin simd. ¡Al menos puedes comprobar si funciona y experimentar!

350% de aumento de rendimiento es una MENTIRA :)

También porté parte de Vector3 pero está comentado.

https://github.com/DVLP/three.turbo.js

Editar: tengo una versión más actualizada en algún lugar de mi disco duro, así que actualizaré este proyecto pronto

Increíble mirar y mirar fijamente un +1 a eso.
Lo que sería genial es un sistema que verifique el rendimiento y habilite o deshabilite dichas funciones en función de dicho rendimiento.

Lo que sería genial es un sistema que verifique el rendimiento y habilite o deshabilite dichas funciones en función de dicho rendimiento.

Supongo que uno tendría dos definiciones de Vector3 dentro del módulo Vector3 y devolvería condicionalmente una u otra dependiendo de si SIMD es nativo. Supongo que funcionaría, pero aumentaría el lado de descarga. Tal vez solo pueda tener algunas funciones que cambien dependiendo de si SIMD está disponible; probablemente SIMD sea más importante solo para un pequeño subconjunto de funciones matemáticas. Si esto fue pequeño en términos de código total, puede que valga la pena ponerlo ahora. Pero debe ser opcional para que no se vuelva lento cuando SIMD no está disponible.

Podríamos comenzar haciendo una versión SIMD de Matrix4 de multiplyMatrices() ya que actualmente es el método más llamado en escenas complejas.

https://github.com/mrdoob/three.js/blob/dev/src/math/Matrix4.js#L383 -L419

screen shot 2016-08-30 at 20 46 29

@mrdoob mira aquí está hecho.
https://github.com/DVLP/three.turbo.js/blob/master/src/three.turbo.js

Pruébelo como bookmarklet:
javascript:(function(){var script=document.createElement('script');script.src='//rawgit.com/DVLP/three.turbo.js/master/src/three.turbo.js';document.head.appendChild(script);})()

El código responsable

THREE.Matrix4.prototype.multiplyMatrices = function(a, b) {
    var ae = a.elements,
      be = b.elements,
      tb = this.elements,
      arr1 = SIMD.Float32x4.load(ae, 0),
      arr3 = SIMD.Float32x4.load(ae, 4),
      arr5 = SIMD.Float32x4.load(ae, 8),
      arr7 = SIMD.Float32x4.load(ae, 12),
      arr2,
      arr4,
      arr6,
      arr8,
      res;
    // calculated version
        for (var i = 0; i < 4; i++) {
            arr2 = SIMD.Float32x4.splat(be[i * 4]);
            arr4 = SIMD.Float32x4.splat(be[i * 4 + 1]);
            arr6 = SIMD.Float32x4.splat(be[i * 4 + 2]);
            arr8 = SIMD.Float32x4.splat(be[i * 4 + 3]);
            res = SIMD.Float32x4.add(SIMD.Float32x4.add(SIMD.Float32x4.mul(arr1, arr2), SIMD.Float32x4.mul(arr3, arr4)), SIMD.Float32x4.add(SIMD.Float32x4.mul(arr5, arr6), SIMD.Float32x4.mul(arr7, arr8)));
            SIMD.Float32x4.store(tb, i * 4, res);
          }
}

Cuando estaba probando esto hace medio año, noté que la versión con el bucle "for" desplegado era mínimamente más rápida. Es por eso que en mi pequeña biblioteca se comenta el bucle y está presente la versión codificada.

Hay más funciones en la rama "inversa"
https://github.com/DVLP/three.turbo.js/blob/inverse/src/three.turbo.js

¿Cuál es la diferencia de rendimiento?

https://jsfiddle.net/tk6zx5dm/6/

Eso depende. En Nightly, cuando el número de cálculos es pequeño (<1000), el resultado es 3 veces más lento. Cuando el número de cálculos es superior a 10000, la velocidad es ~ 40% más rápida

En Chrome con la bandera --js-flags="--harmony-simd" habilitada, no hay SIMD real, pero un polyfill de JavaScript, por lo que obviamente la velocidad es muchas veces más lenta por ahora.

Un buen lugar para probar sería el proyecto Crosswalk (basado en Chromium). Tienen SIMD real para Android por lo que podría ser un experimento interesante construir un proyecto con código de este JSFiddle para ver cuál sería el resultado.

Es posible que desee incluir el polyfill simd de todos modos en sus páginas de ejemplo. Un poco más conveniente para que la gente los pruebe. Registre una línea en la consola o coloque algo de texto en la pantalla cuando no haya ningún nativo disponible (el polyfill probablemente deja algunos indicios de que está habilitado).

No puedo imaginar por qué Chrome simplemente cargaría el polyfill js simd con --js-flags="--harmony-simd" , ¡eso no tiene sentido cuando ya se puede hacer en la tierra del usuario! ¿Cuál es el beneficio de esto? Tal vez comiencen a poner cosas gradualmente. ¿Dónde leíste esto? ¿Qué está pasando realmente con la bandera? ¿Algún buen enlace? Parece estar "en desarrollo" aquí https://www.chromestatus.com/features/5757910432874496

Editar: Al tema real: imagino que es muy difícil poner estas cosas en three.js si el perf está por todas partes, desde unos pocos objetos hasta muchos objetos. Si todas las implementaciones pueden dar una mejora de rendimiento con 1 a N objetos, debería detectarse la característica y usarse donde tenga sentido. Si las impls nativas son inconsistentes, no veo que todo vaya a ninguna parte, así que, ¿por qué molestarse en trabajar en ello? Pasar las horas de desarrollo en algo más productivo.

tres pueden saltar sobre esto cuando madure, ¿o es el caso de que la compatibilidad con three.js podría impulsar las implementaciones del navegador para que funcionen mejor? Creo que el motor irreal y otros casos de uso de simulación / matemáticas serían la fuerza impulsora para los proveedores de navegadores, no particularmente cuántas bibliotecas quieren usar la función. Pero quién sabe.

No puedo imaginar por qué Chrome simplemente cargaría el polyfill de js simd con --js-flags = "- harmony-simd"

Creo que es una práctica bastante común que los navegadores lo hagan de esta manera, para que los usuarios puedan comenzar a probar cosas. Por ejemplo, si lo entiendo correctamente, así es como se introducirá WASM en los navegadores inicialmente.

Todos los argumentos que apoyan la inevitabilidad de que se necesita un centurión. Monitoreo en tiempo real del desempeño que puede habilitar o deshabilitar funciones y determinar el desempeño óptimo. Así que incluso la densidad del mapa de sombras debería cambiar en función de la distancia de la cámara, etc. De todos modos, sé que el consenso ha decidido que esta sería una herramienta de terceros y no necesaria. Aún así, solo quiero mantener ese punto en la mente consciente, si no subconsciente.
Tal vez solo esté verificando un pollyfill y deshabilitando SIMD, pero nuevamente FPS lo dice todo. Es probable que las prioridades de qué habilitar o deshabilitar sea mejor como preferencia específica del usuario / aplicación. ¡Gracias por su atención! Espero tener un GL mejor y más rápido en un futuro próximo. Estemos preparados para eclipsar al resto.

Parece que el proceso de carga de datos en SIMD podría estar creando una sobrecarga que desafía el beneficio de usar SIMD en Nightly. Tengo mucha curiosidad sobre el rendimiento en Chrome, pero el último Chromium con SIMD real está aquí http://peterjensen.github.io/idf2014-simd/
Es viejo.

Actualizar:
ahora SIMD funciona también en Edge. Puede habilitarlo yendo a about: flags y marcando "Habilitar funciones experimentales de JavaScript" (reiniciar Edge)
Sin embargo, no estoy seguro de si esto es SIMD real o polyfill. Esta prueba muestra un SIMD un 40% más lento en mi máquina: / https://jsfiddle.net/tk6zx5dm/6/

variación de la prueba con objetos SIMD almacenados en caché en el objeto Matrix4, no estoy seguro de si esto alguna vez será útil
https://jsfiddle.net/tk6zx5dm/15/
Lo interesante es que el código con objetos SIMD almacenados en caché es _a veces_ más rápido incluso en Chrome que usa polyfill SIMD (...? Raro)

THREE.Matrix4.prototype.multiplyMatrices = function(a, b) {
  var i = 4;
  while(i--) {
    SIMD.Float32x4.store(this.elements, i * 4, 
      SIMD.Float32x4.add(
        SIMD.Float32x4.add(
          SIMD.Float32x4.mul(
            a.cacheSIMDRow1,
            b.cacheSIMDSplat[i * 4]
          ),
          SIMD.Float32x4.mul(
            a.cacheSIMDRow2,
            b.cacheSIMDSplat[i * 4 + 1]
          )
        ),
        SIMD.Float32x4.add(
          SIMD.Float32x4.mul(
            a.cacheSIMDRow3,
            b.cacheSIMDSplat[i * 4 + 2]
          ), 
          SIMD.Float32x4.mul(
            a.cacheSIMDRow4,
            b.cacheSIMDSplat[i * 4 + 3]
          )
        )
      )
    );
  }
}

Almacenamiento en caché: probablemente deba ejecutarse en cada updateMatrix () que puede hacer que toda la solución sea más lenta al final

THREE.Matrix4.prototype.updateSIMDCache = function() {
  this.cacheSIMDRow1 = SIMD.Float32x4.load(this.elements, 0);
  this.cacheSIMDRow2 = SIMD.Float32x4.load(this.elements, 4);
  this.cacheSIMDRow3 = SIMD.Float32x4.load(this.elements, 8);
  this.cacheSIMDRow4 = SIMD.Float32x4.load(this.elements, 12);

  if(!this.cacheSIMDSplat) {
    this.cacheSIMDSplat = [];
  }
  for(var i = 0; i < 16; i++) {
    this.cacheSIMDSplat.push(SIMD.Float32x4.splat(this.elements[i]));
  }
};

Tengo curiosidad, ¿se ha revisado el estilo de ES6? El código completo no se puede usar en vivo en este momento sin ejecutar un concatenador, así que ¿por qué no ejecutar también babel y comenzar a usar cosas de ES6 cuando sea apropiado?

El código completo no se puede usar en vivo en este momento sin ejecutar un concatenador, así que ¿por qué no ejecutar también babel y comenzar a usar cosas de ES6 cuando sea apropiado?

Principalmente debido a la falta de pruebas sobre el impacto en el rendimiento del código producido por babel. Además, escuché que V8 produce un código más rápido cuando se usa var en lugar de let / const.

FYI: Recientemente comencé a probar bublé, que "se limita a las características de ES que se pueden compilar en ES5 compacto y de alto rendimiento".

La parte inferior de este enlace ayuda a explicar var vs let in bucles
http://stackoverflow.com/questions/21467642/is-there-a-performance-difference-between-let-and-var
Personalmente, estoy esperando que las soluciones sin transpilador lleguen al navegador. como para 'esperar', cuanto antes mejor, pero por ahora tal vez debería estar escrito de esa manera y pasar por un transpilador (quedando horriblemente desfigurado), pero ¿si funciona en Chrome? así que probando para otros navegadores? Yo digo 'Déjalos comer pastel ... o usa Chrome'. (mi expresión favorita).
Creo que "dejar" debería usarse si se encuentra en una situación en la que preferiblemente se demuestra mediante pruebas que es mejor hacerlo.
Supongo que es como si 'var' estuviera levantado para evitar el alcance, pero es posible que desee eso y luego 'dejar' es lo mejor. Creo / espero que 'dejar' debería mantener su huella de memoria más pequeña en ciertas situaciones también.

El código transpilado nunca será tan rápido como se optimiza a mano. Es una pena que JSPerf no funcione. Solía ​​visitarlo con más frecuencia que Google.
Editar: ¡JSPerf.com no está caído! Simplemente asumí que está muerto para siempre después de que no funcionó durante un año.
let 3 veces más lento que var en mi Chrome Canary: https://jsperf.com/let-vs-var-performance/14
en Firefox y Edge no hay diferencia de velocidad pero Chrome es el más importante.
¿Alguien puede probar en Safari?

¡Las clases parecen geniales y modernas! ¿Alguien sabe si esto ya está programado?

@ Rubinhuang9239 No he visto a nadie

deje 3 veces más lento que var en mi Chrome Canary: https://jsperf.com/let-vs-var-performance/14

Por lo que vale, let y const ahora son ligeramente más rápidos que var para mí en Chrome 66, Firefox 59 y Edge 42, usando esa prueba.

Creo que cambiar las clases debería ser muy sencillo: la mayor parte del trabajo fue la adopción del paquete acumulativo que se realizó hace bastante tiempo. No me sorprendería que un héroe pudiera implementar clases en ThreeJS en un par de horas.

Bueno, hay muchas clases, así que tal vez te lleve unas 8 horas si lo hicieras manualmente.

Tal vez comience poco a poco y convierta las clases de matemáticas primero y haga un PR. Si eso funciona, pase a los demás.

@looeee ha pasado más de un año, así que no es de extrañar que ES6 haya logrado ponerse al día con el rendimiento

2019 es el año para finalmente comenzar a adoptar algún código ES6 en los ejemplos / documentos, ¿verdad @mrdoob? 😄

ES6 ha sido el estándar desde hace bastante tiempo, los nuevos desarrolladores aprenden ES6. También podemos dejar de admitir IE11 en los ejemplos como ustedes discutieron en # 16220, ¿qué desarrolladores ven ejemplos de three.js usando IE11? 😅

Creo que las características más necesarias para simplificar el código para los recién llegados son las clases y las cadenas de plantillas, sin olvidar las ahora predeterminadas const / let.

Puedo contribuir si decidimos empezar.

Paso a paso. Comencemos actualizando los ejemplos para usar three.module.js por ahora.

Paso a paso. Comencemos actualizando los ejemplos para usar three.module.js por ahora.

Este paso se ha completado durante un tiempo. ¿Quizás es hora de pasar oficialmente al siguiente paso?

Dos candidatos:

  1. const / let
  2. clases

Dado que las clases ya se han utilizado en las geometrías de caja durante un tiempo, voto por hacer eso primero. O podríamos hacer ambas cosas al mismo tiempo.

Relacionado: # 11552, # 18863

Si entiendo bien, el problema es que no podemos convertir nada a las clases ES6 si se amplía con ejemplos, hasta que los ejemplos también se conviertan. ¿Y eso podría significar esperar hasta que examples/js se acabe? A menos que podamos confirmar que el script modularize admitirá clases, para convertir los archivos examples/js al mismo tiempo que sus clases principales.

Según tengo entendido, examples/js es una especie de todas las características en exceso que son geniales sin embargo, pero que si todas las combinamos en el src/... , las inflaría fuera de proporción. Inherentemente es la respuesta a la pregunta '¿Proporcionamos ejemplos / scripts de x, y, z comúnmente creados?'. Me atrevo a suponer que la respuesta de three.js es mayoritariamente sí, pero como material educativo dentro del sitio web. Eliminar examples/js parece imposible en ese momento. Aunque quizás no he entendido cómo se hace referencia / uso de examples/js 🤔 avíseme.

Dejar examples/js como único sitio web / educativo pierde parte del punto de lo que podría ser esa carpeta, es decir, scripts / contenido / proyectos de la comunidad / otros que a la gente le gustaría compartir, pero no tengo conocimiento de algún lugar que se esté duplicando. ese.

Estoy divagando.

hasta que los ejemplos también se conviertan.

Me gusta cómo suena esto como nuestro próximo mejor paso intermedio.

@DefinitelyMaybe no estamos eliminando la funcionalidad en examples/js , hay dos directorios dignos de mención:

  • examples/js/*
  • examples/jsm/*

El primero contiene archivos heredados, el segundo contiene módulos ES generados a partir de esos archivos, con la misma funcionalidad. Eventualmente eliminaremos el primero. El script que realiza la conversión no admite clases de ES actualmente. Entonces, hasta que se elimine, los archivos en examples/js no se pueden convertir a clases ES. Algunos de ellos extienden archivos en src/ , y no puede extender las clases de ES sin usar las clases de ES, por lo que esta es una dependencia de bloqueo.

ah, estaba confundido por el comentario anterior

¿Y eso podría significar esperar hasta que examples / js desaparezca?

tiene sentido ahora.

modularize.js me recuerda a mi proyecto inicial que me trajo aquí. Convertidor . Vi comentarios aquí sobre pasar a las clases de ES6, así que pensé en saltar aquí.

Entonces, si examples/js extiende src de alguna manera, ambos deben convertirse a clases ES6 al mismo tiempo
o...
trabajar en modularizar hasta que genere clases / es6?

no podemos convertir nada a clases ES6 si se amplía con ejemplos

Todavía hay muchas cosas en el núcleo que no se extienden en los ejemplos, ¿por qué no comenzamos con eso?

Eso suena bien para mi.

@ Mugen87 , ¿hubo algo más que bloqueara el cambio de clase ES, o solo eso?

Todavía hay muchas cosas en el núcleo que no se extienden en los ejemplos, ¿por qué no comenzamos con eso?

Lista de scripts no ampliada con ejemplos .

editar: ¡la lista ha sido actualizada!

Los bloqueadores son secciones como estas:

https://github.com/mrdoob/three.js/blob/6865b8e6367d0ce07acbacfae6663c4cce3ac21e/examples/js/loaders/ColladaLoader.js#L6 -L12

https://github.com/mrdoob/three.js/blob/6865b8e6367d0ce07acbacfae6663c4cce3ac21e/examples/js/cameras/CinematicCamera.js#L38 -L39

https://github.com/mrdoob/three.js/blob/6865b8e6367d0ce07acbacfae6663c4cce3ac21e/examples/js/controls/OrbitControls.js#L1149 -L1150

El uso de THREE.<class>.call y Object.create( THREE.<class> serían los patrones más probables. Lo que significaría que Loader, EventDispatcher y PerspectiveCamera (entre probablemente muchos otros) aún no se pueden convertir en clases.

https://github.com/mrdoob/three.js/commit/1017a5432eede4487436d6d34807fda24b506088

Bien, creo que podemos empezar con let y const en src/ .

@DefinitelyMaybe ¿Es esto algo en lo que le gustaría ayudar?

🎉 💯 demonios, ¡sí!

Solo quería plantear la preocupación de que si está cargando el código caliente, mi miedo es que la constante cause problemas. Si es cierto en todo JavaScript que los objetos sobrescriben totalmente const, entonces no hay problema. Por desgracia, si no es así, nunca se debe utilizar all const. Simplemente fusiono estructuras de objetos con funciones de código asignadas a claves de esos árboles de objetos (como estructuras), por lo que evito la necesidad de usar let o const en su mayor parte.
De todos modos, es algo en lo que pensar y básicamente creo que las const nunca deben usarse y son realmente desastrosas. Principalmente por mis preocupaciones con la carga de hotcode.
Aún así, creo que no son tan constantes como crees, así que tal vez alguien que entienda que más puede explicar que es una preocupación sin sentido con la recarga de importación o lo que sea. Gracias por su consideración y aportación.
¡Que sea el 'dejar'! Finalmente.

Crockford dijo que var fue un gran error, pero no se pudo cambiar, por lo que se creó 'let', pero var se considera defectuoso y el código de 'let' debería haber sido una solución para var, pero se habrían roto algunos casos de borde mal codificados. acechando en la naturaleza. El modo estricto y el izado son problemas relacionados con este tema.

@MasterJames no hay absolutamente ningún problema con la recarga en caliente cuando se usa const.

Trabajo en un entorno React y la recarga en caliente es la norma allí, así como const y let, que son el estándar hoy en día.

Estoy de acuerdo, esto no interferirá con la recarga en caliente. ¿Quizás ha confundido const con hacer objetos inmutables con Object.freeze ? No estamos planeando hacer eso.

¿Fue útil esta página
0 / 5 - 0 calificaciones