Three.js: Adote alguns recursos ES6

Criado em 16 abr. 2015  ·  74Comentários  ·  Fonte: mrdoob/three.js

O ES6 está chegando, com navegadores e ferramentas ganhando suporte rapidamente. Eu acho que THREE.js poderia se beneficiar enormemente com alguns dos novos recursos trazidos pelo ES6.

Para se divertir e estimular o debate em torno de uma possível migração do projeto, criei este problema e criei alguns exemplos de código.

Recursos demonstrados nos exemplos abaixo:

  • Parâmetros padrão
  • Palavra-chave com escopo de bloco let
  • Iteradores + For..Of
  • Aulas
  • Funções de seta
  • Geradores
  • Módulos

Exemplo 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;

Exemplo de gerador transversal

class Object3D {
    constructor() {
        ...
    }

    traverse(callback) {
        callback(this);

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

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

    ...
}

Gerador em uso:

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

Nota: Eu não testei nada disso

Suggestion

Comentários muito úteis

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

Ok, acho que podemos começar com let e const em src/ .

@DefinitelyMaybe É algo que você gostaria de ajudar?

Todos 74 comentários

Provavelmente um pouco mais cedo? O suporte não é consistente em todos os navegadores: http://kangax.github.io/compat-table/es6/

let não exposto no FF e não em 100% das situações no Chrome e IE.
generators não disponível no IE
class está apenas no Chrome, visualização técnica do IE12 (Spartan) para Win10 e FF39, que é dois acima da versão atual.
import ainda não está disponível em nenhum lugar
super está disponível apenas no IE12, não no IE11, Chrome ou FF
arrow functions não está no IE11 ou no Chrome

Além disso, ambos os geradores e for-of são assassinos de otimização para o Chrome

Imo também é muito cedo apenas para uma sintaxe de aparência mais sofisticada. Discutível quando algo na lista daria ganhos de desempenho perceptíveis ou benefícios de legibilidade do código. Talvez alguém que conheça a base de código e os recursos do ES6 possa comentar sobre isso.

Estou um pouco atrasado para a festa ES6. Isso parece um idioma diferente para mim. Eu contribuo regularmente com o Three.js, mas se parecesse com os trechos acima, não sei se continuaria. Eu simplesmente não tenho paciência para aprender uma versão de JavaScript com aparência e funcionamento diferentes, que basicamente faz as mesmas coisas que 'new function ()' e 'object.prototype', mas possivelmente mais lenta.

É isso que a comunidade da web tem exigido do comitê de idiomas do ES6? Estou programando há 20 anos e a palavra 'classe' não aparece em nenhum lugar dos meus projetos (nem aparecerá se eu tiver meu caminho). Francamente, JavaScript está começando a se parecer com JAVA ... (script). : - \

Estou com @benaadams e @jonnenauha ; muito cedo, e pode tornar o código lento se o Chrome e o Firefox não otimizarem fortemente esta nova versão da linguagem, como se já estivessem otimizando o JavaScript nos bastidores (V8, etc ...).

: +1:

@erichlof Bem, na verdade estou esperando mais pelo suporte para classes e módulos ES6. Atualmente, estou usando AMD para meus aplicativos. O principal projeto JS em que trabalho é de aproximadamente 10 mil linhas com centenas de "classes" e a AMD é um salva-vidas. Durante o desenvolvimento e na produção de compilações. Os projetos Imo grandes ou até menores precisam ter algum tipo de sistema de módulo e uma maneira de as coisas declararem do que dependem. Ele fica muito complicado de gerenciar, uma vez que você tem uma estrutura de projeto complexa. Não deve ser deixado para o programado descobrir em que ordem colocar as tags <script> 25x. Isso é simplesmente bobo, uma vez que você tem a quantidade de arquivos como o three.js tem. A maioria dos projetos resolve isso construindo um grande arquivo js (como three.js) e então há uma pasta extras / auxiliares aleatórios onde você pode incluir outras coisas. Isso é um pouco limitante e eu tenho que incluir uma compilação de ~ 500kb (minimizada) para colocar ~ tudo sob o sol.

Em um ponto eu acho que três adicionaram suporte a AMD, mas isso é apenas um pequeno bloco de código que detecta se AMD é usado e chama uma função em vez de efetivamente declarar window.THREE. Não sei como é difícil fazer builds personalizados que eliminariam funcionalidades de que não preciso e adicionar coisas que desejo fora do núcleo e otimizá-las para um único arquivo de trabalho que carregue as coisas em ordem.

Você pode não ter "classe" em seus projetos, mas se usar object.prototype (como o three.js faz muito) é efetivamente a mesma coisa, você concorda? Gostamos de colocar objetos juntos e dar-lhes um propósito. Outro código então deseja usar esses objetos e uma forma declarativa limpa de importá-los.

Tudo o que estou dizendo que classes e módulos ES6 seriam uma boa adição também ao three.js para dar a ele um pouco mais de estrutura e modularidade para compilações. É muito cedo demais porque afaik não há suporte para navegadores, por exemplo. módulos ainda. Outros podem dizer que devemos apenas começar a usá-los e usar babel etc. e gerar compilações compatíveis com ES5, não tenho certeza se isso é uma boa ideia, mas quem sabe. Isso torna o desenvolvimento mais difícil, você precisa iniciar automaticamente a compilação ao salvar os arquivos, e a depuração também pode ficar mais complexa. Só por essas coisas, tendo a pensar que esses transpiladores não valem a pena atm.

PS Não foi um discurso retórico contra o three.js, apenas dizendo que pode haver benefícios no ES6 para projetos como o three.js, uma vez que o suporte do navegador está lá :) e principalmente é mais sintático do que torná-lo uma linguagem totalmente nova. Só terá mais coisas.

Outro recurso que pode ser benéfico para three.js é WeakMap e possivelmente WeakSet . Não tenho certeza sobre as implicações, mas parece que isso poderia ser usado para rastrear as coisas sem manter o GC fazendo seu trabalho se o "proprietário" não tiver mais o ref. Há muitos estados como esse em three.js e usá-lo internamente pode fazer a diferença. Parece-me que isso é um pouco semelhante a ptrs compartilhados / fracos em C ++ para declarar a propriedade.

Um bom candidato pode ser algo como https://github.com/mrdoob/three.js/blob/master/src/lights/SpotLight.js#L12 onde esta poderia ser uma referência fraca e seria automaticamente apagada se o alvo fosse retirado de cena e recolhido. Mas eu acho que você não poderia depender da coleção, mas de qualquer maneira precisaria anular isso uma vez que o alvo fosse removido da cena.

Quem sabe, vou esperar que especialistas escrevam alguns posts de como todos esses recursos podem beneficiar os aplicativos em geral :)

Olá @jonnenauha ,

Sim, concordo que novos recursos como 'importar' e 'exportar' serão úteis, especialmente no que diz respeito à modularidade. Acredito que essa é a direção que @coballast e @kumavis estão tentando seguir ao tornar THREE.js mais modular e gerenciável para compilações personalizadas e capacidade de manutenção de base de código. Sou totalmente a favor de módulos e reutilização de objetos e funções, especialmente quando temos um formato de biblioteca grande, como THREE.js.

No entanto, não acho que precisamos do açúcar sintático adicional de classes, super, let, for, of, funções de seta, etc. quando basicamente obtemos a mesma funcionalidade em JavaScript agora que está em uso há décadas e tem um muita tração já. Posso ser antiquado, mas estou com Douglas Crockford quando ele diz que JavaScript já é uma linguagem orientada a objetos (significando funções = objetos = cidadãos de primeira classe), mas não uma linguagem 'clássica' - então não devemos nos preocupar com aulas de calçados em JavaScript. Ele foi projetado com uma abordagem diferente - uma abordagem que me surpreendeu no início (vindo da programação C / C ++ na década de 1990), mas com a qual concordo cada vez mais cada vez que me sento para codificar ou tento resolver a arquitetura de código problemas.

Em vez de mudanças sintáticas no THREE.js, prefiro ver a migração para recursos como a nova interface de programação SIMD. Acho que o código matemático do ALL THREE (especialmente Vector3 e Matrix4) poderia se beneficiar muito com isso. Aqui está um link de vídeo (verifique 22:51 no código de tempo):
https://youtu.be/CbMXkbqQBcQ?t=1371
Quando esse recurso chega aos principais navegadores, cada usuário THREE.js veria um aumento notável em sua taxa de quadros como resultado.

Desculpe se meu post anterior soou como um discurso retórico, eu apenas gosto de THREE.js como está agora - posso facilmente selecionar qualquer parte aleatória dele e saber o que está acontecendo, de onde veio e o que ele usa. :)

@erichlof @jonnenauha Sinto-me compelido a apontar que as classes es6 são apenas açúcar e estão usando internamente o mecanismo de protótipo para implementar tudo em tempo de execução.

Estou bastante otimista de que os recursos do es6 não afetarão o desempenho computacional. Módulos es6 podem afetar o tempo de carregamento quando eles são finalmente implementados pelos motores, porque você está obtendo um monte de pequenos arquivos ao invés de um arquivo grande. O HTTP / 2 pode deixar isso um problema. De qualquer forma, se usarmos módulos es6, podemos usar o browserify para construir um pacote como sempre fazemos.

Pessoalmente, sou a favor de usar a sintaxe es6 na base de código o máximo possível, porque tornaria o código mais conciso e reduziria os erros. Acho que muitas pessoas tendem a abusar da cadeia de protótipos e usá-la incorretamente. Mas não tenho um bom exemplo.

Eu também acho que sentar e esperar que o es6 seja implementado nos engines é uma ideia errada. Transpiladores estão disponíveis agora e produzem bons resultados que podem ser executados em navegadores agora. Acho que os benefícios de fazer isso são enormes, por isso devemos ser impacientes e começar a trabalhar nisso imediatamente.

Não acho que mover o código manualmente seja uma boa ideia. Como Doug McIlroy, o inventor dos tubos unix e geralmente um semideus disse:
"Use ferramentas ao invés de ajuda não qualificada para aliviar uma tarefa de programação, mesmo se você tiver que desviar para construir as ferramentas e esperar jogar algumas delas fora depois de terminar de usá-las."

Eu encorajaria qualquer pessoa interessada em es6 a entrar e ajudar a contribuir com este repo: https://github.com/5to6/5to6

Não concordo em converter toda a biblioteca em um subconjunto diferente de javascript. Como sempre, devemos discutir o que é possível e quais são os prós e os contras. Porque o desempenho vai variar entre as versões.

Por exemplo, mapa fraco é algo que seria um grande ganho nos renderizadores para lidar com estados de objetos. Suas maiores desvantagens eram um polyfill fraco, muito pouco suporte ao navegador e características de desempenho desconhecidas. (Já faz um tempo que eu investiguei isso, então é provável que isso tenha mudado)

E não devemos olhar apenas para es6. Por exemplo, ams.js seria ótimo como a tecnologia que executa um renderizador de software. Para obter mais informações, http://stackoverflow.com/questions/18427810/three-and-asmjs/18439786#18439786.

E não devemos esquecer que a maioria dos contribuidores está contribuindo principalmente porque o javascript é familiar e o es6 ainda não é para a maioria.

@ gero3 Esses são bons pontos que eu não pensei. Se estamos falando de micro otimização, concordo 100% com você. Eu não gostaria de tirar proveito desses recursos sem o suporte do navegador.

Em grande parte, o que eu estava falando acima era sobre o uso de açúcar sintático que tem semântica idêntica aos recursos es5 existentes e, portanto, pode ser construído com transpiladores sem afetar muito o desempenho.

ATUALIZAR:
Talvez ninguém se importe, mas mudei de ideia. Eu acredito que não devemos usar classes. Ainda acho que os módulos es6 são uma boa ideia.

Sou totalmente a favor das aulas. Recebo todas as coisas maravilhosas que o protótipo de objeto em JavaScript pode fazer. No entanto, em THREE.js (e em muitos outros projetos de SO modernos) estamos usando herança prototípica para simular classes, então por que não ter a boa sintaxe para acompanhá-la e se livrar de coisas hacky como:

THREE.Object3D.call( this );

e

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

Assim que as classes forem suportadas no Chrome e Firefox estáveis, eu não me importaria em considerar atualizar o código 😊

As classes

O Safari no iOS parece ser o que está se arrastando hoje em dia ... 😣

As aulas são incríveis, assim como outros recursos do ES7. Estamos usando-os em um de nossos projetos, mas tivemos que introduzir um compilador cruzado (babel.js) porque precisamos rodar em todos os navegadores - Chrome, Firefox, IE e Safari.

Há uma transformação de browserify para executar babel.js (babelify), então funcionaria bem com meus esforços.

Só por curiosidade, já começou o trabalho em alguns deles? :)

não, pois ainda não sabemos as implicações disso na velocidade.

Meu conhecimento é transpilado ES6 geralmente não tem desempenho e, portanto, não para produção até que seja implementado no navegador. Com isso, os projetos ou módulos mais novos devem se adaptar a essas conveniências hoje, mas o desempenho deve ser levado em consideração nesta decisão.

Concordo com @erichlof imo a implementação mais útil seria SIMD (https://github.com/tc39/ecmascript_simd), mesmo com o uso do polyfill. Parece que os usuários se beneficiariam mais com isso.

Onde o SIMD se encaixaria no ThreeJS? Acho que o ThreeJS já transfere todos os cálculos significativos para a GPU. Embora eu possa entender como usá-lo nas classes Vector, há muito pouca matemática realmente feita no ThreeJS, principalmente esses vetores são apenas transportados para a GPU.

Falo por experiência própria quando implementei extensões SSE2 / SSE4 antes e descobri que os benefícios eram passageiros na maioria dos casos - os únicos casos reais em que era um benefício foram quando eu tinha grandes arrays nos quais eu queria fazer o mesmo Operação.

Olá @bhouston ,
O mesmo se aplica às operações da Matrix? Quando estava pensando em SIMD, estava pensando que as operações de matriz 4 x 4 seriam as que mais se beneficiariam. E como todos sabemos, as matrizes são usadas em todos os quadros de animação em Three.js no lado do JavaScript / CPU, independentemente da complexidade do aplicativo.

Se os caras do Babylon.js não se importarem, aqui vai uma dica de como começar tudo isso:
https://github.com/BabylonJS/Babylon.js/blob/master/src/Math/babylon.math.js#L2030 -L2093

Eu acho que um único múltiplo de matriz, se você tiver que converter o formato, é provavelmente um perdedor. Se você tem suas matrizes sempre em formato SIMD, isso pode ser uma vantagem.

Mas, mesmo assim, a multiplicação de Matrix geralmente não é ideal porque você precisa multiplicar colunas por linhas, o que requer uma operação de reordenamento.

Descobri que a maioria dos esforços de otimização SIMD (excluindo grandes matrizes com operações homogêneas) não vale o esforço, mas estou bem com outros fazendo benchmarks para descobrir.

O código resultante também é difícil de depurar e manter.

Uma estratégia que pode funcionar é fazer com que todos os vetores e matrizes usem um layout de memória compatível com SIMD como sua representação nativa - que é o que Quake 3 eu acredito em sua biblioteca matemática. Mas então você tem que usar 4 flutuadores para os tipos vec2 e vec3 para eficiência, mas isso se torna problemático quando você deseja fazer o upload para a GPU porque agora você tem flutuadores extras no caminho.

Entendo o que você quer dizer, obrigado por sua visão e experiência. Ficar impressionado com a apresentação do SIMD.js um tempo atrás, colocá-lo no three.js e mantê-lo são duas coisas diferentes, suponho. Seria interessante, como você disse, fazer algumas comparações de desempenho. Talvez bibliotecas de física como Cannon.js e Oimo.js, que são usadas em conjunto com three.js, obtivessem mais benefícios do SIMD?

@bhouston Ahh ok isso faz algum sentido, alguns benchmarks seriam bem interessantes.

@erichlof se você estiver interessado, eu comecei uma filial, https://github.com/Globegitter/three.js/tree/include-SIMD , onde comecei a substituir Vector3 com SIMD. Ainda é um WIP pesado e meu tempo é limitado, então vamos ver até onde vou chegar. Além disso, usando o Firefox mais recente todas as noites, você pode executar este código sem um polyfill (onde a implementação nativa é aparentemente ~ 20 vezes mais rápida em comparação com o polyfill: https://blog.mozilla.org/javascript/2015/03/10/state -of-simd-js-performance-in-firefox /).

@erichlof @jonnenauha Sinto-me compelido a apontar que as classes es6 são apenas açúcar e estão usando internamente o mecanismo de protótipo para implementar tudo em tempo de execução.
Estou bastante otimista de que os recursos do es6 não afetarão o desempenho computacional.

Você pode ser um pouco rápido para concluir que: Existem de fato caminhos de código diferentes para ES6 em cada mecanismo JS na implementação (bastante complexa) de objetos JS.

Módulos es6 podem afetar o tempo de carregamento quando eles são finalmente implementados pelos motores, porque você está obtendo um monte de pequenos arquivos ao invés de um arquivo grande. O HTTP / 2 pode deixar isso um problema.

Os clientes ainda podem querer usar compactação de nível JS de aplicativo inteiro para cortar a largura de banda da rede e proteger sua propriedade intelectual.

Fazendo o Closure Compiler entender Three.js permitiria compilar para ES6 e ver quando é o momento certo para fazer a troca, além de muitos benefícios adicionais. Acho que é aqui que esforços desse tipo devem estar indo agora ...

Mas, mesmo assim, a multiplicação de matriz [SIMD] muitas vezes não é ideal porque você tem que multiplicar colunas por linhas, o que requer uma operação de reordenamento.

Os conjuntos de instruções SIMD geralmente têm uma instrução "multiplique por escalar e adicione", para implementar a multiplicação de matrizes 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

A multiplicação de matrizes é, na verdade, apenas aplicar uma transformação aos vetores de coluna do operando do lado direito. Agora, as transformações podem ser vistas como um monte de produtos escalares (a forma confusa que normalmente usamos com caneta e papel) ou como uma combinação linear dos vetores de eixo do espaço de destino = vetores de coluna do lado esquerdo operando.

@Globegitter Uau, isso é um começo incrível! Vou obter o Firefox Nightly para que também possa experimentar o novo branch!

@Globegitter Adoro quando alguém vai em frente e faz algo quando acredita nisso. O código estabelece pontos de vista divergentes mais rápido do que a discussão.

onde a implementação nativa é aparentemente ~ 20 vezes mais rápida em comparação com o polyfill

Ficaria interessado em ver também o quanto mais lento o polyfill é em comparação com o não SIMD

Vou obter o Firefox Nightly para que também possa experimentar o novo branch!

Também deve ser capaz de testá-lo no Edge ativando experimental e asm.js em about: flags

@Globegitter Acho que seu editor está mudando o espaço em branco que leva a diffs realmente desagradáveis: https://github.com/Globegitter/three.js/commit/d835ca3a22eed4ed4603534773ae55c29d5a8026

Percebi que você está fazendo o tipo SIMD como um carro lateral:

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

Posso sugerir que você apenas altere Vector3 x, y, z em getter / setters e armazene apenas um float32x4? Acho que essa abordagem pode ser muito mais fácil de implementar com menos mudanças.

Não tenho certeza da melhor maneira de definir propriedades, mas mrdoob faz algo assim aqui:

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

Ter o SIMD como o principal tipo de armazenamento por trás de um tipo matemático é provavelmente o mais eficiente, sem a necessidade de conversões extras. Aqui está a biblioteca matemática Bullet Physics SSE se você precisar de um guia para qualquer operação vetorial / matriz padrão:

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

@bhouston , obrigado por essas notas. Eu estava apenas indo direto ao ponto para ver o quão longe eu chegaria em algumas horas sem ter trabalhado muito com três e SIMD antes (nós o usamos na maioria de nossos projetos). Portanto, este feedback de alguém que conhece três é muito apreciado. E sim, tenho que desligar isso no meu editor.

@tschw, obrigado pela nota sobre a matemática de matriz / vetor! Você está certo, é melhor.

@Globegitter Aqui está um exemplo melhor de setter / getter no protótipo de um objeto: https://github.com/mrdoob/three.js/blob/master/src/core/Object3D.js#L83

Alguns centavos por trabalhar no ES2015 (principalmente no nó)

  • há lugares que os mecanismos de Javascript (por exemplo, V8) precisam se atualizar para otimizar os recursos do ES6
  • pela minha experiência, um código como let x = 1, y = 2 desotimizaria a v8, embora eu esperasse que a v8 fosse suportá-la eventualmente
  • o código transpilado para ES5 pode ser executado mais lentamente do que o código ES6 (é por isso que eu prefiro usar apenas recursos ES6 suportados em> nó 4, que é quase tudo, exceto o sistema de exportação de importação)
  • Mapas e conjuntos são vitórias em desempenho
  • As aulas são legais
  • Usar o Babel pode ser uma dor para o seu fluxo de trabalho, provavelmente não vale o esforço se usar o ES6 puramente para sintaxe

Meio ano atrás, converti algumas funções do Three.js (multiplicação de matrizes 4x4, Vector4 etc.) para SIMD e você pode experimentá-las. Em algum ponto, funcionou como um bookmarklet, mas agora pode exigir uma atualização para funcionar com a última versão do Three

  • Firefox Nightly suporta SIMD nativo pronto para uso
  • Chrome com sinalizador --js-flags = "- Harmony-simd" suporta JS polyfill de SIMD, então será mais lento do que a versão não simd. Pelo menos você pode verificar se funciona e experimentar!

O ganho de desempenho de 350% é uma MENTIRA :)

Eu também portei parte do Vector3, mas está comentado.

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

Edit: Eu tenho uma versão mais atualizada em algum lugar no meu disco rígido, então vou atualizar este projeto em breve

Impressionante assistir e olhar um +1 para isso.
O que seria ótimo é um sistema que verifica o desempenho e habilita ou desabilita esses recursos dependendo do desempenho.

O que seria ótimo é um sistema que verifica o desempenho e habilita ou desabilita esses recursos dependendo do desempenho.

Eu acho que um teria duas definições Vector3 dentro do módulo Vector3 e você retornaria condicionalmente uma ou outra dependendo se o SIMD é nativo? Acho que funcionaria, mas aumentaria o lado do download. Talvez você possa ter apenas algumas funções que mudam dependendo se o SIMD está disponível - provavelmente o SIMD é mais importante apenas para um pequeno subconjunto de funções matemáticas. Se isso era pequeno em termos de código total, pode valer a pena colocá-lo agora. Mas precisa ser opcional para não ficar lento quando o SIMD não estiver disponível.

Poderíamos começar fazendo uma versão SIMD de Matrix4 's multiplyMatrices() já que é atualmente o método mais chamado em cenas complexas.

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

screen shot 2016-08-30 at 20 46 29

@mrdoob olhe aqui está feito.
https://github.com/DVLP/three.turbo.js/blob/master/src/three.turbo.js

Tente como um 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);})()

O trecho de código responsável

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

Quando eu estava testando este meio ano atrás, percebi que a versão com o loop "for" desdobrado era minimamente mais rápida. É por isso que em minha pequena biblioteca o loop é comentado e a versão codificada está presente.

Existem mais funções no ramo "inverso"
https://github.com/DVLP/three.turbo.js/blob/inverse/src/three.turbo.js

Qual é a diferença de desempenho?

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

Depende. Em Nightly, quando o número de cálculos é pequeno (<1000), o resultado é 3 vezes mais lento. Quando o número de cálculos é superior a 10000, a velocidade é ~ 40% mais rápida

No Chrome com o sinalizador --js-flags="--harmony-simd" habilitado, não há SIMD real, mas um polyfill JavaScript, então obviamente a velocidade é muitas vezes mais lenta por enquanto.

Um bom lugar para testar seria o projeto Crosswalk (baseado no Chromium). Eles têm SIMD real para Android, então pode ser uma experiência interessante construir um projeto com o código deste JSFiddle para ver qual seria o resultado.

Você pode querer incluir o simd polyfill de qualquer maneira em suas páginas de exemplo. Apenas um pouco mais conveniente para as pessoas experimentarem. Registre uma linha no console ou coloque algum texto na tela quando nenhum nativo estiver disponível (o polyfill provavelmente deixa algumas dicas de que está habilitado).

Não consigo imaginar por que o Chrome carregaria apenas o js simd polyfill com --js-flags="--harmony-simd" , isso simplesmente não faz sentido quando já pode ser feito na terra do usuário ?! Qual é o benefício disso. Talvez eles comecem a colocar as coisas gradualmente. Onde você leu isto é o que realmente está acontecendo com a bandeira, algum bom link? Parece estar "em desenvolvimento" aqui https://www.chromestatus.com/features/5757910432874496

Edit: Para o tópico real: eu imagino que seja muito difícil colocar essas coisas em three.js se o perf estiver em todo o lugar, de alguns objetos a muitos objetos. Se todas as implementações podem fornecer uma melhoria de desempenho com 1 a N objetos, ele deve ser detectado e usado onde fizer sentido. Se os impls nativos são inconsistentes, não vejo a coisa toda indo a lugar nenhum, então por que se preocupar em trabalhar nisso, gastar as horas de desenvolvimento em algo mais produtivo.

três podem saltar sobre isso quando amadurecer, ou será que o suporte a three.js poderia levar as implementações de navegador a um desempenho melhor? Eu acho que o mecanismo irreal e outros casos de uso de simulação / matemática seriam a força motriz para os fornecedores de navegadores, não particularmente quantas bibliotecas desejam usar o recurso. Mas quem sabe.

não consigo imaginar por que o Chrome simplesmente carregaria o js simd polyfill com --js-flags = "- Harmony-simd"

Acho que é uma prática bastante comum que os navegadores façam dessa forma, para que os usuários possam começar a testar as coisas. Por exemplo, se bem entendi, é assim que o WASM será introduzido nos navegadores inicialmente.

Todos os argumentos que apóiam a inevitabilidade da necessidade de um centurião. Monitoramento de desempenho em tempo real que pode ativar ou desativar recursos e determinar o desempenho ideal. Portanto, mesmo a densidade do mapa de sombra deve mudar com base na distância da câmera, etc. De qualquer forma, eu sei que o consenso decidiu que esta seria uma ferramenta de terceiros e não necessária. Mesmo assim, quero apenas manter esse ponto na mente consciente, se não subconsciente.
Talvez você esteja apenas verificando um pollyfill e desabilitando o SIMD, mas novamente o FPS diz tudo. As prioridades do que habilitar ou desabilitar são provavelmente melhores como uma preferência específica do usuário / aplicativo. Obrigado pela atenção! Estou ansioso para melhorar o GL mais rápido em um futuro próximo. Vamos estar prontos para ofuscar o resto.

Parece que o processo de carregamento de dados no SIMD pode estar criando uma sobrecarga que desafia os benefícios de usar o SIMD no Nightly. Estou muito curioso sobre o desempenho no Chrome, mas o Chromium mais recente com SIMD real está aqui http://peterjensen.github.io/idf2014-simd/
É velho.

Atualizar:
agora o SIMD também funciona no Edge. Você pode habilitá-lo acessando sobre: ​​sinalizadores e marcando "Habilitar recursos experimentais de JavaScript" (reinicie o Edge)
Não tenho certeza se este é SIMD real ou polyfill embora. Este teste torna SIMD ~ 40% mais lento em minha máquina: / https://jsfiddle.net/tk6zx5dm/6/

variação do teste com objetos SIMD em cache no objeto Matrix4, não tenho certeza se isso será útil
https://jsfiddle.net/tk6zx5dm/15/
O que é interessante é que o código com objetos SIMD em cache é _ às vezes_ mais rápido mesmo no Chrome, que usa SIMD polyfill (...? Estranho)

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

Cache - provavelmente deve ser executado em cada updateMatrix (), o que pode tornar a solução inteira mais lenta no 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]));
  }
};

Estou curioso, o estilo ES6 foi revisitado? O código inteiro está inutilizável ao vivo agora sem executar um concatenador, então por que não executar o babel e começar a usar o ES6 quando apropriado?

O código inteiro está inutilizável ao vivo agora sem executar um concatenador, então por que não executar o babel e começar a usar o ES6 quando apropriado?

Principalmente devido à falta de testes sobre o impacto no desempenho do código produzido pelo babel. Além disso, ouvi que o V8 produz um código mais rápido ao usar var em vez de let / const.

Para sua informação: recentemente comecei a experimentar o bublé, que "se limita aos recursos do ES que podem ser compilados para um ES5 compacto e de alto desempenho".

A parte inferior deste link ajuda a explicar var vs loops let in
http://stackoverflow.com/questions/21467642/is-there-a-performance-difference-between-let-and-var
Pessoalmente, estou esperando que as soluções de nenhum transpiler cheguem ao navegador. goste de 'esperar' quanto antes, melhor, mas por enquanto talvez deva ser escrito dessa forma e passar (sendo terrivelmente desfigurado por) um transpiler, mas e se funciona no Chrome ?! então testando para outros navegadores? Eu digo 'Deixe-os comer bolo ... ou usar o Chrome'. (minha expressão favorita).
Acho que 'let' deve ser usado se for em uma situação em que seja, de preferência, comprovado por meio de testes que é melhor fazê-lo.
Suponho que seja como se 'var' fosse içado para evitar o escopo, mas você pode querer isso e então 'let' é o melhor. Eu acho / espero que 'let' mantenha sua pegada de memória menor em certas situações também.

O código transpilado nunca será tão rápido quanto otimizado manualmente. É uma pena que o JSPerf esteja fora do ar. Eu costumava visitá-lo com mais frequência do que o Google.
Edit: JSPerf.com não está fora do ar! Eu apenas assumi que está morto para sempre depois de não ter funcionado por um ano
let 3x mais lento do que var no meu Chrome Canary: https://jsperf.com/let-vs-var-performance/14
no Firefox e no Edge não há diferença na velocidade, mas o Chrome é o mais importante.
Alguém pode testar no Safari?

As aulas parecem ótimas e modernas! alguém sabe se já está agendado?

@ Rubinhuang9239 Não vi ninguém dando uma chance.

deixe 3x mais lento do que var no meu Chrome Canary: https://jsperf.com/let-vs-var-performance/14

Pelo que vale a pena, let e const são agora ligeiramente mais rápidos do que var para mim no Chrome 66, Firefox 59 e Edge 42, usando esse teste.

A troca de classes deve ser muito simples, eu acho - a maior parte do trabalho foi a adoção do rollup que foi feito há algum tempo. Eu não ficaria surpreso se um herói pudesse implementar classes no ThreeJS em algumas horas.

Bem, há muitas aulas, então talvez demore cerca de 8 horas se você fizer isso manualmente.

Talvez comece devagar e converta primeiro as aulas de matemática e faça uma RP. Se funcionar, passe para os outros.

@looeee ,

2019 é o ano para finalmente começar a adotar algum código ES6 nos exemplos / documentos, certo @mrdoob? 😄

ES6 tem sido o padrão há algum tempo, novos desenvolvedores aprendem ES6. Além disso, podemos parar de oferecer suporte ao IE11 nos exemplos conforme vocês discutiram em # 16220, que desenvolvedores veem os exemplos do three.js usando o IE11? 😅

Acho que os recursos mais necessários para simplificar o código para os novatos são as classes e strings de modelo, sem esquecer o agora padrão const / let.

Posso contribuir se decidirmos começar.

Passo a passo. Vamos começar atualizando os exemplos para usar three.module.js por enquanto.

Passo a passo. Vamos começar atualizando os exemplos para usar three.module.js por enquanto.

Esta etapa já foi concluída há algum tempo. Talvez seja hora de passar oficialmente para a próxima etapa?

Dois candidatos:

  1. const / let
  2. Aulas

Como as classes já são usadas nas geometrias de caixa há algum tempo, voto por fazer isso primeiro. Ou podemos fazer as duas coisas ao mesmo tempo.

Relacionado: # 11552, # 18863

Se entendi bem, o problema é que não podemos converter nada para classes ES6 se for estendido por exemplos, até que os exemplos sejam convertidos também. E isso pode significar esperar até que examples/js desapareça? A menos que possamos confirmar que o script modularize suportará classes, para converter os arquivos examples/js ao mesmo tempo que suas classes pai.

Pelo que entendi, examples/js é uma espécie de todos os recursos em excesso que são legais mesmo assim, mas que se todos estivéssemos combinados no src/... , isso aumentaria fora de proporção. É inerente a resposta à pergunta 'Fornecemos exemplos / scripts de x, y, z comumente criados?'. Eu arrisco um palpite de que a resposta do three.js é principalmente sim, mas como material educacional dentro do site. Remover examples/js parece fora de questão nesse ponto. Embora talvez eu não tenha entendido como examples/js é referenciado / usado 🤔 me avise.

Deixar examples/js como apenas um site / educacional perde parte do que essa pasta poderia ser, ou seja, scripts / conteúdo / projetos / outros da comunidade que as pessoas gostariam de compartilhar, mas não estou ciente de algum lugar que esteja dobrando naquela.

Eu divago.

até que os exemplos sejam convertidos também.

Gosto de como isso soa como nosso próximo melhor passo provisório.

@DefinitelyMaybe não estamos removendo a funcionalidade em examples/js , existem dois diretórios dignos de nota:

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

O primeiro contém arquivos legados, o último contém módulos ES gerados a partir desses arquivos, com a mesma funcionalidade. Eventualmente removeremos o primeiro. O script que faz a conversão não suporta classes ES atualmente. Portanto, até que seja removido, os arquivos em examples/js não podem ser convertidos em classes ES. Alguns deles estendem arquivos em src/ , e você não pode estender classes ES sem usar classes ES, portanto, esta é uma dependência de bloqueio.

ah, estava confuso com o comentário anterior

E isso pode significar esperar até que example / js desapareça?

faz sentido agora.

modularize.js me lembra do meu projeto inicial que me trouxe aqui. Conversor . Eu vi comentários aqui sobre a mudança para classes ES6, então pensei em pular aqui em vez disso.

Portanto, se examples/js estende src de alguma forma, ambos precisam ser convertidos para classes ES6 ao mesmo tempo
ou...
trabalhar em modularizar até gerar classes / ES6?

não podemos converter nada para classes ES6 se for estendido por exemplos

Ainda há muitas coisas no núcleo que não foram estendidas nos exemplos, por que não começamos com isso?

Isso soa bem para mim.

@ Mugen87 havia mais alguma coisa bloqueando a mudança de classe do ES, ou apenas isso?

Ainda há muitas coisas no núcleo que não foram estendidas nos exemplos, por que não começamos com isso?

Lista de scripts não ampliada por exemplos .

editar: a lista foi atualizada!

Os bloqueadores são seções 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

O uso de THREE.<class>.call e Object.create( THREE.<class> seriam os padrões mais prováveis. O que significaria que Loader, EventDispatcher e PerspectiveCamera (entre provavelmente muitos outros) ainda não podem ser convertidos em classes.

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

Ok, acho que podemos começar com let e const em src/ .

@DefinitelyMaybe É algo que você gostaria de ajudar?

🎉 💯 diabos sim!

Eu só queria levantar uma preocupação de que se você estiver carregando um código quente, meu medo está constante de causar problemas. Se for verdade em todo o JavaScript que os objetos sobrescrevem totalmente const, não há problema. Infelizmente, se não o fizerem, todas as const nunca devem ser usadas. Acabei de mesclar estruturas de objeto com funções de código atribuídas a chaves dessas árvores de objeto (como estruturas), para evitar a necessidade de usar let ou const na maior parte.
De qualquer forma, é algo para se pensar e basicamente acredito que const nunca deve ser usado e é realmente desnecessário. Principalmente para minhas preocupações com o carregamento de hotcode.
Ainda assim, acho que eles não são tão constantes quanto você pensa, então talvez alguém que entenda isso mais possa explicar que é uma preocupação sem sentido com o recarregamento de importação ou o que quer que seja. Obrigado por sua consideração e contribuição.
Que haja 'let'! Finalmente.

Crockford disse que var foi um grande erro, mas não poderia ser alterado, então 'let' foi criado, mas var é considerado defeituoso e o código de 'let' deveria ter sido uma correção para var, mas teria quebrado alguns casos marginais mal codificados restantes espreitando na selva. O modo estrito e a elevação são problemas em torno deste tópico.

@MasterJames não há absolutamente nenhum problema com recarregamento a quente ao usar const.

Eu trabalho em um ambiente React e recarregar a quente é a norma lá, assim como const e let, que são o padrão hoje em dia.

Eu concordo, isso não vai interferir no recarregamento a quente. Talvez você tenha confundido const por tornar objetos imutáveis ​​com Object.freeze ? Não estamos planejando fazer isso.

Esta página foi útil?
0 / 5 - 0 avaliações