Three.js: Adoptez certaines fonctionnalités ES6

Créé le 16 avr. 2015  ·  74Commentaires  ·  Source: mrdoob/three.js

ES6 arrive, avec des navigateurs et des outils qui gagnent rapidement en support. Je pense que THREE.js pourrait bénéficier énormément de certaines des nouvelles fonctionnalités apportées par ES6.

Pour le plaisir et pour encourager le débat autour d'une éventuelle migration du projet, j'ai créé ce numéro et créé quelques exemples de code.

Fonctionnalités illustrées dans les exemples ci-dessous :

  • Paramètres par défaut
  • Mot clé let portée
  • Itérateurs + Pour..De
  • Des classes
  • Fonctions de flèche
  • Générateurs
  • Modules

Exemple de classe

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;

Exemple de générateur de parcours

class Object3D {
    constructor() {
        ...
    }

    traverse(callback) {
        callback(this);

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

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

    ...
}

Générateur en cours d'utilisation :

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

Remarque : je n'ai rien testé

Suggestion

Commentaire le plus utile

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

D'accord, je pense que nous pouvons commencer avec let et const dans src/ .

@DefinitelyMaybe Souhaitez -vous aider ?

Tous les 74 commentaires

Probablement un peu tôt ? La prise en charge n'est pas toujours excellente entre navigateurs : http://kangax.github.io/compat-table/es6/

let non exposé dans FF et pas dans 100% des situations dans Chrome et IE.
generators non disponible dans IE
class est uniquement dans Chrome, aperçu technique IE12 (Spartan) pour Win10 et FF39 qui est deux au-dessus de la version actuelle.
import n'est encore disponible nulle part
super n'est disponible que dans IE12, pas IE11, Chrome ou FF
arrow functions pas dans IE11 ou Chrome

De plus, les deux générateurs et for-of sont des tueurs d'optimisation pour Chrome

Imo aussi trop tôt juste pour une syntaxe plus sophistiquée. Discutable quand quelque chose sur la liste donnerait des gains de performances notables ou des avantages en termes de lisibilité du code. Peut-être que quelqu'un qui connaît la base de code et les fonctionnalités ES6 peut commenter cela.

Je suis un peu en retard à la soirée ES6. Cela ressemble à une langue différente pour moi. Je contribue régulièrement à Three.js mais si cela ressemblait aux extraits ci-dessus, je ne sais pas si je continuerais. Je n'ai tout simplement pas la patience d'apprendre une version de JavaScript d'apparence et de fonctionnement différents, qui fait essentiellement les mêmes choses que 'new function()' et 'object.prototype', mais peut-être plus lentement.

Est-ce ce que la communauté web demande au comité des langues de l'ES6 ? Je code depuis 20 ans et le mot 'classe' n'apparaît nulle part dans mes projets (et il ne le sera jamais si j'en ai ma volonté). Franchement, JavaScript commence à ressembler à JAVA... (script). :-\

Je suis avec @benaadams et @jonnenauha ; trop tôt, et cela pourrait ralentir le code si Chrome et Firefox n'optimisent pas fortement cette nouvelle version du langage comme ils optimisent déjà JavaScript sous le capot (V8, etc...).

:+1:

@erichlof Eh bien, j'attends le plus la prise en charge des classes et des modules ES6. J'utilise actuellement AMD pour mes applications. Le principal projet JS sur lequel je travaille est d'environ 10 000 lignes avec des centaines de "classes" et AMD est une bouée de sauvetage. Pendant le développement et la production des builds. Les projets Imo, grands ou même plus petits, doivent avoir une sorte de système de modules et un moyen pour que les choses déclarent de quoi elles dépendent. Cela devient trop compliqué à gérer une fois que vous avez une structure de projet complexe. Il ne faut pas laisser le programmeur déterminer dans quel ordre mettre 25x <script> tags. C'est tout simplement idiot une fois que vous avez la quantité de fichiers comme le fait three.js. La plupart des projets résolvent ce problème en créant un gros fichier js (comme three.js), puis il y a des dossiers aléatoires extras/helpers où vous pouvez inclure d'autres éléments. C'est quelque peu limitatif et je dois inclure une version d'environ 500 Ko (minifiée) pour obtenir ~ tout sous le soleil.

À un moment donné, je pense que trois ont ajouté la prise en charge d'AMD, mais ce n'est qu'un petit bloc de code qui détecte si AMD est utilisé et appelle une fonction au lieu de déclarer efficacement window.THREE. Je ne sais pas à quel point il est actuellement difficile de créer des versions personnalisées qui supprimeraient les fonctionnalités dont je n'ai pas besoin et ajouteraient des choses que je veux en dehors du noyau et les optimiseraient dans un seul fichier de travail qui charge les choses dans l'ordre.

Vous n'avez peut-être pas de "classe" dans vos projets, mais si vous utilisez object.prototype (comme le fait massivement three.js), c'est effectivement la même chose, êtes-vous d'accord ? Nous aimons assembler des objets et leur donner un but. Un autre code souhaite ensuite utiliser lesdits objets et un moyen déclaratif propre pour les importer.

Tout ce que je dis, les classes et modules ES6 seraient également un ajout intéressant à three.js pour lui donner plus de structure et de modularité pour les builds. C'est beaucoup trop tôt car, à ma connaissance, aucun navigateur ne prend en charge, par exemple. modules encore. D'autres pourraient dire qu'ils devraient simplement commencer à les utiliser et utiliser babel, etc. et produire des versions conformes à ES5, je ne sais pas si c'est une bonne idée, mais qui sait. Cela rend le développement plus difficile, vous devez démarrer automatiquement la construction lorsque vous enregistrez des fichiers, et le débogage peut également devenir plus complexe. Rien que pour ces choses, j'ai tendance à penser que ces transpileurs n'en valent pas la peine.

PS n'était pas une diatribe contre three.js, disant simplement qu'il pourrait y avoir des avantages dans ES6 pour des projets comme three.js une fois que le support du navigateur est là :) et surtout son sucre plus syntaxique que d'en faire un tout nouveau langage. Il y aura juste plus de choses.

Une autre fonctionnalité qui pourrait être bénéfique pour three.js est WeakMap et éventuellement WeakSet . Je ne suis pas sûr des implications, mais il semble que cela pourrait être utilisé pour suivre les choses sans que le GC fasse son travail si le "propriétaire" ne détient plus la référence. Il y a beaucoup d'états comme celui-ci dans three.js et son utilisation en interne peut faire la différence. Il me semble que c'est un peu similaire aux points partagés/faibles en C++ pour déclarer la propriété.

Un bon candidat pourrait être des choses comme https://github.com/mrdoob/three.js/blob/master/src/lights/SpotLight.js#L12 où cela pourrait être une référence faible et serait automatiquement effacé si la cible était retiré de la scène et récupéré. Mais je suppose que vous ne pourriez de toute façon pas dépendre de la collection, mais que vous auriez de toute façon besoin de l'annuler une fois la cible retirée de la scène.

Qui sait, j'attendrai que les experts écrivent des articles de blog sur la façon dont toutes ces fonctionnalités pourraient profiter aux applications en général :)

Salut @jonnenauha ,

Oui je suis d'accord que de nouvelles fonctionnalités comme 'import' et 'export' seront utiles, surtout en ce qui concerne la modularité. Je crois que c'est la direction que @coballast et @kumavis essaient de suivre pour rendre THREE.js plus modulaire et gérable pour les versions personnalisées et la maintenabilité du code. Je suis tout à fait pour les modules et la réutilisation d'objets et de fonctions, surtout lorsque nous avons un grand format de bibliothèque tel que THREE.js.

Cependant, je ne pense pas que nous ayons besoin du sucre syntaxique supplémentaire des classes, des fonctions super, let, for, of, fléchées, etc. déjà beaucoup de traction. Je suis peut-être archaïque mais je suis avec Douglas Crockford quand il dit que JavaScript est déjà un langage orienté objet (c'est-à-dire fonctions = objets = citoyens de première classe), mais pas un langage "classique" - nous ne devrions donc pas nous préoccuper de cours de chausse-pied en JavaScript. Il a été conçu avec une approche différente - une approche qui m'a d'abord surpris (venant de la programmation C/C++ dans les années 1990), mais avec laquelle je suis de plus en plus d'accord à chaque fois que je m'assois pour coder ou essayer de résoudre l'architecture du code problèmes.

Au lieu de modifications syntaxiques de THREE.js, je préférerais une migration vers des fonctionnalités telles que la nouvelle interface de programmation SIMD. Je pense que TOUS les codes mathématiques de TROIS (en particulier Vector3 et Matrix4) pourraient grandement en bénéficier. Voici un lien vidéo (consultez 22:51 dans le time code) :
https://youtu.be/CbMXkbqQBcQ?t=1371
Lorsque cette fonctionnalité atterrira dans les principaux navigateurs, chaque utilisateur de THREE.js verrait en conséquence une accélération notable de sa fréquence d'images.

Désolé si mon message précédent ressemblait à une diatribe, j'aime juste THREE.js à quoi il ressemble maintenant - je peux facilement sélectionner n'importe quelle partie aléatoire et savoir ce qui se passe, d'où il vient et ce qu'il utilise. :)

@erichlof @jonnenauha Je me sens obligé de souligner que les classes es6 ne sont que du sucre et qu'elles utilisent en interne le mécanisme de prototype pour tout implémenter au moment de l'exécution.

Je suis assez optimiste sur le fait que les fonctionnalités es6 n'auront pas d'impact sur les performances de calcul. Les modules es6 peuvent affecter le temps de chargement lorsqu'ils sont finalement implémentés par les moteurs, car vous récupérez un tas de petits fichiers plutôt qu'un seul gros fichier. HTTP/2 pourrait cependant en faire un non-problème. Dans tous les cas, si nous utilisons des modules es6, nous pouvons utiliser browserify pour créer un bundle comme nous le faisons toujours.

Personnellement, je suis pour l'utilisation de la syntaxe es6 dans la base de code autant que possible, car cela rendrait le code plus concis et réduirait les erreurs. Je pense que beaucoup de gens ont tendance à abuser de la chaîne de prototypes et à l'utiliser de manière incorrecte. Je n'ai pas un bon exemple cependant.

Je pense aussi que rester assis et attendre que es6 soit implémenté dans les moteurs est une mauvaise idée. Les transpileurs sont disponibles dès maintenant et produisent de bons résultats qui s'exécutent dans les navigateurs dès maintenant. Je pense que les avantages de faire cela sont énormes, nous devrions donc être impatients et commencer à travailler dessus immédiatement.

Je ne pense pas que déplacer manuellement le code soit une bonne idée. Comme l'a dit Doug McIlroy, l'inventeur des pipes Unix et généralement un demi-dieu :
"Utilisez des outils de préférence à une aide non qualifiée pour alléger une tâche de programmation, même si vous devez faire un détour pour construire les outils et vous attendre à en jeter certains une fois que vous avez fini de les utiliser."

J'encourage toute personne intéressée par es6 à participer et à contribuer à ce dépôt : https://github.com/5to6/5to6

Je ne suis pas d'accord sur la conversion de l'ensemble de la bibliothèque en un sous-ensemble différent de javascript. Comme toujours, nous devons discuter de ce qui est possible et des avantages et inconvénients. Parce que les performances vont différer entre les versions.

Par exemple, les cartes faibles sont quelque chose qui serait un gain énorme dans les moteurs de rendu pour gérer les états des objets. Ses plus gros inconvénients étaient un polyfill faible et très peu de support de navigateur et des caractéristiques de performances inconnues. (Cela fait un moment que je n'ai pas enquêté là-dessus, donc il y a de fortes chances que cela ait changé)

Et nous ne devrions pas seulement regarder es6. Par exemple, ams.js serait génial comme technologie qui exécute un moteur de rendu logiciel. Pour plus d'informations, http://stackoverflow.com/questions/18427810/three-and-asmjs/18439786#18439786.

Et il ne faut pas oublier que la plupart des contributeurs contribuent principalement car javascript est familier et es6 ne l'est pas encore pour la plupart.

@gero3 Ce sont de bons points auxquels je n'ai pas pensé. Si nous parlons de micro optimisation, je suis à 100% d'accord avec vous. Je ne voudrais pas profiter de ces fonctionnalités sans la prise en charge du navigateur.

En grande partie, ce dont je parlais ci-dessus était d'utiliser du sucre syntaxique qui a une sémantique identique aux fonctionnalités es5 existantes, et qui pourrait donc être construit avec des transpileurs sans trop affecter les performances.

METTRE À JOUR:
Peut-être que personne ne s'en soucie, mais j'ai changé d'avis. Je crois que nous ne devrions pas utiliser les classes. Je pense toujours que les modules es6 sont une bonne idée.

Je suis totalement en faveur des cours. J'obtiens toutes les choses merveilleuses que le prototype d'objet en JavaScript peut faire. Cependant, dans THREE.js (et dans de nombreux autres projets de système d'exploitation modernes), nous utilisons l'héritage prototypique pour simuler des classes, alors pourquoi ne pas avoir la belle syntaxe pour l'accompagner et nous débarrasser des trucs bidons comme :

THREE.Object3D.call( this );

et

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

Dès que les classes seront prises en charge dans Chrome et Firefox stables, cela ne me dérangerait pas d'envisager de mettre à jour le code 😊

@mrdoob Les classes sont prises en charge dans Chrome 42 stable aujourd'hui et Firefox 39 disponible en juin pour info

Safari sur iOS semble être celui qui traîne de nos jours... 😣

Les cours sont incroyables, tout comme les autres fonctionnalités ES7. Nous les utilisons dans l'un de nos projets, mais nous avons dû introduire un compilateur croisé (babel.js) car nous devons fonctionner sur tous les navigateurs - Chrome, Firefox, IE et Safari.

Il existe une transformation browserify pour exécuter babel.js (babelify), donc cela fonctionnerait bien avec mes efforts.

Juste par curiosité, est-ce que le travail a commencé sur certains d'entre eux ? :)

non car nous ne connaissons toujours pas les implications sur la vitesse de ceux-ci.

Ma compréhension est transpilée ES6 n'est généralement pas performant et donc pas pour la production jusqu'à ce qu'il soit implémenté dans le navigateur. Cela dit, les nouveaux projets ou modules devraient adapter ces commodités aujourd'hui, mais les performances doivent être prises en compte dans cette décision.

Je suis d'accord avec @erichlof imo, l'implémentation la plus utile serait SIMD (https://github.com/tc39/ecmascript_simd), même en utilisant le polyfill. Il semble que les utilisateurs en bénéficieraient le plus.

Où SIMD s'intégrerait-il dans ThreeJS ? Je pense que ThreeJS décharge déjà tous les calculs importants sur le GPU. Bien que je puisse en quelque sorte comprendre son utilisation sur les classes Vector, il y a très peu de calculs qui sont réellement effectués dans ThreeJS, la plupart du temps, ces vecteurs sont simplement transportés vers le GPU.

Je parle d'expérience car j'ai déjà implémenté des extensions SSE2/SSE4 et j'ai constaté que les avantages étaient éphémères dans la majorité des cas - les seuls cas réels où c'était un avantage, c'était lorsque j'avais de grandes baies sur lesquelles je voulais faire la même chose opération.

Salut @bhouston ,
Est-ce la même chose pour les opérations Matrix ? Quand je pensais à SIMD, je pensais que les opérations matricielles 4 X 4 en bénéficieraient le plus. Et comme nous le savons tous, des matrices sont utilisées à chaque image d'animation dans Three.js du côté JavaScript/CPU, quelle que soit la complexité de l'application.

Si les gars de Babylon.js ne s'en soucient pas, voici un indice sur la façon de démarrer tout cela :
https://github.com/BabylonJS/Babylon.js/blob/master/src/Math/babylon.math.js#L2030 -L2093

Je pense qu'une seule matrice multiple si vous devez convertir le format est probablement un perdant. Si vous avez toujours vos matrices au format SIMD, cela peut être un avantage.

Mais même ainsi, Matrix n'est souvent pas optimal car vous devez multiplier les colonnes par les lignes, ce qui nécessite une opération de réorganisation.

J'ai constaté que la plupart des efforts d'optimisation SIMD (à l'exception des grands tableaux avec des opérations homogènes) n'en valent pas la peine, mais je suis d'accord avec les autres qui font des tests pour le savoir.

Le code résultant est également difficile à déboguer et à maintenir.

Une stratégie qui peut fonctionner consiste à faire en sorte que tous les vecteurs et matrices utilisent une disposition de mémoire compatible SIMD comme représentation native - c'est ce que Quake 3 croyait dans sa bibliothèque mathématique. Mais ensuite, vous devez utiliser 4 flotteurs pour les types vec2 et vec3 pour plus d'efficacité, mais cela devient alors problématique lorsque vous souhaitez télécharger sur le GPU car vous avez maintenant des flotteurs supplémentaires sur le chemin.

Je vois ce que vous voulez dire, merci pour votre perspicacité et votre expertise. Être impressionné par la présentation SIMD.js il y a quelque temps, la coller dans trois.js et la maintenir sont deux choses différentes, je suppose. Il serait intéressant, comme vous l'avez dit, d'avoir des comparaisons de performances. Peut-être que les bibliothèques de physique comme Cannon.js et Oimo.js , qui sont utilisées en conjonction avec three.js, tireraient plus d'avantages de SIMD ?

@bhouston Ahh ok cela a du sens, certains points de repère seraient cependant assez intéressants.

@erichlof si vous êtes intéressé, j'ai lancé une branche, https://github.com/Globegitter/three.js/tree/include-SIMD , où j'ai commencé à remplacer Vector3 par SIMD. C'est toujours un WIP lourd et mon temps est limité, nous allons donc savoir jusqu'où j'irai. De plus, en utilisant le dernier Firefox nightly, vous pouvez exécuter ce code sans polyfill (où l'implémentation native est apparemment environ 20 fois plus rapide que le polyfill : https://blog.mozilla.org/javascript/2015/03/10/state -of-simd-js-performance-in-firefox/).

@erichlof @jonnenauha Je me sens obligé de souligner que les classes es6 ne sont que du sucre et qu'elles utilisent en interne le mécanisme de prototype pour tout implémenter au moment de l'exécution.
Je suis assez optimiste sur le fait que les fonctionnalités es6 n'auront pas d'impact sur les performances de calcul.

Vous pourriez être un peu rapide pour conclure que : Il existe en effet différents chemins de code pour ES6 dans chaque moteur JS dans l'implémentation (assez complexe) des objets JS.

Les modules es6 peuvent affecter le temps de chargement lorsqu'ils sont finalement implémentés par les moteurs, car vous récupérez un tas de petits fichiers plutôt qu'un seul gros fichier. HTTP/2 pourrait cependant en faire un non-problème.

Les clients peuvent toujours vouloir utiliser la compression au niveau JS de l'ensemble de l'application pour réduire la bande passante du réseau et protéger leur propriété intellectuelle.

Faire comprendre au compilateur de fermeture Three.js permettrait de compiler vers ES6 et de voir quand le moment est venu de basculer, ainsi que de nombreux avantages supplémentaires. Je pense que c'est là que devraient aller les efforts de ce genre pour l'instant...

Mais même ainsi, la multiplication par matrice [SIMD] n'est souvent pas optimale car vous devez multiplier les colonnes par les lignes, ce qui nécessite une opération de réorganisation.

Les jeux d'instructions SIMD ont souvent une instruction "multiplier par scalaire et ajouter", pour implémenter une multiplication matricielle comme celle-ci :

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 multiplication matricielle consiste en fait à appliquer une transformation aux vecteurs colonnes de l'opérande de droite. Maintenant, les transformations peuvent être considérées soit comme un ensemble de produits scalaires (la manière déroutante que nous utilisons habituellement avec un stylo et du papier), soit comme une combinaison linéaire des vecteurs d'axe de l'espace de destination = vecteurs de colonne du côté gauche opérande.

@Globegitter Wow, c'est un super début ! Je vais obtenir Firefox Nightly pour pouvoir également expérimenter avec la nouvelle branche !

@Globegitter J'aime quand quelqu'un va de l'avant et fait quelque chose quand il y croit. Le code règle les points de vue divergents plus rapidement que la discussion.

où l'implémentation native est apparemment ~20 fois plus rapide par rapport au polyfill

Serait intéressé de voir aussi à quel point le polyfill est plus lent par rapport aux non-SIMD

Je vais obtenir Firefox Nightly pour pouvoir également expérimenter avec la nouvelle branche !

Devrait également pouvoir l'essayer dans Edge en activant expérimental et asm.js dans about:flags

@Globegitter Je pense que votre éditeur modifie les espaces blancs menant à des différences vraiment désagréables : https://github.com/Globegitter/three.js/commit/d835ca3a22eed4ed4603534773ae55c29d5a8026

Je remarque que vous faites le type SIMD comme side car :

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

Puis-je suggérer que vous changiez simplement Vector3 x, y, z en getter/setters et stockiez uniquement un float32x4? Je pense qu'une telle approche peut être beaucoup plus facile à mettre en œuvre avec moins de changements.

Je ne suis pas sûr de la meilleure façon de définir les propriétés mais mrdoob fait quelque chose comme ça ici :

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

Avoir le SIMD comme type de stockage principal derrière un type mathématique est probablement le plus efficace, aucune conversion supplémentaire n'est requise. Voici la bibliothèque mathématique Bullet Physics SSE si vous avez besoin d'un guide sur les opérations vectorielles/matrices standard :

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

@bhouston , merci pour ces notes. J'étais en quelque sorte juste là pour voir jusqu'où j'irais en quelques heures sans avoir beaucoup travaillé avec trois et SIMD auparavant (nous l'utilisons dans la plupart de nos projets). Donc, ce retour de quelqu'un qui en connaît trois est vraiment apprécié. Et oui, je dois désactiver cela dans mon éditeur.

@tschw merci pour la note sur les maths matrice/vecteur ! Tu as raison c'est mieux.

@Globegitter Voici un meilleur exemple de setter/getter sur le prototype d'un objet : https://github.com/mrdoob/three.js/blob/master/src/core/Object3D.js#L83

Quelques centimes pour travailler sur ES2015 (principalement en nœud)

  • il y a des endroits où les moteurs Javascript (par exemple V8) ont besoin de rattraper leur retard en optimisant les fonctionnalités d'ES6
  • d'après mon expérience, un code comme let x = 1, y = 2 désoptimiserait la v8 bien que je m'attendrais à ce que la v8 la supporte éventuellement
  • le code transpilé vers ES5 peut être exécuté plus lentement que le code ES6 (c'est pourquoi je préfère utiliser uniquement les fonctionnalités ES6 prises en charge dans > nœud 4, c'est presque tout sauf le système d'import-export)
  • Les cartes et les ensembles sont des gains de performance
  • Les cours sont sympas
  • L'utilisation de Babel peut être pénible pour votre flux de travail, cela ne vaut probablement pas la peine si vous utilisez ES6 uniquement pour le sucre de syntaxe

Il y a six mois, j'ai converti certaines fonctions Three.js (multiplication de matrice 4x4, Vector4, etc.) en SIMD et vous pouvez les essayer. À un moment donné, cela fonctionnait comme un bookmarklet, mais peut maintenant nécessiter une actualisation pour fonctionner avec la dernière version de Three.

  • Firefox Nightly prend en charge le SIMD natif prêt à l'emploi
  • Chrome avec indicateur --js-flags="--harmony-simd" prend en charge le polyfill JS de SIMD, il sera donc plus lent que la version non-simd. Au moins, vous pouvez vérifier si cela fonctionne et expérimenter!

350% de gain de performances est un MENSONGE :)

J'ai aussi porté une partie de Vector3 mais c'est commenté.

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

Edit : j'ai une version plus à jour quelque part sur mon disque dur donc je mettrai à jour ce projet bientôt

Super regarder et regarder un +1 à ça.
Ce qui serait génial, c'est un système qui vérifie les performances et active ou désactive ces fonctionnalités en fonction de ces performances.

Ce qui serait génial, c'est un système qui vérifie les performances et active ou désactive ces fonctionnalités en fonction de ces performances.

Je suppose que l'on aurait deux définitions Vector3 dans le module Vector3 et que vous renverriez conditionnellement l'une ou l'autre selon que SIMD est natif? Je suppose que cela fonctionnerait, mais cela augmenterait le côté téléchargement. Peut-être que vous pourriez juste avoir quelques fonctions qui changent selon que SIMD est disponible - probablement SIMD n'est le plus important que pour un petit sous-ensemble de fonctions mathématiques. Si c'était petit en termes de code total, cela peut valoir la peine de le mettre maintenant. Mais il doit être facultatif afin qu'il ne devienne pas lent lorsque SIMD n'est pas disponible.

Nous pourrions commencer par faire une version SIMD de Matrix4 de multiplyMatrices() car c'est actuellement la méthode la plus appelée dans les scènes complexes.

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

screen shot 2016-08-30 at 20 46 29

@mrdoob regarde ici c'est fait.
https://github.com/DVLP/three.turbo.js/blob/master/src/three.turbo.js

Essayez comme 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);})()

Le morceau de code 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);
          }
}

Lorsque j'ai testé ce semestre il y a six mois, j'ai remarqué que la version avec la boucle "for" dépliée était un peu plus rapide. C'est pourquoi dans ma petite bibliothèque la boucle est commentée et la version codée en dur est présente.

Il y a plus de fonctions dans la branche "inverse"
https://github.com/DVLP/three.turbo.js/blob/inverse/src/three.turbo.js

Quelle est la différence de performances ?

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

Ça dépend. Dans Nightly quand le nombre de calculs est petit (<1000) alors le résultat est 3 fois plus lent. Lorsque le nombre de calculs est supérieur à 10 000, la vitesse est ~ 40 % plus rapide

Dans Chrome avec le drapeau --js-flags="--harmony-simd" activé, il n'y a pas de vrai SIMD, mais un polyfill JavaScript donc évidemment la vitesse est beaucoup plus lente pour le moment.

Un bon endroit pour tester serait le projet Crosswalk (basé sur Chromium). Ils ont un vrai SIMD pour Android, donc cela pourrait être une expérience intéressante de construire un projet avec le code de ce JSFiddle pour voir quel serait le résultat.

Vous ne voudrez peut-être pas inclure le polyfill simd de toute façon sur vos pages d'exemple. Juste un peu plus pratique pour les gens de les essayer. Enregistrez une ligne dans la console ou mettez du texte à l'écran lorsqu'aucun natif n'est disponible (le polyfill laisse probablement quelques indices indiquant qu'il est activé).

Je ne peux pas imaginer pourquoi Chrome chargerait simplement le polyfill js simd avec --js-flags="--harmony-simd" , cela n'a aucun sens alors que cela peut déjà être fait dans le domaine de l'utilisateur ?! Quel est l'avantage de cela. Peut-être qu'ils commenceront à mettre des trucs progressivement. Où avez-vous lu ce qui se passe réellement avec le drapeau, de bons liens? Semble être "en développement" ici https://www.chromestatus.com/features/5757910432874496

Edit : Au sujet actuel : j'imagine qu'il est très difficile de mettre ce truc dans three.js si la perf est partout, de quelques objets à beaucoup d'objets. Si toutes les implémentations peuvent améliorer les performances avec 1 à N objets, la fonctionnalité doit être détectée et utilisée là où cela a du sens. Si les impls natifs sont incohérents, je ne vois pas le tout aller nulle part, alors pourquoi s'embêter à y travailler, passer les heures de développement sur quelque chose de plus productif.

trois peuvent sauter dessus quand il arrive à maturité, ou est-ce que le support de three.js pourrait conduire les implémentations de navigateur à faire mieux ? Je pense que le moteur irréel et d'autres cas d'utilisation de simulation/mathématiques seraient la force motrice pour les fournisseurs de navigateurs, pas particulièrement le nombre de bibliothèques souhaitant utiliser la fonctionnalité. Mais qui sait.

Je ne peux pas imaginer pourquoi Chrome chargerait simplement le polyfill js simd avec --js-flags="--harmony-simd"

Je pense que c'est une pratique assez courante que les navigateurs procèdent de cette façon, afin que les utilisateurs puissent commencer à tester les choses. Par exemple, si je comprends bien, c'est ainsi que WASM sera initialement introduit dans les navigateurs.

Tous les arguments qui soutiennent l'inévitabilité qu'un centurion est nécessaire. Surveillance en temps réel des performances qui peut activer ou désactiver des fonctionnalités et déterminer les performances optimales. Ainsi, même la densité de la carte d'ombre devrait changer en fonction de la distance de la caméra, etc. De toute façon, je sais que le consensus a décidé que ce serait un outil tiers et non nécessaire. Pourtant, je veux juste garder ce point dans l'esprit conscient sinon subconscient.
Peut-être que vous vérifiez juste un pollyfill et désactivez SIMD, mais encore une fois, FPS dit tout. Les priorités d'activation ou de désactivation sont probablement les meilleures en tant que préférence spécifique à l'utilisateur/à l'application. Merci pour l'écoute! J'attends avec impatience un meilleur GL plus rapide dans un proche avenir. Soyons prêts à surpasser les autres.

Il semble que le processus de chargement des données sur SIMD puisse créer une surcharge qui défie l'avantage d'utiliser SIMD dans Nightly. Je suis très curieux de connaître les performances dans Chrome, mais le dernier Chromium avec un vrai SIMD est ici http://peterjensen.github.io/idf2014-simd/
C'est vieux.

Mettre à jour:
maintenant SIMD fonctionne également dans Edge. Vous pouvez l'activer en allant à about:flags et en cochant "Activer les fonctionnalités JavaScript expérimentales" (redémarrer Edge)
Je ne sais pas s'il s'agit d'un vrai SIMD ou d'un polyfill. Ce test rend le SIMD ~ 40% plus lent sur ma machine :/ https://jsfiddle.net/tk6zx5dm/6/

variation du test avec des objets SIMD mis en cache dans l'objet Matrix4, je ne sais pas si cela sera un jour utile
https://jsfiddle.net/tk6zx5dm/15/
Ce qui est intéressant, c'est que le code avec les objets SIMD mis en cache est _parfois_ plus rapide même dans Chrome qui utilise polyfill SIMD (...? bizarre)

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]
          )
        )
      )
    );
  }
}

Mise en cache - doit probablement être exécutée sur chaque updateMatrix(), ce qui peut ralentir l'ensemble de la solution à la fin

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]));
  }
};

Je suis curieux de savoir si le style ES6 a été revisité ? L'ensemble du code est inutilisable en direct pour le moment sans exécuter un concaténateur, alors pourquoi ne pas également exécuter babel et commencer à utiliser des éléments ES6 le cas échéant ?

L'ensemble du code est inutilisable en direct pour le moment sans exécuter un concaténateur, alors pourquoi ne pas également exécuter babel et commencer à utiliser des éléments ES6 le cas échéant ?

Principalement en raison du manque de tests sur l'impact sur les performances du code produit par babel. De plus, j'ai entendu dire que V8 produisait un code plus rapide lors de l'utilisation de var au lieu de let/const.

Pour info : j'ai récemment commencé à essayer bublé qui "se limite aux fonctionnalités ES pouvant être compilées en ES5 compact et performant".

Le bas de ce lien aide à expliquer var vs let dans les boucles
http://stackoverflow.com/questions/21467642/is-there-a-performance-difference-between-let-and-var
Personnellement, j'attends que les solutions sans transpileur arrivent sur le navigateur. comme pour 'attendre' le plus tôt sera le mieux, mais pour l'instant peut-être que cela devrait être écrit de cette façon et passer (horriblement défiguré par) un transpiler, mais si cela fonctionne dans Chrome ?! donc tester pour d'autres navigateurs ? Je dis 'Laissez-les manger du gâteau... ou utilisez Chrome.' (mon expression préférée).
Je pense que 'let' devrait être utilisé si c'est dans la situation où il est préférable de prouver par des tests qu'il est préférable de le faire.
Je suppose que c'est comme si 'var' était hissé pour éviter la portée, mais vous voudrez peut-être cela et ensuite 'let' est le mieux. Je pense/espère que « let » devrait également réduire votre empreinte mémoire dans certaines situations.

Le code transpilé ne sera jamais aussi rapide qu'optimisé à la main. C'est dommage que JSPerf soit en panne. J'avais l'habitude de le visiter plus souvent que Google.
Edit : JSPerf.com n'est pas en panne ! J'ai juste supposé qu'il était mort pour toujours après qu'il n'ait pas fonctionné pendant un an
let 3x plus lent que var dans mon Chrome Canary : https://jsperf.com/let-vs-var-performance/14
dans Firefox et Edge aucune différence de vitesse mais Chrome est le plus important.
Quelqu'un peut-il tester dans Safari ?

Les cours ont l'air super et modernes! Est-ce que quelqu'un sait si c'est déjà au programme ?

@ Rubinhuang9239 Je n'ai vu personne

laissez 3x plus lent que var dans mon Chrome Canary : https://jsperf.com/let-vs-var-performance/14

Pour ce que ça vaut, let et const sont maintenant légèrement plus rapides que var pour moi sur Chrome 66, Firefox 59 et Edge 42, en utilisant ce test.

Je pense que le changement de classe devrait être très simple - le gros du travail a été l'adoption du rollup qui a été fait il y a un certain temps. Je ne serais pas surpris qu'un héros puisse implémenter des classes dans ThreeJS en quelques heures.

Eh bien, il y a beaucoup de cours, alors peut-être que cela prendra environ 8 heures si vous le faites manuellement.

Peut-être commencer petit et convertir les cours de mathématiques d'abord et faire un PR. Si cela fonctionne, passez aux autres.

@looeee ça fait plus d'un an, donc pas de surprise, ES6 a réussi à rattraper ses performances

2019 est l'année pour enfin commencer à adopter du code ES6 dans les exemples/docs, n'est-ce pas @mrdoob ? ??

ES6 est la norme depuis un certain temps maintenant, les nouveaux développeurs apprennent ES6. Nous pouvons également arrêter de prendre en charge IE11 dans les exemples, comme vous en avez discuté dans #16220, quels développeurs examinent les exemples de three.js utilisant IE11 ? ??

Je pense que les fonctionnalités les plus nécessaires pour simplifier le code pour les nouveaux arrivants sont les classes et les chaînes de modèles, sans oublier le const/let désormais par défaut.

Je peux contribuer si nous décidons de commencer.

Pas à pas. Commençons par mettre à jour les exemples pour utiliser three.module.js pour le moment.

Pas à pas. Commençons par mettre à jour les exemples pour utiliser three.module.js pour le moment.

Cette étape est terminée depuis un certain temps maintenant. Peut-être est-il temps de passer officiellement à l'étape suivante ?

Deux candidats :

  1. const/let
  2. Des classes

Étant donné que les classes sont déjà utilisées dans les géométries des boîtes depuis un certain temps maintenant, je vote pour le faire en premier. Ou nous pourrions faire les deux en même temps.

Connexe : #11552, #18863

Si je comprends bien, le problème est que nous ne pouvons rien convertir en classes ES6 si elles sont étendues par des exemples, jusqu'à ce que les exemples soient également convertis. Et cela pourrait signifier attendre que examples/js soit parti ? A moins que nous puissions confirmer que le script modularize prendra en charge les classes, pour convertir les fichiers examples/js en même temps que leurs classes parents.

D'après ce que je comprends, examples/js est une sorte de toutes les fonctionnalités en excès qui sont néanmoins intéressantes, mais qui si nous sommes tous combinés dans le src/... , le gonfleraient de manière disproportionnée. La réponse à la question « Fournissons-nous des exemples/scripts de x, y, z ? » est-elle inhérente. Je risque de supposer que la réponse de three.js est principalement oui, mais en tant que matériel pédagogique sur le site Web. Supprimer examples/js semble hors de question à ce stade. Bien que j'ai peut-être mal compris comment examples/js est référencé/utilisé 🤔 faites le moi savoir.

Laissant examples/js comme seul site Web/éducation manque une partie de ce que pourrait être ce dossier, c'est-à-dire des scripts/contenu/projets/autres communautaires que les gens aimeraient partager mais je ne suis pas au courant d'un endroit qui double cette.

Je digresse.

jusqu'à ce que les exemples soient également convertis.

J'aime le son de ceci comme notre prochaine meilleure étape intermédiaire.

@DefinitelyPeut-être que nous ne examples/js , il y a deux répertoires à noter :

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

Le premier contient des fichiers hérités, le dernier contient des modules ES générés à partir de ces fichiers, avec la même fonctionnalité. Nous finirons par supprimer le premier. Le script qui effectue la conversion ne prend actuellement pas en charge les classes ES. Ainsi, jusqu'à ce que cela soit supprimé, les fichiers dans examples/js ne peuvent pas être convertis en classes ES. Certains d'entre eux étendent les fichiers dans src/ , et vous ne pouvez pas étendre les classes ES sans utiliser les classes ES, il s'agit donc d'une dépendance bloquante.

ah, j'ai été confus par le commentaire précédent

Et cela pourrait signifier attendre que examples/js soit parti ?

a du sens maintenant.

modularize.js me rappelle mon projet initial qui m'a amené ici. Convertisseur . J'ai vu des commentaires ici sur le passage aux classes ES6, alors j'ai pensé que je devais me lancer ici à la place.

Donc, si examples/js étend src d'une manière ou d'une autre, les deux doivent être convertis en classes ES6 en même temps
ou...
travailler sur modulariser jusqu'à ce qu'il génère des classes/es6?

nous ne pouvons rien convertir en classes ES6 si c'est étendu par des exemples

Il y a encore beaucoup de choses dans le noyau qui ne sont pas étendues dans les exemples, pourquoi ne pas commencer par ça ?

Cela me semble bien.

@ Mugen87 y avait-il autre chose bloquant le changement de classe ES, ou juste cela?

Il y a encore beaucoup de choses dans le noyau qui ne sont pas étendues dans les exemples, pourquoi ne pas commencer par ça ?

Liste de scripts non prolongée par des exemples .

edit : la liste a été mise à jour !

Les bloqueurs sont des sections comme celles-ci :

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

L'utilisation de THREE.<class>.call et Object.create( THREE.<class> serait les modèles les plus probables. Ce qui signifierait que Loader, EventDispatcher et PerspectiveCamera (parmi probablement beaucoup d'autres) ne peuvent pas encore être convertis en classes.

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

D'accord, je pense que nous pouvons commencer avec let et const dans src/ .

@DefinitelyMaybe Souhaitez -vous aider ?

hellz ouais !

Je voulais juste soulever une préoccupation selon laquelle si vous chargez du code à chaud, ma crainte est que la const causera des problèmes. S'il est vrai dans tout JavaScript que les objets écrasent totalement const, alors pas de problème. Hélas, s'ils ne le font pas, tous les const ne devraient jamais être utilisés. Je fusionne simplement les structures d'objets avec les fonctions de code affectées aux clés de ces arbres d'objets (comme les structures), j'évite donc d'avoir à utiliser let ou const pour la plupart.
Quoi qu'il en soit, c'est quelque chose à quoi il faut penser et je crois fondamentalement que const ne devrait jamais être utilisé et qu'il n'est vraiment pas effrayant. Principalement pour mes soucis avec le chargement de hotcode.
Pourtant, je pense qu'ils ne sont pas aussi constants que vous le pensez, alors peut-être que quelqu'un qui comprend mieux cela peut expliquer que c'est une préoccupation dénuée de sens avec le rechargement des importations ou autre. Merci pour votre considération et votre contribution.
Qu'il y ait « laissez » ! Finalement.

Crockford a déclaré que var était une grosse erreur mais qu'elle ne pouvait pas être modifiée, donc 'let' a été créé mais var est considéré comme défectueux et le code de 'let' aurait dû être un correctif pour var, mais cela aurait cassé quelques cas marginaux mal codés. tapi dans la nature. Le mode strict et le levage sont des problèmes autour de ce sujet.

@MasterJames, il n'y a absolument aucun problème avec le rechargement à chaud lors de l'utilisation de const.

Je travaille dans un environnement React et le rechargement à chaud y est la norme, ainsi que const et let, qui sont la norme de nos jours.

Je suis d'accord, cela n'interfère pas avec le rechargement à chaud. Peut-être avez-vous confondu const en rendant les objets immuables avec Object.freeze ? Nous n'avons pas l'intention de le faire.

Cette page vous a été utile?
0 / 5 - 0 notes