最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • React 优化技巧在 Web 版光线追踪里的应用(上)

    正文概述 掘金(工业聚)   2020-12-24   347

    我在使用 Web 技术去实践 Ray Tracing 相关的知识的时候,遇到了很多问题。

    在克服了那些问题后,我发现,它跟 React 优化技巧如出一辙(这里的 React 优化技巧,不是指优化用 React 实现的 Web APP 的技巧,而是 React 内部实现中包含的优化技巧)。

    与其说是 React 优化技巧在 Web 版光线追踪里的应用。其实不如说,UI 渲染的优化技巧,在 React ,Ray Tracing 还是其它 UI 平台,是通用的。

    只是闻道有先后,我个人先有了 React 背景,再去学习 Ray Tracing,故有此标题。如果反过来,则是《Ray Tracing 优化技巧在 React 里的应用》了。

    接下来,我们来一一例举遇到的问题及其解决方案吧。

    问题:Operator Overloading

    JavaScript 还没有 C++ 等语言里的操作符重载特性,在编写向量、矩阵计算时,代码既繁琐,又不直观。

    在 C++ 里,color 函数写起来是这样的。

    React 优化技巧在 Web 版光线追踪里的应用(上)

    数字跟向量相乘,只需要用 * 号即可。然而在 JS 里你得这样写:

    React 优化技巧在 Web 版光线追踪里的应用(上)

    在 JS 里,+-/* 不能用在 Float32Array 等非数值类型上。我们只好抽象成 add, sub, mul, div 等计算函数。写起来索然无味,调试起来也异常痛苦。

    那么,如何克服这个问题?

    解决方案:Babel Plugin

    目前可以搜索到几个 Babel Plugin 能让 JS 支持操作符重载,但它们都有各自的问题。

    比如:babel-plugin-overload,它的思路是参考 Python,在 JS 里用 Symbol.for('+') 表示 overloading。

    React 优化技巧在 Web 版光线追踪里的应用(上)

    它的原理是,把所有 +-/* 代码都编译成下面这样:

    React 优化技巧在 Web 版光线追踪里的应用(上)

    四则运算表达式,变成了匿名函数表达式。检查 left 是否包含重载属性。

    它的完成度很低。既不能处理 number * vector 这种 left 值为数字的情况,还有非常严重的性能问题,每次执行都会创建一个匿名函数。基本上是不可用的。

    另一个是,operator-overloading-js,年代更久远,连 Symbol 都没用,使用的是 __plus 这种约定做法。

    React 优化技巧在 Web 版光线追踪里的应用(上)

    它的思路是,在运行时解析函数的 AST,然后编译和生成新的函数并执行它。

    使用它意味着我们会依赖 esprima,escodegen,分别用来解析代码和生成代码。这部分体积不小。

    并且,因为它生成新的函数,我们的函数内部就不能随意访问闭包里的变量。这基本告别了 ES2016 模块写法,因为顶部的 import 语句引入的变量,对于模块内的函数来说,就是闭包里的变量。在它的示例里,模块写法都是 commonjs 的。

    React 优化技巧在 Web 版光线追踪里的应用(上)

    如上图所示,overload 函数包裹了几乎所有代码。它的运行时开销,会随着代码规模的增加而增加。总体而言得不偿失。

    考察了多个方案后,我没有成功找到可以直接使用的方案。因此,我亲自动手写了一个 babel plugin,发现它其实可以非常简单。

    在我的场景里,只用到了几十行代码,如下所示:

    React 优化技巧在 Web 版光线追踪里的应用(上)

    它做的事情非常简单,就是把 +-*/ 的表达式,按照 mapping 关系,替换成 add, sub, muldiv 四个函数调用。把 left, right 的操作值,作为参数传入。

    如此,我们只需要实现四个 runtime-helper 函数,就可以自定义 +-*/ 的行为了。

    React 优化技巧在 Web 版光线追踪里的应用(上)

    比如我们为3个维度的向量实现相加的行为,首先判断是不是向量,不是向量就直接 return left + right,走默认行为的分支。如果是,则归一化为两个向量,然后用 gl-matrix 里提供的方法进行相加操作。

    sub, muldiv 的代码几乎一样,只是调用不同的 vec3 方法罢了。

    这里只展示了 vector 的部分,没有涉及 matrix,因为恰好我目前的场景里用不到 matrix。如有需要,添加起来也很容易,多一个判断分支而已。我们还可以做成插件注册机制。

    React 优化技巧在 Web 版光线追踪里的应用(上)

    overloading 内部会根据注册的插件,构造出对应的 runtime-helper,依次检测出匹配的插件,调用它的处理函数即可。

    使用效果,我们可以写直观的代码,不用再管四则运算的类型跟 left, right 顺序:

    React 优化技巧在 Web 版光线追踪里的应用(上)

    Babel 插件把它编译成:

    React 优化技巧在 Web 版光线追踪里的应用(上)

    跟我们最初的代码进行对比:

    React 优化技巧在 Web 版光线追踪里的应用(上)

    只看 return 语句,我们会发现,它的编译结果,跟最初我们手写,总体上是一致的。这正是我们想要的效果,我们得到了跟我们手写一样的结果,但我们实际写的是更简洁直观的代码。

    问题:Blocking The Main UI Thread

    使用 Web 技术来学习和实现光线追踪或者 3D 图形渲染,最吸引人的优势是,我们可以很容易地在浏览器里部署和浏览效果。

    然而,像光线追踪这种高度耗费运算量的算法,它需要长时间计算,才能得出结果。如果采用同步计算,它会卡住主线程,页面无法交互,甚至难以关闭。

    React 优化技巧在 Web 版光线追踪里的应用(上)

    上面这幅图渲染了 500+ 小球到 800 * 400 的分辨率中,使用 node.js v8.9.4,渲染了近 2 小时。即便减少小球,只用 20 来个,也得十几分钟。

    如此,即便我们解决了 JS 没有 operator overloading 的问题,也无济于事。没人想看一个会卡死浏览器的光线追踪 DEMO。

    我们得想办法解决这个问题。

    具体如何解决,请看下回分解。后面我将介绍 Time Slicing 和 Streaming Rendering 优化策略。


    起源地下载网 » React 优化技巧在 Web 版光线追踪里的应用(上)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元