硬核万字长文:我是如何把Skia的体积“缩小”到1/8的?( 八 )


循环一周会发现点 P 永远在左侧 , 而 Q 则有时候在左侧有时候在右侧 。至于左右可以通过向量几何的叉积的正负来判断 。通过这个特性可以判断像素是不是处于多边形的包围中 。
算法中可以通过这个原理构建 SDF 的核函数 。理论上只能对凸多边形有效果 , 其他多边形需要转化成多个凸多边形后依次加以判断(实际上还存在其他问题) 。在判断像素的时候同时需要找到像素距离每个边的最短距离 , 通过这个距离可以控制边缘的一些策略用来抗锯齿 。
Skia 中并未暴露 SDF 相关的策略接口 , 但是在内核代码中存在类似的实现 。
硬核万字长文:我是如何把Skia的体积“缩小”到1/8的?
文章图片

文章图片
上文描述了几个典型的裁剪方式 。理论上需要上层业务进行合理的选择 , 用以达到最佳的性能 , 而不是无脑的 ClipPath 。
和 Skia 的差异
SaveLayers
暂时不觉得需要提供 SaveLayers 这类接口 。
CPU Backend 渲染器
只支持硬件加速渲染 , 尽可能的多支持不同的硬件 。不考虑 CPU Backend , 对普众的消费电子设备显卡应该和 CPU 一样是标配 。不存在 GPU 的设备不在考虑范围内 。
为什么体积会小这么多
主要有以下几个因素
我们实现的渲染器不支持 CPU 软渲染策略 , 一些都是为了硬件加速设计的 , 更加简洁 。
作为 Shader 处理的逻辑 , 核心的编译器相关模块都是离线实现 。同样的 Skia 的 SKSL 编译器需要内置到 Skia 的核心逻辑中难以剥离 。
由于 Skia 的历史非常悠久 , 存在相当多的 legacy 性质的代码和模块 。
总结
至此整个矢量渲染器的核心技术就已经描述完毕 。每个部分单独实现难度并不大 , 但是集合起来构建一个完备的项目还是太“顶”了 。如果你也想实现一个类似的渲染器 , 那么祝你好运 。
关于渲染器的未来使用场景
跨平台
这个方向毋庸置疑 , 未来类似 Flutter 这样的跨多端的会慢慢变成主流(多年前笔者从事 Windows 开发 , 就是先用系统的渲染器绘制一套 UI 体系 , 然后在上面做各种业务 。Flutter 在移动端算一个新东西 , 但是业界早有类似的解决方案) , 那么构建适合自己业务的渲染引擎非常有必要 , 也是技术实力的体现 。
Mini 浏览器
随着前端的敏捷的开发方式慢慢在整个行业得到接受 , 国内有众多尝试在 系统原生组件或者 Flutter 上构建类似浏览器的逻辑(远不如浏览器那么复杂) 。我把这类项目称为 Mini 浏览器项目 , 那么渲染器可以最大化减少包体积 , 提高渲染性能 。
天下没有免费的午餐 , 没有哪一个硬件渲染器能够保证 , 随意使用其 API 就能得到好的性能 。Flutter 本身也因为过多使用 Skia 的 ClipPath 和 SaveLayers 导致性能低下 。对渲染本身足够理解、对硬件的足够理解 , 知己知彼才能做到最好 。
混合渲染
纵观全文 , 我都致力于把二维渲染实时转化成由三角形构成的 Mesh 。那么 3D 游戏为什么可以在渲染复杂的场景下提供好的性能?原因在于 3D 游戏中使用的 3D 模型大多都是通过 “3DMax” “Maya” “Blender”这里建模工具离线构建的 。
从三角形的 Mesh 角度来说 , 2D 和 3D 没有本质区别 , 所以可以混合到一起渲染 。这会带来一些新的原来不具备的特性 。移动设备时至今日运算能力已经很强了 , 但是交互方式却没有大的变化 , 随着混合模式下的渲染会带来更加新颖的体验的交互模式 。
作者介绍
陈国栋 , 主要从事多端跨平台、计算机图形学、编译器、高并发、分布式共识和一致性的研究和实践 。曾在腾讯、百度、蘑菇街、爱奇艺等公司任职 。目前就职于字节跳动 Client Infra 团队 。我所在的团队对外负责的技术产品有 Lynx(移动端动态化跨平台引擎)、JavaScript 虚拟机、浏览器内核、自渲染框架内核等 。欢迎有意向在以上几个方向参与研究和研发的同学加入我们 。