Three.js: 采用一些 ES6 特性

创建于 2015-04-16  ·  74评论  ·  资料来源: mrdoob/three.js

ES6 即将到来,浏览器和工具正在迅速获得支持。 我认为 THREE.js 可以从 ES6 带来的一些新特性中受益匪浅。

为了好玩并鼓励围绕项目可能迁移的辩论,我创建了这个问题并创建了一些代码示例。

以下示例中演示的功能:

  • 默认参数
  • 块范围的let关键字
  • 迭代器 + For..Of
  • 班级
  • 箭头函数
  • 发电机
  • 模块

类示例

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;

遍历生成器示例

class Object3D {
    constructor() {
        ...
    }

    traverse(callback) {
        callback(this);

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

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

    ...
}

使用中的发电机:

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

注意:我没有测试过任何这些

Suggestion

最有用的评论

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

好的,我想我们可以从letconst src/

@DefinitelyMaybe这是您想要帮助的事情吗?

所有74条评论

可能有点早? 跨浏览器的支持并不总是很好: http :

let未在 FF 中公开,也未在 Chrome 和 IE 中 100% 的情况下公开。
generators在 IE 中不可用
class仅在 Chrome、IE12(Spartan) 技术预览版中适用于 Win10 和 FF39,比当前版本高两个。
import尚未在任何地方可用
super仅适用于 IE12,不适用于 IE11、Chrome 或 FF
arrow functions不在 IE11 或 Chrome 中

此外,生成器和for-of都是Chrome 的优化杀手

Imo 也太早了,只是为了更漂亮的语法。 当列表中的某些内容会带来显着的性能提升或代码可读性优势时,这是值得商榷的。 也许知道代码库和 ES6 特性的人可以对此发表评论。

我参加 ES6 派对有点晚了。 这对我来说似乎是一种不同的语言。 我经常为 Three.js 做出贡献,但如果它看起来像上面的片段,我不知道我是否会继续。 我只是没有耐心去学习一个外观不同、功能不同的 JavaScript 版本,它基本上与“new function()”和“object.prototype”做同样的事情,但可能更慢。

这是网络社区对 ES6 语言委员会的要求吗? 我已经编码了 20 年,“类”这个词没有出现在我的项目中(如果我按照我的方式,也不会出现)。 坦率地说,JavaScript 开始看起来像 JAVA...(脚本)。 :-\

我和@benaadams@jonnenauha 在一起; 为时过早,如果 Chrome 和 Firefox 没有像他们已经在引擎盖下优化 JavaScript(V8 等)那样大量优化这个新版本的语言,它可能会减慢代码速度。

:+1:

@erichlof好吧,我实际上最在等待 ES6 类和模块支持。 我目前正在为我的应用程序使用 AMD。 我从事的主要 JS 项目是大约 10k 行,包含数百个“类”,而 AMD 是一个救星。 在开发和生产构建期间。 Imo 大项目甚至小项目都需要某种模块系统和一种方式来声明它们所依赖的东西。 一旦您拥有复杂的项目结构,它就会变得难以管理。 不应该让编程人员弄清楚以什么顺序放置 25x <script>标签。 一旦你拥有像three.js这样的文件数量,这就是愚蠢的。 大多数项目通过构建一个大 js 文件(如three.js)来解决这个问题,然后有一个随机的 extras/helpers 文件夹,您可以在其中包含其他内容。 这有点限制,我必须包含一个 ~500kb(缩小)的构建才能获得 ~ 一切都在阳光下。

有一点我认为增加了三个 AMD 支持,但这只是一个小代码块,用于检测是否使用 AMD 并且它调用一个函数而不是有效地声明 window.THREE。 我不知道目前制作自定义构建有多么困难,这些构建会删除我不需要的功能并在核心之外添加我想要的东西并将其优化为一个按顺序加载的工作文件。

您的项目中可能没有“类”,但如果您使用 object.prototype(就像three.js 大量使用的那样),它实际上是同一件事,您同意吗? 我们喜欢将物体放在一起并赋予它们一个目的。 然后其他代码想要使用所述对象和一种干净的声明方式来导入它们。

我所说的所有 ES6 类和模块也将是对three.js 的一个很好的补充,为构建提供更多的结构和模块化。 这还为时过早,因为 afaik 没有浏览器支持,例如。 模块。 其他人可能会说应该开始使用它们并使用 babel 等并输出符合 ES5 的构建,我不确定这是否是个好主意,但谁知道呢。 这使得开发更加困难,您必须在保存文件时自动启动构建,并且调试也可能变得更加复杂。 仅就这些而言,我倾向于认为这些转译器不值得在 atm 上使用。

PS 并不是对three.js 的咆哮,只是说一旦浏览器支持,ES6 可能会给three.js 等项目带来好处:) 并且主要是它更多的语法糖而不是使它成为一种全新的语言。 它只会有更多的东西。

另一个可能对 Three.js 有益的特性是WeakMapWeakSet 。 我不确定其中的含义,但如果“所有者”不再持有引用,这似乎可以用于跟踪事物,而无需让 GC 完成其工作。 Three.js 中有很多这样的状态,在内部使用它可能会有所不同。 在我看来,这有点类似于 C++ 中用于声明所有权的共享/弱 ptr。

一个好的候选者可能是https://github.com/mrdoob/three.js/blob/master/src/lights/SpotLight.js#L12 之类的东西,这可能是一个弱引用,如果目标是从现场移走并收集。 但我想你无论如何都不能依赖于集合,但是一旦目标从场景中移除,无论如何都需要将其归零。

谁知道呢,我会等待专家写一些博客文章,所有这些功能通常如何使应用程序受益:)

@jonnenauha

是的,我同意像“导入”和“导出”这样的新功能会很有用,尤其是在涉及模块化的情况下。 我相信这就是@coballast@kumavis试图使 THREE.js 更加模块化和易于管理以实现自定义构建和代码库可维护性的方向。 我完全支持模块和对象和函数的重用,尤其是当我们拥有像 THREE.js 这样的大型库格式时。

但是,我认为我们不需要类的额外语法糖,super、let、for、of、箭头函数等。已经有很大的吸引力了。 我可能已经过时了,但我和 Douglas Crockford 在一起,他说 JavaScript 已经是一种面向对象的语言(意思是函数 = 对象 = 一等公民),但不是“经典”语言——所以我们不应该担心将类硬塞到 JavaScript 中。 它是用不同的方法设计的——起初我对这种方法感到吃惊(来自 1990 年代的 C/C++ 编程),但每次我坐下来编写代码或尝试解决代码架构时,我越来越同意这种方法问题。

我宁愿看到向新的 SIMD 编程接口等功能迁移,而不是对 THREE.js 进行语法更改。 我认为三者的所有数学代码(尤其是 Vector3 和 Matrix4)都可以从中受益匪浅。 这是一个视频链接(查看时间码中的 22:51):
https://youtu.be/CbMXkbqQBcQ?t=1371
当此功能登陆主流浏览器时,每个 THREE.js 用户都会看到他们的帧速率明显加快。

抱歉,如果我之前的帖子听起来像咆哮,我只是喜欢 THREE.js 现在的样子——我可以轻松地选择它的任何随机部分,并知道发生了什么、它来自哪里以及它的用途。 :)

@erichlof @jonnenauha我不得不指出 es6 类只是糖,它们在内部使用原型机制在运行时实现一切。

我相当乐观地认为 es6 特性不会影响计算性能。 当引擎最终实现 es6 模块时,它们可能会影响加载时间,因为您正在获取一堆小文件而不是一个大文件。 不过,HTTP/2 可能会使这成为一个非问题。 无论哪种方式,如果我们使用 es6 模块,我们可以像往常一样使用 browserify 构建一个包。

我个人是赞成在代码库中尽可能多地使用es6语法,因为这样会使代码更简洁,减少错误。 我认为很多人倾向于滥用原型链并错误地使用它。 不过我没有很好的例子。

我也认为坐等 es6 在引擎中实现是错误的想法。 转译器现在可用,可以产生现在在浏览器中运行的良好结果。 我认为这样做的好处是巨大的,所以我们应该不耐烦并立即开始工作。

我认为手动移动代码不是一个好主意。 正如道格麦克罗伊,unix 管道的发明者和一般的半神说:
“优先使用工具而不是不熟练的帮助来减轻编程任务的负担,即使你不得不绕道而行,并希望在你用完它们后将其中的一些扔掉。”

我会鼓励任何对 es6 感兴趣的人加入并帮助为此 repo 做出贡献: https :

我不同意将整个库转换为 javascript 的不同子集。 一如既往,我们应该讨论什么是可能的,什么是利弊。 因为版本之间的性能会有所不同。

例如,weakmaps 是渲染器处理对象状态的巨大增益。 它最大的缺点是 polyfill 很弱,很少有浏览器支持和未知的性能特征。 (自从我调查这个已经有一段时间了,所以很可能会改变)

我们不应该只看 es6。 例如,ams.js 作为运行软件渲染器的技术会很棒。 有关更多信息,请访问 http://stackoverflow.com/questions/18427810/three-and-asmjs/18439786#18439786。

我们不应该忘记,大多数贡献者主要是在贡献,因为 javascript 很熟悉,而 es6 对大多数人来说还不是。

@gero3这些是我没想到的好点。 如果我们谈论的是微优化,那么我 100% 同意你的看法。 我不想在没有浏览器支持的情况下利用这些功能。

我在上面谈论的主要是使用与现有 es5 功能具有相同语义的语法糖,因此可以使用转译器构建而不会对性能产生太大影响。

更新:
也许没人关心,但我改变了主意。 我相信我们不应该使用类。 我仍然认为 es6 模块是个好主意。

我完全赞成上课。 我得到了 JavaScript 中的对象原型可以做的所有美妙的事情。 然而,在 THREE.js(以及许多其他现代操作系统项目)中,我们使用原型继承来模拟类,那么为什么不使用漂亮的语法来配合它,并摆脱像这样的hacky 东西:

THREE.Object3D.call( this );

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

一旦稳定的 Chrome 和 Firefox 支持类,我不介意考虑更新代码😊

今天稳定的 Chrome 42 支持@mrdoob类,Firefox 39 将于 6 月发布,仅供参考😊

iOS 上的 Safari 似乎是现在拖着的那个...... 😣

类是惊人的,其他 ES7 特性也是如此。 我们在我们的一个项目中使用它们,但我们不得不引入交叉编译器 (babel.js),因为我们需要在所有浏览器上运行——Chrome、Firefox、IE 和 Safari。

有一个 browserify 转换来运行 babel.js (babelify),所以它会在我的努力下很好地工作。

只是出于好奇,其中一些工作已经开始了吗? :)

不,因为我们仍然不知道这些对速度的影响。

我的理解是转译的 ES6 大多不是高性能的,因此在实现到浏览器之前不会用于生产。 话虽如此,较新的项目或模块现在应该适应这些便利,但性能必须考虑到这个决定中。

我同意@erichlof imo 最有用的实现是 SIMD (https://github.com/tc39/ecmascript_simd),即使使用 polyfill。 似乎用户将从中受益最大。

SIMD 在哪里适合 ThreeJS? 我认为 ThreeJS 已经将所有重要的计算卸载到 GPU 上。 虽然我可以理解在 Vector 类上使用它,但在 ThreeJS 中实际完成的数学很少,而大多数这些向量只是传输到 GPU。

我从之前实现 SSE2/SSE4 扩展的经验中讲,我发现在大多数情况下好处是短暂的——唯一真实的情况是当我有大型阵列时我想做同样的事情手术。

@bhouston
矩阵运算也是如此吗? 当我考虑 SIMD 时,我认为 4 X 4 矩阵运算会受益最大。 众所周知,无论应用程序的复杂程度如何,在 JavaScript/CPU 端的 Three.js 中,每个动画帧都会使用矩阵。

如果 Babylon.js 的人不介意,这里有一个关于如何开始所有这些的提示:
https://github.com/BabylonJS/Babylon.js/blob/master/src/Math/babylon.math.js#L2030 -L2093

我认为如果必须转换格式,单个矩阵倍数可能会失败。 如果您的矩阵始终采用 SIMD 格式,那么这可能是一个好处。

但即便如此,矩阵乘法通常也不是最优的,因为您必须将列乘以行,这需要重新排序操作。

我发现在 SIMD 优化方面的大多数努力(不包括具有同构操作的大型数组)都不值得付出努力,但我可以接受其他人进行基准测试以找出答案。

生成的代码也很难调试和维护。

一种可行的策略是让所有向量和矩阵都使用 SIMD 兼容的内存布局作为它们的本机表示——这就是我相信 Quake 3 在其数学库中所做的。 但是,为了提高效率,您必须为 vec2 和 vec3 类型使用 4 个浮点数,但是当您想上传到 GPU 时,这就会出现问题,因为现在您有额外的浮点数。

我明白你的意思,谢谢你的洞察力和专业知识。 不久前的 SIMD.js 演示给我留下了深刻的印象,我认为将其放入 Three.js 并维护它是两件不同的事情。 像您说的那样进行一些性能比较会很有趣。 也许像 Cannon.js 和 Oimo.js 这样与three.js结合使用的物理库会从SIMD中获得更多好处?

@bhouston Ahh 好吧,这确实有道理,不过有些基准测试会很有趣。

@erichlof如果您有兴趣,我已经创建了一个分支https://github.com/Globegitter/three.js/tree/include-SIMD ,在那里我开始用 SIMD 替换 Vector3。 这仍然是一个沉重的 WIP,我的时间有限,所以我们会走多远。 此外,每晚使用最新的 Firefox 您可以在没有 polyfill 的情况下运行此代码(与 polyfill 相比,本机实现显然快约 20 倍:https://blog.mozilla.org/javascript/2015/03/10/state -of-simd-js-performance-in-firefox/)。

@erichlof @jonnenauha我不得不指出 es6 类只是糖,它们在内部使用原型机制在运行时实现一切。
我相当乐观地认为 es6 特性不会影响计算性能。

您可能会很快得出结论:在 JS 对象的(相当复杂的)实现中,每个 JS 引擎中的 ES6 确实有不同的代码路径。

当引擎最终实现 es6 模块时,它们可能会影响加载时间,因为您正在获取一堆小文件而不是一个大文件。 不过,HTTP/2 可能会使这成为一个非问题。

客户可能仍然希望使用整体应用 JS 级压缩来削减网络带宽并保护他们的知识产权。

让 Closure Compiler 理解 Three.js 将允许编译到 ES6 并查看何时进行切换,以及许多额外的好处。 我认为这是目前应该进行此类努力的地方......

但即便如此,[SIMD] 矩阵乘法通常不是最佳的,因为您必须将列乘以行,这需要重新排序操作。

SIMD 指令集通常有一个“乘以标量和加”指令,来实现这样的矩阵乘法:

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

矩阵乘法实际上只是对右侧操作数的列向量进行变换。 现在,变换可以被视为一堆点积(我们通常用笔和纸使用的令人困惑的方式),或者作为目标空间的轴向量的线性组合 = 左侧的列向量操作数。

@Globegitter哇,这是一个很棒的开始! 我将获得 Firefox Nightly,这样我也可以尝试新的分支!

@Globegitter我喜欢有人继续前进并在他们相信时做某事。 代码比讨论更快地解决不同的观点。

与 polyfill 相比,本机实现显然要快 20 倍

也有兴趣看看 polyfill 与非 SIMD 相比慢了多少

我将获得 Firefox Nightly,这样我也可以尝试新的分支!

也应该能够通过在about:flags 中切换实验性和 asm.js来在 Edge 中尝试它

@Globegitter我认为你的编辑器正在改变导致非常讨厌的差异的空白: https :

我注意到您将 SIMD 类型作为侧车:

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

我可以建议您将 Vector3 x, y, z 更改为 getter/setter 并且只存储一个 float32x4 吗? 我认为这种方法可能更容易实施,更改较少。

我不确定定义属性的最佳方式,但 mrdoob 在这里做了类似的事情:

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

将 SIMD 作为数学类型背后的主要存储类型可能是最有效的,不需要额外的转换。 如果您需要任何标准向量/矩阵运算的指南,这里是 Bullet Physics SSE 数学库:

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

@bhouston ,感谢您的笔记。 我有点直接进入那里,看看我在几个小时内能走多远,而之前没有使用 3 和 SIMD(我们在大多数项目中使用它)。 因此,非常感谢了解三的人的反馈。 是的,必须在我的编辑器中关闭它。

@tschw感谢您对矩阵/向量数学的说明! 你说得对,那就更好了。

@Globegitter这是一个更好的对象原型上的 setter/getter 示例: https :

在 ES2015 上工作的一些美分(主要在节点中)

  • Javascript 引擎(例如 V8)需要在某些地方追赶优化 ES6 功能
  • 根据我的经验,像let x = 1, y = 2这样的代码会去优化 v8,尽管我希望 v8 最终会支持它
  • 转译为 ES5 的代码可能比 ES6 代码运行得慢(这就是为什么我更喜欢在 >node 4 中只使用受支持的 ES6 特性,这几乎是除了导入导出系统之外的所有功能)
  • Maps 和 Sets 是性能优势
  • 课很好
  • 使用 Babel 可能会给您的工作流程带来痛苦,如果仅将 ES6 用于语法糖,则可能不值得付出努力

半年前,我将一些 Three.js 函数(4x4 矩阵乘法、Vector4 等)转换为 SIMD,您可以尝试一下。 在某些时候它可以用作书签,但现在可能需要刷新才能使用最新的三个版本

  • Firefox Nightly开箱即
  • 带有标志 --js-flags="--harmony-simd" 的 Chrome 支持 SIMD 的 JS polyfill,因此它会比非 SIMD 版本慢。 至少您可以检查它是否有效并进行实验!

350% 的性能提升是谎言 :)

我也移植了 Vector3 的一部分,但它被评论了。

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

编辑:我的硬盘上有一个更新的版本,所以我很快就会更新这个项目

令人敬畏的观看和凝视+1。
最好的系统是检查性能并根据所述性能启用或禁用此类功能。

最好的系统是检查性能并根据所述性能启用或禁用此类功能。

我猜想在 Vector3 模块中有两个 Vector3 定义,你会根据 SIMD 是否是原生的有条件地返回一个或另一个? 我想这会起作用,但它会增加下载量。 也许您可以根据 SIMD 是否可用来切换一些函数——可能 SIMD 仅对一小部分数学函数最重要。 如果这在总代码方面很小,那么现在可能值得投入。 但它需要是可选的,这样当 SIMD 不可用时它不会变慢。

我们可以从Matrix4multiplyMatrices()的 SIMD 版本开始,因为它是目前在复杂场景中调用次数最多的方法。

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

screen shot 2016-08-30 at 20 46 29

@mrdoob看看这里已经完成了。
https://github.com/DVLP/three.turbo.js/blob/master/src/three.turbo.js

尝试作为书签:
javascript:(function(){var script=document.createElement('script');script.src='//rawgit.com/DVLP/three.turbo.js/master/src/three.turbo.js';document.head.appendChild(script);})()

负责的那段代码

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

当我在半年前进行测试时,我注意到带有展开的“for”循环的版本速度最低。 这就是为什么在我的小库中对循环进行注释并存在硬编码版本的原因。

“反向”分支中有更多功能
https://github.com/DVLP/three.turbo.js/blob/inverse/src/three.turbo.js

性能有什么区别?

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

这取决于。 在 Nightly 中,当计算次数很少(<1000)时,结果会慢 3 倍。 当计算次数高于 10000 时,速度提高约 40%

在启用了--js-flags="--harmony-simd"标志的 Chrome 中,没有真正的 SIMD,但是 JavaScript polyfill 显然现在速度要慢很多倍。

测试的好地方是 Crosswalk 项目(基于 Chromium)。 他们有适用于 Android 的真正 SIMD,因此使用此 JSFiddle 中的代码构建项目以查看结果可能是一个有趣的实验。

您可能不想在示例页面中包含 simd polyfill。 只是更方便人们试用它们。 当没有本地可用时,在控制台中记录一行或在屏幕上放置一些文本(polyfill 可能会留下一些提示,表明它已启用)。

我无法想象为什么 Chrome 会只加载带有--js-flags="--harmony-simd"的 js simd polyfill,当它已经可以在用户空间完成时就没有意义了?! 这有什么好处。 也许他们会逐渐开始放东西。 你在哪里读到的这是国旗的实际情况,有什么好的链接吗? 看起来这里“正在开发中” https://www.chromestatus.com/features/5757910432874496

编辑:对于实际主题:如果性能从几个对象到很多对象到处都是,我想很难将这些东西放在three.js中。 如果所有实现都可以提高 1 到 N 个对象的性能,那么应该检测到它并在有意义的地方使用它。 如果原生 impls 不一致,我看不到整件事的进展,所以为什么要费心去做,把开发时间花在更高效的事情上。

当它成熟时,三个可以跳过这个,或者三个.js 支持是否可以推动浏览器实现做得更好? 我认为虚幻引擎和其他模拟/数学用例将成为浏览器供应商的驱动力,而不是特别是有多少库想要使用该功能。 但谁知道呢。

无法想象为什么 Chrome 会使用 --js-flags="--harmony-simd" 加载 js simd polyfill

我认为浏览器这样做是一种相当普遍的做法,这样用户就可以开始测试了。 例如,如果我理解正确,这就是最初在浏览器中引入 WASM 的方式。

所有支持百夫长不可避免的论据。 实时监控可以启用或禁用功能并确定最佳性能的性能。 所以即使是阴影贴图密度也应该根据相机距离等变化。无论如何,我知道共识已经决定这将是一个第三方工具,不需要。 我仍然只想将这一点保留在意识中,如果不是潜意识中的话。
也许您只是在检查 pollyfill 并禁用 SIMD,但 FPS 再次说明了一切。 启用或禁用什么的优先级可能最好作为用户/应用程序特定的偏好。 谢谢收听! 我期待在不久的将来更好更快的 GL。 让我们准备好超越其他人。

似乎将数据加载到 SIMD 的过程可能会产生开销,这违背了在 Nightly 中使用 SIMD 的好处。 我对 Chrome 的性能很好奇,但最新的带有真正 SIMD 的 Chromium 在这里http://peterjensen.github.io/idf2014-simd/
它老了。

更新:
现在 SIMD 也适用于 Edge。 您可以通过转到about:flags并选中“启用实验性 JavaScript 功能”(重新启动 Edge)来启用它
不过不确定这是真正的 SIMD 还是 polyfill。 此测试在我的机器上呈现约 40% 的 SIMD 慢:/ https://jsfiddle.net/tk6zx5dm/6/

使用缓存在 Matrix4 对象中的 SIMD 对象的测试变体,不确定这是否有用
https://jsfiddle.net/tk6zx5dm/15/
有趣的是,即使在使用 polyfill SIMD(...?奇怪)的 Chrome 中,缓存 SIMD 对象的代码有时也会更快

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

缓存 - 可能必须在每个 updateMatrix() 上执行,这可能最终会使整个解决方案变慢

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

我很好奇是否重新审视了 ES6 风格? 如果不运行连接器,整个代码现在无法实时使用,那么为什么不运行 babel 并在适当的地方开始使用 ES6 的东西呢?

如果不运行连接器,整个代码现在无法实时使用,那么为什么不运行 babel 并在适当的地方开始使用 ES6 的东西呢?

主要是由于缺乏对 babel 生成代码的性能影响的测试。 另外,我听说 V8 在使用 var 而不是 let/const 时会生成更快的代码。

仅供参考:我最近开始尝试bublé ,它“将自身限制为可以编译为紧凑、高性能的 ES5 的 ES 功能”。

此链接的底部有助于解释 var 与 let in 循环
http://stackoverflow.com/questions/21467642/is-there-a-performance-difference-between-let-and-var
就我个人而言,我正在等待无转译器解决方案进入浏览器。 就像'await'越早越好,但现在也许它应该这样写并运行(被严重毁容)一个转译器,但如果它在Chrome中工作?! 所以测试其他浏览器? 我说“让他们吃蛋糕……或者使用 Chrome。” (我最喜欢的表达)。
我认为如果在最好通过测试证明这样做更好的情况下,应该使用“让”。
我想这就像 'var' 被提升以避免作用域,但你可能想要那个,然后 'let' 是最好的。 我认为/希望“让”在某些情况下也应该使您的内存占用更小。

转译后的代码永远不会像手工优化那样快。 很遗憾 JSPerf 宕机了。 我曾经比谷歌更频繁地访问它。
编辑:JSPerf.com 没有关闭! 我只是假设它在一年不工作后就永远死了
let var在我的 Chrome Canary 中比https :
在 Firefox 和 Edge 中速度没有区别,但 Chrome 是最重要的。
有人可以在 Safari 中测试吗?

课程看起来很棒很现代! 有谁知道这是否已经在计划中?

@Rubinhuang9239我还没有看到有人

让 Chrome Canary 中的 var 比 var 慢 3 倍: https :

就其价值而言,在 Chrome 66、Firefox 59 和 Edge 42 上,使用该测试, letconst现在比var略快。

我认为切换课程应该非常简单 - 主要的工作是采用很久以前完成的汇总。 一个英雄可以在几个小时内在 ThreeJS 中实现类,我不会感到惊讶。

嗯,有很多课程,所以如果你手动完成,可能需要 8 个小时左右。

也许从小处开始,先转换数学课程,然后做 PR。 如果这有效,然后转向其他人。

@looeee已经过去一年多了,所以 ES6 赶上性能也就不足为奇了

2019 年是最终开始在示例/文档中采用一些 ES6 代码的一年,对吗 @mrdoob? 😄

ES6 已经成为标准已经有一段时间了,新的开发人员学习 ES6。 我们也可以停止在示例中支持 IE11,正如你们在 #16220 中讨论的那样,哪些开发人员查看了使用 IE11 的三个.js 示例? 😅

我认为为了简化新手的代码,最需要的功能是类和模板字符串,同时不要忘记现在默认的 const/let。

如果我们决定开始,我可以做出贡献。

一步步。 让我们首先更新示例以现在使用three.module.js

一步步。 让我们首先更新示例以现在使用three.module.js。

这一步已经完成了一段时间。 也许是时候正式进入下一步了?

两位候选人:

  1. 常量/让
  2. 班级

由于类已经在盒子几何中使用了一段时间,我投票赞成首先这样做。 或者我们可以同时进行。

相关:#11552、#18863

如果我理解正确,问题是如果通过示例扩展任何东西,我们无法将其转换为 ES6 类,直到示例也被转换。 这可能意味着等到examples/js消失? 除非我们可以确认modularize脚本将支持类,否则将examples/js文件与其父类同时转换。

据我了解, examples/js是所有多余的功能,虽然很酷,但如果我们都合并到主要的src/... ,它会变得不成比例。 本质上是对“我们是否提供常见创建的 x、y、z 的示例/脚本?”的回答。 我敢猜测,three.js 的回答大多是肯定的,但作为网站内的教育材料。 删除examples/js在那时似乎是不可能的。 虽然我可能误解了examples/js是如何引用/使用的🤔 让我知道。

examples/js作为唯一的网站/教育错过了该文件夹可能是什么的一部分,即社区脚本/内容/项目/人们想要共享的其他内容,但我不知道某个地方正在加倍那。

我离题了。

直到示例也被转换。

我喜欢这个声音作为我们下一个最好的临时步骤。

@DefinitelyMaybe我们没有删除examples/js ,有两个目录值得注意:

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

第一个包含遗留文件,后者包含从这些文件生成的 ES 模块,具有相同的功能。 我们最终将删除第一个。 进行转换的脚本目前不支持 ES 类。 因此,在删除之前, examples/js中的文件无法转换为 ES 类。 其中一些扩展src/ ,并且您不能在不使用 ES 类的情况下扩展 ES 类,因此这是一个阻塞依赖项。

啊,被之前的评论弄糊涂了

这可能意味着等到 examples/js 消失?

现在是有道理的。

moduleize.js 让我想起了我最初将我带到这里的项目。 转换器。 我在这里看到了关于迁移到 ES6 类的评论,所以我想我应该直接跳到这里。

所以如果examples/js以某种方式扩展src两者都需要同时转换为 ES6 类
或者...
在模块化之前工作,直到它生成类/es6?

如果通过示例进行扩展,我们将无法将任何内容转换为 ES6 类

核心中还有很多东西没有在示例中扩展,我们为什么不从这些开始呢?

这对我来说听起来不错。

@Mugen87还有什么阻止 ES 类更改的吗,或者只是这样?

核心中还有很多东西没有在示例中扩展,我们为什么不从这些开始呢?

未通过示例扩展的脚本列表

编辑:列表已更新!

拦截器是这样的部分:

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

使用THREE.<class>.callObject.create( THREE.<class>将是最有可能的模式。 这意味着 Loader、EventDispatcher 和 PerspectiveCamera(可能还有很多其他的)还不能转换为类。

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

好的,我想我们可以从letconst src/

@DefinitelyMaybe这是您想要帮助的事情吗?

🎉 💯 是的!

我只是想提出一个问题,如果您正在加载热代码,我担心 const 会导致问题。 如果在所有 JavaScript 中对象完全覆盖 const 都是正确的,那么没问题。 唉,如果他们不这样做,则永远不应使用所有 const 。 我只是将对象结构与分配给这些对象树(如结构)的键的代码函数合并,因此我在大多数情况下不需要使用 let 或 const 。
无论如何,这是需要考虑的事情,我基本上相信 const 永远不应该被使用,而且真的是 unscary。 主要是因为我对热代码加载的担忧。
我仍然认为它们并不像你想象的那么恒定,所以也许有人理解更多可以解释它对导入重新加载或其他什么毫无意义。 感谢您的考虑和投入。
让有'让'! 最后。

Crockford 说 var 是一个大错误,但无法更改,因此创建了 'let',但认为 var 有缺陷,'let' 的代码应该是对 var 的修复,但它会打破一些编码不佳的边缘情况潜伏在野外。 严格模式和提升是围绕这个主题的问题。

@MasterJames使用 const 时热重载绝对没有问题。

我在 React 环境中工作,热重载是那里的常态,const 和 let 也是当今的标准。

我同意,这不会干扰热重载。 也许您误认为const使用Object.freeze使对象不可变? 我们不打算这样做。

此页面是否有帮助?
0 / 5 - 0 等级